1 /* Target machine subroutines for Altera Nios II.
2 Copyright (C) 2012-2022 Free Software Foundation, Inc.
3 Contributed by Jonah Graham (jgraham@altera.com),
4 Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@altera.com).
5 Contributed by Mentor Graphics, Inc.
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published
11 by the Free Software Foundation; either version 3, or (at your
12 option) any later version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
22
23 #define IN_TARGET_CODE 1
24
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "target.h"
30 #include "rtl.h"
31 #include "tree.h"
32 #include "stringpool.h"
33 #include "attribs.h"
34 #include "df.h"
35 #include "memmodel.h"
36 #include "tm_p.h"
37 #include "optabs.h"
38 #include "regs.h"
39 #include "emit-rtl.h"
40 #include "recog.h"
41 #include "diagnostic-core.h"
42 #include "output.h"
43 #include "insn-attr.h"
44 #include "flags.h"
45 #include "explow.h"
46 #include "calls.h"
47 #include "varasm.h"
48 #include "expr.h"
49 #include "toplev.h"
50 #include "langhooks.h"
51 #include "stor-layout.h"
52 #include "builtins.h"
53 #include "tree-pass.h"
54 #include "xregex.h"
55 #include "opts.h"
56
57 /* This file should be included last. */
58 #include "target-def.h"
59
60 /* Forward function declarations. */
61 static bool nios2_symbolic_constant_p (rtx);
62 static bool prologue_saved_reg_p (unsigned);
63 static void nios2_load_pic_register (void);
64 static void nios2_register_custom_code (unsigned int, enum nios2_ccs_code, int);
65 static const char *nios2_unspec_reloc_name (int);
66 static void nios2_register_builtin_fndecl (unsigned, tree);
67 static rtx nios2_ldst_parallel (bool, bool, bool, rtx, int,
68 unsigned HOST_WIDE_INT, bool);
69 static int nios2_address_cost (rtx, machine_mode, addr_space_t, bool);
70
71 /* Threshold for data being put into the small data/bss area, instead
72 of the normal data area (references to the small data/bss area take
73 1 instruction, and use the global pointer, references to the normal
74 data area takes 2 instructions). */
75 unsigned HOST_WIDE_INT nios2_section_threshold = NIOS2_DEFAULT_GVALUE;
76
77 struct GTY (()) machine_function
78 {
79 /* Current frame information, to be filled in by nios2_compute_frame_layout
80 with register save masks, and offsets for the current function. */
81
82 /* Mask of registers to save. */
83 unsigned int save_mask;
84 /* Number of bytes that the entire frame takes up. */
85 int total_size;
86 /* Number of bytes that variables take up. */
87 int var_size;
88 /* Number of bytes that outgoing arguments take up. */
89 int args_size;
90 /* Number of bytes needed to store registers in frame. */
91 int save_reg_size;
92 /* Number of bytes used to store callee-saved registers. */
93 int callee_save_reg_size;
94 /* Offset from new stack pointer to store registers. */
95 int save_regs_offset;
96 /* Offset from save_regs_offset to store frame pointer register. */
97 int fp_save_offset;
98 /* != 0 if function has a variable argument list. */
99 int uses_anonymous_args;
100 /* != 0 if frame layout already calculated. */
101 int initialized;
102 };
103
104 /* State to track the assignment of custom codes to FPU/custom builtins. */
105 static enum nios2_ccs_code custom_code_status[256];
106 static int custom_code_index[256];
107 /* Set to true if any conflicts (re-use of a code between 0-255) are found. */
108 static bool custom_code_conflict = false;
109
110 /* State for command-line options. */
111 regex_t nios2_gprel_sec_regex;
112 regex_t nios2_r0rel_sec_regex;
113
114
115 /* Definition of builtin function types for nios2. */
116
117 #define N2_FTYPES \
118 N2_FTYPE(1, (SF)) \
119 N2_FTYPE(1, (VOID)) \
120 N2_FTYPE(2, (DF, DF)) \
121 N2_FTYPE(3, (DF, DF, DF)) \
122 N2_FTYPE(2, (DF, SF)) \
123 N2_FTYPE(2, (DF, SI)) \
124 N2_FTYPE(2, (DF, UI)) \
125 N2_FTYPE(2, (SF, DF)) \
126 N2_FTYPE(2, (SF, SF)) \
127 N2_FTYPE(3, (SF, SF, SF)) \
128 N2_FTYPE(2, (SF, SI)) \
129 N2_FTYPE(2, (SF, UI)) \
130 N2_FTYPE(2, (SI, CVPTR)) \
131 N2_FTYPE(2, (SI, DF)) \
132 N2_FTYPE(3, (SI, DF, DF)) \
133 N2_FTYPE(2, (SI, SF)) \
134 N2_FTYPE(3, (SI, SF, SF)) \
135 N2_FTYPE(2, (SI, SI)) \
136 N2_FTYPE(3, (SI, SI, SI)) \
137 N2_FTYPE(3, (SI, VPTR, SI)) \
138 N2_FTYPE(2, (UI, CVPTR)) \
139 N2_FTYPE(2, (UI, DF)) \
140 N2_FTYPE(2, (UI, SF)) \
141 N2_FTYPE(2, (VOID, DF)) \
142 N2_FTYPE(2, (VOID, SF)) \
143 N2_FTYPE(2, (VOID, SI)) \
144 N2_FTYPE(3, (VOID, SI, SI)) \
145 N2_FTYPE(2, (VOID, VPTR)) \
146 N2_FTYPE(3, (VOID, VPTR, SI))
147
148 #define N2_FTYPE_OP1(R) N2_FTYPE_ ## R ## _VOID
149 #define N2_FTYPE_OP2(R, A1) N2_FTYPE_ ## R ## _ ## A1
150 #define N2_FTYPE_OP3(R, A1, A2) N2_FTYPE_ ## R ## _ ## A1 ## _ ## A2
151
152 /* Expand ftcode enumeration. */
153 enum nios2_ftcode {
154 #define N2_FTYPE(N,ARGS) N2_FTYPE_OP ## N ARGS,
155 N2_FTYPES
156 #undef N2_FTYPE
157 N2_FTYPE_MAX
158 };
159
160 /* Return the tree function type, based on the ftcode. */
161 static tree
nios2_ftype(enum nios2_ftcode ftcode)162 nios2_ftype (enum nios2_ftcode ftcode)
163 {
164 static tree types[(int) N2_FTYPE_MAX];
165
166 tree N2_TYPE_SF = float_type_node;
167 tree N2_TYPE_DF = double_type_node;
168 tree N2_TYPE_SI = integer_type_node;
169 tree N2_TYPE_UI = unsigned_type_node;
170 tree N2_TYPE_VOID = void_type_node;
171
172 static const_tree N2_TYPE_CVPTR, N2_TYPE_VPTR;
173 if (!N2_TYPE_CVPTR)
174 {
175 /* const volatile void *. */
176 N2_TYPE_CVPTR
177 = build_pointer_type (build_qualified_type (void_type_node,
178 (TYPE_QUAL_CONST
179 | TYPE_QUAL_VOLATILE)));
180 /* volatile void *. */
181 N2_TYPE_VPTR
182 = build_pointer_type (build_qualified_type (void_type_node,
183 TYPE_QUAL_VOLATILE));
184 }
185 if (types[(int) ftcode] == NULL_TREE)
186 switch (ftcode)
187 {
188 #define N2_FTYPE_ARGS1(R) N2_TYPE_ ## R
189 #define N2_FTYPE_ARGS2(R,A1) N2_TYPE_ ## R, N2_TYPE_ ## A1
190 #define N2_FTYPE_ARGS3(R,A1,A2) N2_TYPE_ ## R, N2_TYPE_ ## A1, N2_TYPE_ ## A2
191 #define N2_FTYPE(N,ARGS) \
192 case N2_FTYPE_OP ## N ARGS: \
193 types[(int) ftcode] \
194 = build_function_type_list (N2_FTYPE_ARGS ## N ARGS, NULL_TREE); \
195 break;
196 N2_FTYPES
197 #undef N2_FTYPE
198 default: gcc_unreachable ();
199 }
200 return types[(int) ftcode];
201 }
202
203
204 /* Definition of FPU instruction descriptions. */
205
206 struct nios2_fpu_insn_info
207 {
208 const char *name;
209 int num_operands, *optvar;
210 int opt, no_opt;
211 #define N2F_DF 0x1
212 #define N2F_DFREQ 0x2
213 #define N2F_UNSAFE 0x4
214 #define N2F_FINITE 0x8
215 #define N2F_NO_ERRNO 0x10
216 unsigned int flags;
217 enum insn_code icode;
218 enum nios2_ftcode ftcode;
219 };
220
221 /* Base macro for defining FPU instructions. */
222 #define N2FPU_INSN_DEF_BASE(insn, nop, flags, icode, args) \
223 { #insn, nop, &nios2_custom_ ## insn, OPT_mcustom_##insn##_, \
224 OPT_mno_custom_##insn, flags, CODE_FOR_ ## icode, \
225 N2_FTYPE_OP ## nop args }
226
227 /* Arithmetic and math functions; 2 or 3 operand FP operations. */
228 #define N2FPU_OP2(mode) (mode, mode)
229 #define N2FPU_OP3(mode) (mode, mode, mode)
230 #define N2FPU_INSN_DEF(code, icode, nop, flags, m, M) \
231 N2FPU_INSN_DEF_BASE (f ## code ## m, nop, flags, \
232 icode ## m ## f ## nop, N2FPU_OP ## nop (M ## F))
233 #define N2FPU_INSN_SF(code, nop, flags) \
234 N2FPU_INSN_DEF (code, code, nop, flags, s, S)
235 #define N2FPU_INSN_DF(code, nop, flags) \
236 N2FPU_INSN_DEF (code, code, nop, flags | N2F_DF, d, D)
237
238 /* Compare instructions, 3 operand FP operation with a SI result. */
239 #define N2FPU_CMP_DEF(code, flags, m, M) \
240 N2FPU_INSN_DEF_BASE (fcmp ## code ## m, 3, flags, \
241 nios2_s ## code ## m ## f, (SI, M ## F, M ## F))
242 #define N2FPU_CMP_SF(code) N2FPU_CMP_DEF (code, 0, s, S)
243 #define N2FPU_CMP_DF(code) N2FPU_CMP_DEF (code, N2F_DF, d, D)
244
245 /* The order of definition needs to be maintained consistent with
246 enum n2fpu_code in nios2-opts.h. */
247 struct nios2_fpu_insn_info nios2_fpu_insn[] =
248 {
249 /* Single precision instructions. */
250 N2FPU_INSN_SF (add, 3, 0),
251 N2FPU_INSN_SF (sub, 3, 0),
252 N2FPU_INSN_SF (mul, 3, 0),
253 N2FPU_INSN_SF (div, 3, 0),
254 /* Due to textual difference between min/max and smin/smax. */
255 N2FPU_INSN_DEF (min, smin, 3, N2F_FINITE, s, S),
256 N2FPU_INSN_DEF (max, smax, 3, N2F_FINITE, s, S),
257 N2FPU_INSN_SF (neg, 2, 0),
258 N2FPU_INSN_SF (abs, 2, 0),
259 N2FPU_INSN_SF (sqrt, 2, 0),
260 N2FPU_INSN_SF (sin, 2, N2F_UNSAFE),
261 N2FPU_INSN_SF (cos, 2, N2F_UNSAFE),
262 N2FPU_INSN_SF (tan, 2, N2F_UNSAFE),
263 N2FPU_INSN_SF (atan, 2, N2F_UNSAFE),
264 N2FPU_INSN_SF (exp, 2, N2F_UNSAFE),
265 N2FPU_INSN_SF (log, 2, N2F_UNSAFE),
266 /* Single precision compares. */
267 N2FPU_CMP_SF (eq), N2FPU_CMP_SF (ne),
268 N2FPU_CMP_SF (lt), N2FPU_CMP_SF (le),
269 N2FPU_CMP_SF (gt), N2FPU_CMP_SF (ge),
270
271 /* Double precision instructions. */
272 N2FPU_INSN_DF (add, 3, 0),
273 N2FPU_INSN_DF (sub, 3, 0),
274 N2FPU_INSN_DF (mul, 3, 0),
275 N2FPU_INSN_DF (div, 3, 0),
276 /* Due to textual difference between min/max and smin/smax. */
277 N2FPU_INSN_DEF (min, smin, 3, N2F_FINITE, d, D),
278 N2FPU_INSN_DEF (max, smax, 3, N2F_FINITE, d, D),
279 N2FPU_INSN_DF (neg, 2, 0),
280 N2FPU_INSN_DF (abs, 2, 0),
281 N2FPU_INSN_DF (sqrt, 2, 0),
282 N2FPU_INSN_DF (sin, 2, N2F_UNSAFE),
283 N2FPU_INSN_DF (cos, 2, N2F_UNSAFE),
284 N2FPU_INSN_DF (tan, 2, N2F_UNSAFE),
285 N2FPU_INSN_DF (atan, 2, N2F_UNSAFE),
286 N2FPU_INSN_DF (exp, 2, N2F_UNSAFE),
287 N2FPU_INSN_DF (log, 2, N2F_UNSAFE),
288 /* Double precision compares. */
289 N2FPU_CMP_DF (eq), N2FPU_CMP_DF (ne),
290 N2FPU_CMP_DF (lt), N2FPU_CMP_DF (le),
291 N2FPU_CMP_DF (gt), N2FPU_CMP_DF (ge),
292
293 /* Conversion instructions. */
294 N2FPU_INSN_DEF_BASE (floatis, 2, 0, floatsisf2, (SF, SI)),
295 N2FPU_INSN_DEF_BASE (floatus, 2, 0, floatunssisf2, (SF, UI)),
296 N2FPU_INSN_DEF_BASE (floatid, 2, 0, floatsidf2, (DF, SI)),
297 N2FPU_INSN_DEF_BASE (floatud, 2, 0, floatunssidf2, (DF, UI)),
298 N2FPU_INSN_DEF_BASE (round, 2, N2F_NO_ERRNO, lroundsfsi2, (SI, SF)),
299 N2FPU_INSN_DEF_BASE (fixsi, 2, 0, fix_truncsfsi2, (SI, SF)),
300 N2FPU_INSN_DEF_BASE (fixsu, 2, 0, fixuns_truncsfsi2, (UI, SF)),
301 N2FPU_INSN_DEF_BASE (fixdi, 2, 0, fix_truncdfsi2, (SI, DF)),
302 N2FPU_INSN_DEF_BASE (fixdu, 2, 0, fixuns_truncdfsi2, (UI, DF)),
303 N2FPU_INSN_DEF_BASE (fextsd, 2, 0, extendsfdf2, (DF, SF)),
304 N2FPU_INSN_DEF_BASE (ftruncds, 2, 0, truncdfsf2, (SF, DF)),
305
306 /* X, Y access instructions. */
307 N2FPU_INSN_DEF_BASE (fwrx, 2, N2F_DFREQ, nios2_fwrx, (VOID, DF)),
308 N2FPU_INSN_DEF_BASE (fwry, 2, N2F_DFREQ, nios2_fwry, (VOID, SF)),
309 N2FPU_INSN_DEF_BASE (frdxlo, 1, N2F_DFREQ, nios2_frdxlo, (SF)),
310 N2FPU_INSN_DEF_BASE (frdxhi, 1, N2F_DFREQ, nios2_frdxhi, (SF)),
311 N2FPU_INSN_DEF_BASE (frdy, 1, N2F_DFREQ, nios2_frdy, (SF))
312 };
313
314 /* Some macros for ease of access. */
315 #define N2FPU(code) nios2_fpu_insn[(int) code]
316 #define N2FPU_ENABLED_P(code) (N2FPU_N(code) >= 0)
317 #define N2FPU_N(code) (*N2FPU(code).optvar)
318 #define N2FPU_NAME(code) (N2FPU(code).name)
319 #define N2FPU_ICODE(code) (N2FPU(code).icode)
320 #define N2FPU_FTCODE(code) (N2FPU(code).ftcode)
321 #define N2FPU_FINITE_P(code) (N2FPU(code).flags & N2F_FINITE)
322 #define N2FPU_UNSAFE_P(code) (N2FPU(code).flags & N2F_UNSAFE)
323 #define N2FPU_NO_ERRNO_P(code) (N2FPU(code).flags & N2F_NO_ERRNO)
324 #define N2FPU_DOUBLE_P(code) (N2FPU(code).flags & N2F_DF)
325 #define N2FPU_DOUBLE_REQUIRED_P(code) (N2FPU(code).flags & N2F_DFREQ)
326
327 /* Same as above, but for cases where using only the op part is shorter. */
328 #define N2FPU_OP(op) N2FPU(n2fpu_ ## op)
329 #define N2FPU_OP_NAME(op) N2FPU_NAME(n2fpu_ ## op)
330 #define N2FPU_OP_ENABLED_P(op) N2FPU_ENABLED_P(n2fpu_ ## op)
331
332 /* Export the FPU insn enabled predicate to nios2.md. */
333 bool
nios2_fpu_insn_enabled(enum n2fpu_code code)334 nios2_fpu_insn_enabled (enum n2fpu_code code)
335 {
336 return N2FPU_ENABLED_P (code);
337 }
338
339 /* Return true if COND comparison for mode MODE is enabled under current
340 settings. */
341
342 static bool
nios2_fpu_compare_enabled(enum rtx_code cond,machine_mode mode)343 nios2_fpu_compare_enabled (enum rtx_code cond, machine_mode mode)
344 {
345 if (mode == SFmode)
346 switch (cond)
347 {
348 case EQ: return N2FPU_OP_ENABLED_P (fcmpeqs);
349 case NE: return N2FPU_OP_ENABLED_P (fcmpnes);
350 case GT: return N2FPU_OP_ENABLED_P (fcmpgts);
351 case GE: return N2FPU_OP_ENABLED_P (fcmpges);
352 case LT: return N2FPU_OP_ENABLED_P (fcmplts);
353 case LE: return N2FPU_OP_ENABLED_P (fcmples);
354 default: break;
355 }
356 else if (mode == DFmode)
357 switch (cond)
358 {
359 case EQ: return N2FPU_OP_ENABLED_P (fcmpeqd);
360 case NE: return N2FPU_OP_ENABLED_P (fcmpned);
361 case GT: return N2FPU_OP_ENABLED_P (fcmpgtd);
362 case GE: return N2FPU_OP_ENABLED_P (fcmpged);
363 case LT: return N2FPU_OP_ENABLED_P (fcmpltd);
364 case LE: return N2FPU_OP_ENABLED_P (fcmpled);
365 default: break;
366 }
367 return false;
368 }
369
370 /* Stack layout and calling conventions. */
371
372 #define NIOS2_STACK_ALIGN(LOC) \
373 (((LOC) + ((PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) - 1)) \
374 & ~((PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) - 1))
375
376 /* Return the bytes needed to compute the frame pointer from the current
377 stack pointer. */
378 static int
nios2_compute_frame_layout(void)379 nios2_compute_frame_layout (void)
380 {
381 unsigned int regno;
382 unsigned int save_mask = 0;
383 int total_size;
384 int var_size;
385 int out_args_size;
386 int save_reg_size;
387 int callee_save_reg_size;
388
389 if (cfun->machine->initialized)
390 return cfun->machine->total_size;
391
392 /* Calculate space needed for gp registers. */
393 save_reg_size = 0;
394 for (regno = 0; regno <= LAST_GP_REG; regno++)
395 if (prologue_saved_reg_p (regno))
396 {
397 save_mask |= 1 << regno;
398 save_reg_size += 4;
399 }
400
401 /* If we are saving any callee-save register, then assume
402 push.n/pop.n should be used. Make sure RA is saved, and
403 contiguous registers starting from r16-- are all saved. */
404 if (TARGET_HAS_CDX && save_reg_size != 0)
405 {
406 if ((save_mask & (1 << RA_REGNO)) == 0)
407 {
408 save_mask |= 1 << RA_REGNO;
409 save_reg_size += 4;
410 }
411
412 for (regno = 23; regno >= 16; regno--)
413 if ((save_mask & (1 << regno)) != 0)
414 {
415 /* Starting from highest numbered callee-saved
416 register that is used, make sure all regs down
417 to r16 is saved, to maintain contiguous range
418 for push.n/pop.n. */
419 unsigned int i;
420 for (i = regno - 1; i >= 16; i--)
421 if ((save_mask & (1 << i)) == 0)
422 {
423 save_mask |= 1 << i;
424 save_reg_size += 4;
425 }
426 break;
427 }
428 }
429
430 callee_save_reg_size = save_reg_size;
431
432 /* If we call eh_return, we need to save the EH data registers. */
433 if (crtl->calls_eh_return)
434 {
435 unsigned i;
436 unsigned r;
437
438 for (i = 0; (r = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++)
439 if (!(save_mask & (1 << r)))
440 {
441 save_mask |= 1 << r;
442 save_reg_size += 4;
443 }
444 }
445
446 cfun->machine->fp_save_offset = 0;
447 if (save_mask & (1 << HARD_FRAME_POINTER_REGNUM))
448 {
449 int fp_save_offset = 0;
450 for (regno = 0; regno < HARD_FRAME_POINTER_REGNUM; regno++)
451 if (save_mask & (1 << regno))
452 fp_save_offset += 4;
453
454 cfun->machine->fp_save_offset = fp_save_offset;
455 }
456
457 var_size = NIOS2_STACK_ALIGN (get_frame_size ());
458 out_args_size = NIOS2_STACK_ALIGN (crtl->outgoing_args_size);
459 total_size = var_size + out_args_size;
460
461 save_reg_size = NIOS2_STACK_ALIGN (save_reg_size);
462 total_size += save_reg_size;
463 total_size += NIOS2_STACK_ALIGN (crtl->args.pretend_args_size);
464
465 /* Save other computed information. */
466 cfun->machine->save_mask = save_mask;
467 cfun->machine->total_size = total_size;
468 cfun->machine->var_size = var_size;
469 cfun->machine->args_size = out_args_size;
470 cfun->machine->save_reg_size = save_reg_size;
471 cfun->machine->callee_save_reg_size = callee_save_reg_size;
472 cfun->machine->initialized = reload_completed;
473 cfun->machine->save_regs_offset = out_args_size + var_size;
474
475 return total_size;
476 }
477
478 /* Generate save/restore of register REGNO at SP + OFFSET. Used by the
479 prologue/epilogue expand routines. */
480 static void
save_reg(int regno,unsigned offset)481 save_reg (int regno, unsigned offset)
482 {
483 rtx reg = gen_rtx_REG (SImode, regno);
484 rtx addr = plus_constant (Pmode, stack_pointer_rtx, offset, false);
485 rtx_insn *insn = emit_move_insn (gen_frame_mem (Pmode, addr), reg);
486 RTX_FRAME_RELATED_P (insn) = 1;
487 }
488
489 static void
restore_reg(int regno,unsigned offset)490 restore_reg (int regno, unsigned offset)
491 {
492 rtx reg = gen_rtx_REG (SImode, regno);
493 rtx addr = plus_constant (Pmode, stack_pointer_rtx, offset, false);
494 rtx_insn *insn = emit_move_insn (reg, gen_frame_mem (Pmode, addr));
495 /* Tag epilogue unwind note. */
496 add_reg_note (insn, REG_CFA_RESTORE, reg);
497 RTX_FRAME_RELATED_P (insn) = 1;
498 }
499
500 /* This routine tests for the base register update SET in load/store
501 multiple RTL insns, used in pop_operation_p and ldstwm_operation_p. */
502 static bool
base_reg_adjustment_p(rtx set,rtx * base_reg,rtx * offset)503 base_reg_adjustment_p (rtx set, rtx *base_reg, rtx *offset)
504 {
505 if (GET_CODE (set) == SET
506 && REG_P (SET_DEST (set))
507 && GET_CODE (SET_SRC (set)) == PLUS
508 && REG_P (XEXP (SET_SRC (set), 0))
509 && rtx_equal_p (SET_DEST (set), XEXP (SET_SRC (set), 0))
510 && CONST_INT_P (XEXP (SET_SRC (set), 1)))
511 {
512 *base_reg = XEXP (SET_SRC (set), 0);
513 *offset = XEXP (SET_SRC (set), 1);
514 return true;
515 }
516 return false;
517 }
518
519 /* Does the CFA note work for push/pop prologue/epilogue instructions. */
520 static void
nios2_create_cfa_notes(rtx_insn * insn,bool epilogue_p)521 nios2_create_cfa_notes (rtx_insn *insn, bool epilogue_p)
522 {
523 int i = 0;
524 rtx base_reg, offset, elt, pat = PATTERN (insn);
525 if (epilogue_p)
526 {
527 elt = XVECEXP (pat, 0, 0);
528 if (GET_CODE (elt) == RETURN)
529 i++;
530 elt = XVECEXP (pat, 0, i);
531 if (base_reg_adjustment_p (elt, &base_reg, &offset))
532 {
533 add_reg_note (insn, REG_CFA_ADJUST_CFA, copy_rtx (elt));
534 i++;
535 }
536 for (; i < XVECLEN (pat, 0); i++)
537 {
538 elt = SET_DEST (XVECEXP (pat, 0, i));
539 gcc_assert (REG_P (elt));
540 add_reg_note (insn, REG_CFA_RESTORE, elt);
541 }
542 }
543 else
544 {
545 /* Tag each of the prologue sets. */
546 for (i = 0; i < XVECLEN (pat, 0); i++)
547 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, i)) = 1;
548 }
549 }
550
551 /* Temp regno used inside prologue/epilogue. */
552 #define TEMP_REG_NUM 8
553
554 /* Emit conditional trap for checking stack limit. SIZE is the number of
555 additional bytes required.
556
557 GDB prologue analysis depends on this generating a direct comparison
558 to the SP register, so the adjustment to add SIZE needs to be done on
559 the other operand to the comparison. Use TEMP_REG_NUM as a temporary,
560 if necessary. */
561 static void
nios2_emit_stack_limit_check(int size)562 nios2_emit_stack_limit_check (int size)
563 {
564 rtx sum = NULL_RTX;
565
566 if (GET_CODE (stack_limit_rtx) == SYMBOL_REF)
567 {
568 /* This generates a %hiadj/%lo pair with the constant size
569 add handled by the relocations. */
570 sum = gen_rtx_REG (Pmode, TEMP_REG_NUM);
571 emit_move_insn (sum, plus_constant (Pmode, stack_limit_rtx, size));
572 }
573 else if (!REG_P (stack_limit_rtx))
574 sorry ("Unknown form for stack limit expression");
575 else if (size == 0)
576 sum = stack_limit_rtx;
577 else if (SMALL_INT (size))
578 {
579 sum = gen_rtx_REG (Pmode, TEMP_REG_NUM);
580 emit_move_insn (sum, plus_constant (Pmode, stack_limit_rtx, size));
581 }
582 else
583 {
584 sum = gen_rtx_REG (Pmode, TEMP_REG_NUM);
585 emit_move_insn (sum, gen_int_mode (size, Pmode));
586 emit_insn (gen_add2_insn (sum, stack_limit_rtx));
587 }
588
589 emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode, stack_pointer_rtx, sum),
590 stack_pointer_rtx, sum, GEN_INT (3)));
591 }
592
593 static rtx_insn *
nios2_emit_add_constant(rtx reg,HOST_WIDE_INT immed)594 nios2_emit_add_constant (rtx reg, HOST_WIDE_INT immed)
595 {
596 rtx_insn *insn;
597 if (SMALL_INT (immed))
598 insn = emit_insn (gen_add2_insn (reg, gen_int_mode (immed, Pmode)));
599 else
600 {
601 rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
602 emit_move_insn (tmp, gen_int_mode (immed, Pmode));
603 insn = emit_insn (gen_add2_insn (reg, tmp));
604 }
605 return insn;
606 }
607
608 static rtx_insn *
nios2_adjust_stack(int sp_adjust,bool epilogue_p)609 nios2_adjust_stack (int sp_adjust, bool epilogue_p)
610 {
611 enum reg_note note_kind = REG_NOTE_MAX;
612 rtx_insn *insn = NULL;
613 if (sp_adjust)
614 {
615 if (SMALL_INT (sp_adjust))
616 insn = emit_insn (gen_add2_insn (stack_pointer_rtx,
617 gen_int_mode (sp_adjust, Pmode)));
618 else
619 {
620 rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
621 emit_move_insn (tmp, gen_int_mode (sp_adjust, Pmode));
622 insn = emit_insn (gen_add2_insn (stack_pointer_rtx, tmp));
623 /* Attach a note indicating what happened. */
624 if (!epilogue_p)
625 note_kind = REG_FRAME_RELATED_EXPR;
626 }
627 if (epilogue_p)
628 note_kind = REG_CFA_ADJUST_CFA;
629 if (note_kind != REG_NOTE_MAX)
630 {
631 rtx cfa_adj = gen_rtx_SET (stack_pointer_rtx,
632 plus_constant (Pmode, stack_pointer_rtx,
633 sp_adjust));
634 add_reg_note (insn, note_kind, cfa_adj);
635 }
636 RTX_FRAME_RELATED_P (insn) = 1;
637 }
638 return insn;
639 }
640
641 void
nios2_expand_prologue(void)642 nios2_expand_prologue (void)
643 {
644 unsigned int regno;
645 int total_frame_size, save_offset;
646 int sp_offset; /* offset from base_reg to final stack value. */
647 int save_regs_base; /* offset from base_reg to register save area. */
648 rtx_insn *insn;
649
650 total_frame_size = nios2_compute_frame_layout ();
651
652 if (flag_stack_usage_info)
653 current_function_static_stack_size = total_frame_size;
654
655 /* When R2 CDX push.n/stwm is available, arrange for stack frame to be built
656 using them. */
657 if (TARGET_HAS_CDX
658 && (cfun->machine->save_reg_size != 0
659 || cfun->machine->uses_anonymous_args))
660 {
661 unsigned int regmask = cfun->machine->save_mask;
662 unsigned int callee_save_regs = regmask & 0xffff0000;
663 unsigned int caller_save_regs = regmask & 0x0000ffff;
664 int push_immed = 0;
665 int pretend_args_size = NIOS2_STACK_ALIGN (crtl->args.pretend_args_size);
666 rtx stack_mem =
667 gen_frame_mem (SImode, plus_constant (Pmode, stack_pointer_rtx, -4));
668
669 /* Check that there is room for the entire stack frame before doing
670 any SP adjustments or pushes. */
671 if (crtl->limit_stack)
672 nios2_emit_stack_limit_check (total_frame_size);
673
674 if (pretend_args_size)
675 {
676 if (cfun->machine->uses_anonymous_args)
677 {
678 /* Emit a stwm to push copy of argument registers onto
679 the stack for va_arg processing. */
680 unsigned int r, mask = 0, n = pretend_args_size / 4;
681 for (r = LAST_ARG_REGNO - n + 1; r <= LAST_ARG_REGNO; r++)
682 mask |= (1 << r);
683 insn = emit_insn (nios2_ldst_parallel
684 (false, false, false, stack_mem,
685 -pretend_args_size, mask, false));
686 /* Tag first SP adjustment as frame-related. */
687 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 0)) = 1;
688 RTX_FRAME_RELATED_P (insn) = 1;
689 }
690 else
691 nios2_adjust_stack (-pretend_args_size, false);
692 }
693 if (callee_save_regs)
694 {
695 /* Emit a push.n to save registers and optionally allocate
696 push_immed extra bytes on the stack. */
697 int sp_adjust;
698 if (caller_save_regs)
699 /* Can't allocate extra stack space yet. */
700 push_immed = 0;
701 else if (cfun->machine->save_regs_offset <= 60)
702 /* Stack adjustment fits entirely in the push.n. */
703 push_immed = cfun->machine->save_regs_offset;
704 else if (frame_pointer_needed
705 && cfun->machine->fp_save_offset == 0)
706 /* Deferring the entire stack adjustment until later
707 allows us to use a mov.n instead of a 32-bit addi
708 instruction to set the frame pointer. */
709 push_immed = 0;
710 else
711 /* Splitting the stack adjustment between the push.n
712 and an explicit adjustment makes it more likely that
713 we can use spdeci.n for the explicit part. */
714 push_immed = 60;
715 sp_adjust = -(cfun->machine->callee_save_reg_size + push_immed);
716 insn = emit_insn (nios2_ldst_parallel (false, false, false,
717 stack_mem, sp_adjust,
718 callee_save_regs, false));
719 nios2_create_cfa_notes (insn, false);
720 RTX_FRAME_RELATED_P (insn) = 1;
721 }
722
723 if (caller_save_regs)
724 {
725 /* Emit a stwm to save the EH data regs, r4-r7. */
726 int caller_save_size = (cfun->machine->save_reg_size
727 - cfun->machine->callee_save_reg_size);
728 gcc_assert ((caller_save_regs & ~0xf0) == 0);
729 insn = emit_insn (nios2_ldst_parallel
730 (false, false, false, stack_mem,
731 -caller_save_size, caller_save_regs, false));
732 nios2_create_cfa_notes (insn, false);
733 RTX_FRAME_RELATED_P (insn) = 1;
734 }
735
736 save_regs_base = push_immed;
737 sp_offset = -(cfun->machine->save_regs_offset - push_immed);
738 }
739 /* The non-CDX cases decrement the stack pointer, to prepare for individual
740 register saves to the stack. */
741 else if (!SMALL_INT (total_frame_size))
742 {
743 /* We need an intermediary point, this will point at the spill block. */
744 nios2_adjust_stack (cfun->machine->save_regs_offset - total_frame_size,
745 false);
746 save_regs_base = 0;
747 sp_offset = -cfun->machine->save_regs_offset;
748 if (crtl->limit_stack)
749 nios2_emit_stack_limit_check (cfun->machine->save_regs_offset);
750 }
751 else if (total_frame_size)
752 {
753 nios2_adjust_stack (-total_frame_size, false);
754 save_regs_base = cfun->machine->save_regs_offset;
755 sp_offset = 0;
756 if (crtl->limit_stack)
757 nios2_emit_stack_limit_check (0);
758 }
759 else
760 save_regs_base = sp_offset = 0;
761
762 /* Save the registers individually in the non-CDX case. */
763 if (!TARGET_HAS_CDX)
764 {
765 save_offset = save_regs_base + cfun->machine->save_reg_size;
766
767 for (regno = LAST_GP_REG; regno > 0; regno--)
768 if (cfun->machine->save_mask & (1 << regno))
769 {
770 save_offset -= 4;
771 save_reg (regno, save_offset);
772 }
773 }
774
775 /* Set the hard frame pointer. */
776 if (frame_pointer_needed)
777 {
778 int fp_save_offset = save_regs_base + cfun->machine->fp_save_offset;
779 insn =
780 (fp_save_offset == 0
781 ? emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx)
782 : emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
783 stack_pointer_rtx,
784 gen_int_mode (fp_save_offset, Pmode))));
785 RTX_FRAME_RELATED_P (insn) = 1;
786 }
787
788 /* Allocate sp_offset more bytes in the stack frame. */
789 nios2_adjust_stack (sp_offset, false);
790
791 /* Load the PIC register if needed. */
792 if (crtl->uses_pic_offset_table)
793 nios2_load_pic_register ();
794
795 /* If we are profiling, make sure no instructions are scheduled before
796 the call to mcount. */
797 if (crtl->profile)
798 emit_insn (gen_blockage ());
799 }
800
801 void
nios2_expand_epilogue(bool sibcall_p)802 nios2_expand_epilogue (bool sibcall_p)
803 {
804 rtx_insn *insn;
805 rtx cfa_adj;
806 int total_frame_size;
807 int sp_adjust, save_offset;
808 unsigned int regno;
809
810 if (!sibcall_p && nios2_can_use_return_insn ())
811 {
812 emit_jump_insn (gen_return ());
813 return;
814 }
815
816 emit_insn (gen_blockage ());
817
818 total_frame_size = nios2_compute_frame_layout ();
819 if (frame_pointer_needed)
820 {
821 /* Recover the stack pointer. */
822 insn =
823 (cfun->machine->fp_save_offset == 0
824 ? emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx)
825 : emit_insn (gen_add3_insn
826 (stack_pointer_rtx, hard_frame_pointer_rtx,
827 gen_int_mode (-cfun->machine->fp_save_offset, Pmode))));
828 cfa_adj = plus_constant (Pmode, stack_pointer_rtx,
829 (total_frame_size
830 - cfun->machine->save_regs_offset));
831 add_reg_note (insn, REG_CFA_DEF_CFA, cfa_adj);
832 RTX_FRAME_RELATED_P (insn) = 1;
833
834 save_offset = 0;
835 sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
836 }
837 else if (!SMALL_INT (total_frame_size))
838 {
839 nios2_adjust_stack (cfun->machine->save_regs_offset, true);
840 save_offset = 0;
841 sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
842 }
843 else
844 {
845 save_offset = cfun->machine->save_regs_offset;
846 sp_adjust = total_frame_size;
847 }
848
849 if (!TARGET_HAS_CDX)
850 {
851 /* Generate individual register restores. */
852 save_offset += cfun->machine->save_reg_size;
853
854 for (regno = LAST_GP_REG; regno > 0; regno--)
855 if (cfun->machine->save_mask & (1 << regno))
856 {
857 save_offset -= 4;
858 restore_reg (regno, save_offset);
859 }
860 nios2_adjust_stack (sp_adjust, true);
861 }
862 else if (cfun->machine->save_reg_size == 0)
863 {
864 /* Nothing to restore, just recover the stack position. */
865 nios2_adjust_stack (sp_adjust, true);
866 }
867 else
868 {
869 /* Emit CDX pop.n/ldwm to restore registers and optionally return. */
870 unsigned int regmask = cfun->machine->save_mask;
871 unsigned int callee_save_regs = regmask & 0xffff0000;
872 unsigned int caller_save_regs = regmask & 0x0000ffff;
873 int callee_save_size = cfun->machine->callee_save_reg_size;
874 int caller_save_size = cfun->machine->save_reg_size - callee_save_size;
875 int pretend_args_size = NIOS2_STACK_ALIGN (crtl->args.pretend_args_size);
876 bool ret_p = (!pretend_args_size && !crtl->calls_eh_return
877 && !sibcall_p);
878
879 if (!ret_p || caller_save_size > 0)
880 sp_adjust = save_offset;
881 else
882 sp_adjust = (save_offset > 60 ? save_offset - 60 : 0);
883
884 save_offset -= sp_adjust;
885
886 nios2_adjust_stack (sp_adjust, true);
887
888 if (caller_save_regs)
889 {
890 /* Emit a ldwm to restore EH data regs. */
891 rtx stack_mem = gen_frame_mem (SImode, stack_pointer_rtx);
892 insn = emit_insn (nios2_ldst_parallel
893 (true, true, true, stack_mem,
894 caller_save_size, caller_save_regs, false));
895 RTX_FRAME_RELATED_P (insn) = 1;
896 nios2_create_cfa_notes (insn, true);
897 }
898
899 if (callee_save_regs)
900 {
901 int sp_adjust = save_offset + callee_save_size;
902 rtx stack_mem;
903 if (ret_p)
904 {
905 /* Emit a pop.n to restore regs and return. */
906 stack_mem =
907 gen_frame_mem (SImode,
908 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
909 gen_int_mode (sp_adjust - 4,
910 Pmode)));
911 insn =
912 emit_jump_insn (nios2_ldst_parallel (true, false, false,
913 stack_mem, sp_adjust,
914 callee_save_regs, ret_p));
915 RTX_FRAME_RELATED_P (insn) = 1;
916 /* No need to attach CFA notes since we cannot step over
917 a return. */
918 return;
919 }
920 else
921 {
922 /* If no return, we have to use the ldwm form. */
923 stack_mem = gen_frame_mem (SImode, stack_pointer_rtx);
924 insn =
925 emit_insn (nios2_ldst_parallel (true, true, true,
926 stack_mem, sp_adjust,
927 callee_save_regs, ret_p));
928 RTX_FRAME_RELATED_P (insn) = 1;
929 nios2_create_cfa_notes (insn, true);
930 }
931 }
932
933 if (pretend_args_size)
934 nios2_adjust_stack (pretend_args_size, true);
935 }
936
937 /* Add in the __builtin_eh_return stack adjustment. */
938 if (crtl->calls_eh_return)
939 emit_insn (gen_add2_insn (stack_pointer_rtx, EH_RETURN_STACKADJ_RTX));
940
941 if (!sibcall_p)
942 emit_jump_insn (gen_simple_return ());
943 }
944
945 bool
nios2_expand_return(void)946 nios2_expand_return (void)
947 {
948 /* If CDX is available, generate a pop.n instruction to do both
949 the stack pop and return. */
950 if (TARGET_HAS_CDX)
951 {
952 int total_frame_size = nios2_compute_frame_layout ();
953 int sp_adjust = (cfun->machine->save_regs_offset
954 + cfun->machine->callee_save_reg_size);
955 gcc_assert (sp_adjust == total_frame_size);
956 if (sp_adjust != 0)
957 {
958 rtx mem =
959 gen_frame_mem (SImode,
960 plus_constant (Pmode, stack_pointer_rtx,
961 sp_adjust - 4, false));
962 rtx_insn *insn =
963 emit_jump_insn (nios2_ldst_parallel (true, false, false,
964 mem, sp_adjust,
965 cfun->machine->save_mask,
966 true));
967 RTX_FRAME_RELATED_P (insn) = 1;
968 /* No need to create CFA notes since we can't step over
969 a return. */
970 return true;
971 }
972 }
973 return false;
974 }
975
976 /* Implement RETURN_ADDR_RTX. Note, we do not support moving
977 back to a previous frame. */
978 rtx
nios2_get_return_address(int count)979 nios2_get_return_address (int count)
980 {
981 if (count != 0)
982 return const0_rtx;
983
984 return get_hard_reg_initial_val (Pmode, RA_REGNO);
985 }
986
987 /* Emit code to change the current function's return address to
988 ADDRESS. SCRATCH is available as a scratch register, if needed.
989 ADDRESS and SCRATCH are both word-mode GPRs. */
990 void
nios2_set_return_address(rtx address,rtx scratch)991 nios2_set_return_address (rtx address, rtx scratch)
992 {
993 nios2_compute_frame_layout ();
994 if (cfun->machine->save_mask & (1 << RA_REGNO))
995 {
996 unsigned offset = cfun->machine->save_reg_size - 4;
997 rtx base;
998
999 if (frame_pointer_needed)
1000 base = hard_frame_pointer_rtx;
1001 else
1002 {
1003 base = stack_pointer_rtx;
1004 offset += cfun->machine->save_regs_offset;
1005
1006 if (!SMALL_INT (offset))
1007 {
1008 emit_move_insn (scratch, gen_int_mode (offset, Pmode));
1009 emit_insn (gen_add2_insn (scratch, base));
1010 base = scratch;
1011 offset = 0;
1012 }
1013 }
1014 if (offset)
1015 base = plus_constant (Pmode, base, offset);
1016 emit_move_insn (gen_rtx_MEM (Pmode, base), address);
1017 }
1018 else
1019 emit_move_insn (gen_rtx_REG (Pmode, RA_REGNO), address);
1020 }
1021
1022 /* Implement FUNCTION_PROFILER macro. */
1023 void
nios2_function_profiler(FILE * file,int labelno ATTRIBUTE_UNUSED)1024 nios2_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
1025 {
1026 fprintf (file, "\tmov\tr8, ra\n");
1027 if (flag_pic == 1)
1028 {
1029 fprintf (file, "\tnextpc\tr2\n");
1030 fprintf (file, "\t1: movhi\tr3, %%hiadj(_gp_got - 1b)\n");
1031 fprintf (file, "\taddi\tr3, r3, %%lo(_gp_got - 1b)\n");
1032 fprintf (file, "\tadd\tr2, r2, r3\n");
1033 fprintf (file, "\tldw\tr2, %%call(_mcount)(r2)\n");
1034 fprintf (file, "\tcallr\tr2\n");
1035 }
1036 else if (flag_pic == 2)
1037 {
1038 fprintf (file, "\tnextpc\tr2\n");
1039 fprintf (file, "\t1: movhi\tr3, %%hiadj(_gp_got - 1b)\n");
1040 fprintf (file, "\taddi\tr3, r3, %%lo(_gp_got - 1b)\n");
1041 fprintf (file, "\tadd\tr2, r2, r3\n");
1042 fprintf (file, "\tmovhi\tr3, %%call_hiadj(_mcount)\n");
1043 fprintf (file, "\taddi\tr3, r3, %%call_lo(_mcount)\n");
1044 fprintf (file, "\tadd\tr3, r2, r3\n");
1045 fprintf (file, "\tldw\tr2, 0(r3)\n");
1046 fprintf (file, "\tcallr\tr2\n");
1047 }
1048 else
1049 fprintf (file, "\tcall\t_mcount\n");
1050 fprintf (file, "\tmov\tra, r8\n");
1051 }
1052
1053 /* Dump stack layout. */
1054 static void
nios2_dump_frame_layout(FILE * file)1055 nios2_dump_frame_layout (FILE *file)
1056 {
1057 fprintf (file, "\t%s Current Frame Info\n", ASM_COMMENT_START);
1058 fprintf (file, "\t%s total_size = %d\n", ASM_COMMENT_START,
1059 cfun->machine->total_size);
1060 fprintf (file, "\t%s var_size = %d\n", ASM_COMMENT_START,
1061 cfun->machine->var_size);
1062 fprintf (file, "\t%s args_size = %d\n", ASM_COMMENT_START,
1063 cfun->machine->args_size);
1064 fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START,
1065 cfun->machine->save_reg_size);
1066 fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START,
1067 cfun->machine->initialized);
1068 fprintf (file, "\t%s save_regs_offset = %d\n", ASM_COMMENT_START,
1069 cfun->machine->save_regs_offset);
1070 fprintf (file, "\t%s is_leaf = %d\n", ASM_COMMENT_START,
1071 crtl->is_leaf);
1072 fprintf (file, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START,
1073 frame_pointer_needed);
1074 fprintf (file, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START,
1075 crtl->args.pretend_args_size);
1076 }
1077
1078 /* Return true if REGNO should be saved in the prologue. */
1079 static bool
prologue_saved_reg_p(unsigned regno)1080 prologue_saved_reg_p (unsigned regno)
1081 {
1082 gcc_assert (GP_REG_P (regno));
1083
1084 if (df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno))
1085 return true;
1086
1087 if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
1088 return true;
1089
1090 if (regno == PIC_OFFSET_TABLE_REGNUM && crtl->uses_pic_offset_table)
1091 return true;
1092
1093 if (regno == RA_REGNO && df_regs_ever_live_p (RA_REGNO))
1094 return true;
1095
1096 return false;
1097 }
1098
1099 /* Implement TARGET_CAN_ELIMINATE. */
1100 static bool
nios2_can_eliminate(const int from ATTRIBUTE_UNUSED,const int to)1101 nios2_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
1102 {
1103 if (to == STACK_POINTER_REGNUM)
1104 return !frame_pointer_needed;
1105 return true;
1106 }
1107
1108 /* Implement INITIAL_ELIMINATION_OFFSET macro. */
1109 int
nios2_initial_elimination_offset(int from,int to)1110 nios2_initial_elimination_offset (int from, int to)
1111 {
1112 int offset;
1113
1114 nios2_compute_frame_layout ();
1115
1116 /* Set OFFSET to the offset from the stack pointer. */
1117 switch (from)
1118 {
1119 case FRAME_POINTER_REGNUM:
1120 /* This is the high end of the local variable storage, not the
1121 hard frame pointer. */
1122 offset = cfun->machine->args_size + cfun->machine->var_size;
1123 break;
1124
1125 case ARG_POINTER_REGNUM:
1126 offset = cfun->machine->total_size;
1127 offset -= crtl->args.pretend_args_size;
1128 break;
1129
1130 default:
1131 gcc_unreachable ();
1132 }
1133
1134 /* If we are asked for the frame pointer offset, then adjust OFFSET
1135 by the offset from the frame pointer to the stack pointer. */
1136 if (to == HARD_FRAME_POINTER_REGNUM)
1137 offset -= (cfun->machine->save_regs_offset
1138 + cfun->machine->fp_save_offset);
1139
1140 return offset;
1141 }
1142
1143 /* Return nonzero if this function is known to have a null epilogue.
1144 This allows the optimizer to omit jumps to jumps if no stack
1145 was created. */
1146 int
nios2_can_use_return_insn(void)1147 nios2_can_use_return_insn (void)
1148 {
1149 int total_frame_size;
1150
1151 if (!reload_completed || crtl->profile)
1152 return 0;
1153
1154 total_frame_size = nios2_compute_frame_layout ();
1155
1156 /* If CDX is available, check if we can return using a
1157 single pop.n instruction. */
1158 if (TARGET_HAS_CDX
1159 && !frame_pointer_needed
1160 && cfun->machine->save_regs_offset <= 60
1161 && (cfun->machine->save_mask & 0x80000000) != 0
1162 && (cfun->machine->save_mask & 0xffff) == 0
1163 && crtl->args.pretend_args_size == 0)
1164 return true;
1165
1166 return total_frame_size == 0;
1167 }
1168
1169
1170 /* Check and signal some warnings/errors on FPU insn options. */
1171 static void
nios2_custom_check_insns(void)1172 nios2_custom_check_insns (void)
1173 {
1174 unsigned int i, j;
1175 bool errors = false;
1176
1177 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
1178 if (N2FPU_ENABLED_P (i) && N2FPU_DOUBLE_P (i))
1179 {
1180 for (j = 0; j < ARRAY_SIZE (nios2_fpu_insn); j++)
1181 if (N2FPU_DOUBLE_REQUIRED_P (j) && ! N2FPU_ENABLED_P (j))
1182 {
1183 error ("switch %<-mcustom-%s%> is required for "
1184 "double-precision floating-point", N2FPU_NAME (j));
1185 errors = true;
1186 }
1187 break;
1188 }
1189
1190 if (errors || custom_code_conflict)
1191 fatal_error (input_location,
1192 "conflicting use of %<-mcustom%> switches, "
1193 "target attributes, "
1194 "and/or %<__builtin_custom_%> functions");
1195 }
1196
1197 static void
nios2_set_fpu_custom_code(enum n2fpu_code code,int n,bool override_p)1198 nios2_set_fpu_custom_code (enum n2fpu_code code, int n, bool override_p)
1199 {
1200 if (override_p || N2FPU_N (code) == -1)
1201 N2FPU_N (code) = n;
1202 nios2_register_custom_code (n, CCS_FPU, (int) code);
1203 }
1204
1205 /* Type to represent a standard FPU config. */
1206 struct nios2_fpu_config
1207 {
1208 const char *name;
1209 bool set_sp_constants;
1210 int code[n2fpu_code_num];
1211 };
1212
1213 #define NIOS2_FPU_CONFIG_NUM 4
1214 static struct nios2_fpu_config custom_fpu_config[NIOS2_FPU_CONFIG_NUM];
1215
1216 static void
nios2_init_fpu_configs(void)1217 nios2_init_fpu_configs (void)
1218 {
1219 struct nios2_fpu_config* cfg;
1220 int i = 0;
1221 #define NEXT_FPU_CONFIG \
1222 do { \
1223 cfg = &custom_fpu_config[i++]; \
1224 memset (cfg, -1, sizeof (struct nios2_fpu_config));\
1225 } while (0)
1226
1227 NEXT_FPU_CONFIG;
1228 cfg->name = "60-1";
1229 cfg->set_sp_constants = true;
1230 cfg->code[n2fpu_fmuls] = 252;
1231 cfg->code[n2fpu_fadds] = 253;
1232 cfg->code[n2fpu_fsubs] = 254;
1233
1234 NEXT_FPU_CONFIG;
1235 cfg->name = "60-2";
1236 cfg->set_sp_constants = true;
1237 cfg->code[n2fpu_fmuls] = 252;
1238 cfg->code[n2fpu_fadds] = 253;
1239 cfg->code[n2fpu_fsubs] = 254;
1240 cfg->code[n2fpu_fdivs] = 255;
1241
1242 NEXT_FPU_CONFIG;
1243 cfg->name = "72-3";
1244 cfg->set_sp_constants = true;
1245 cfg->code[n2fpu_floatus] = 243;
1246 cfg->code[n2fpu_fixsi] = 244;
1247 cfg->code[n2fpu_floatis] = 245;
1248 cfg->code[n2fpu_fcmpgts] = 246;
1249 cfg->code[n2fpu_fcmples] = 249;
1250 cfg->code[n2fpu_fcmpeqs] = 250;
1251 cfg->code[n2fpu_fcmpnes] = 251;
1252 cfg->code[n2fpu_fmuls] = 252;
1253 cfg->code[n2fpu_fadds] = 253;
1254 cfg->code[n2fpu_fsubs] = 254;
1255 cfg->code[n2fpu_fdivs] = 255;
1256
1257 NEXT_FPU_CONFIG;
1258 cfg->name = "fph2";
1259 cfg->code[n2fpu_fabss] = 224;
1260 cfg->code[n2fpu_fnegs] = 225;
1261 cfg->code[n2fpu_fcmpnes] = 226;
1262 cfg->code[n2fpu_fcmpeqs] = 227;
1263 cfg->code[n2fpu_fcmpges] = 228;
1264 cfg->code[n2fpu_fcmpgts] = 229;
1265 cfg->code[n2fpu_fcmples] = 230;
1266 cfg->code[n2fpu_fcmplts] = 231;
1267 cfg->code[n2fpu_fmaxs] = 232;
1268 cfg->code[n2fpu_fmins] = 233;
1269 cfg->code[n2fpu_round] = 248;
1270 cfg->code[n2fpu_fixsi] = 249;
1271 cfg->code[n2fpu_floatis] = 250;
1272 cfg->code[n2fpu_fsqrts] = 251;
1273 cfg->code[n2fpu_fmuls] = 252;
1274 cfg->code[n2fpu_fadds] = 253;
1275 cfg->code[n2fpu_fsubs] = 254;
1276 cfg->code[n2fpu_fdivs] = 255;
1277
1278 #undef NEXT_FPU_CONFIG
1279 gcc_assert (i == NIOS2_FPU_CONFIG_NUM);
1280 }
1281
1282 static struct nios2_fpu_config *
nios2_match_custom_fpu_cfg(const char * cfgname,const char * endp)1283 nios2_match_custom_fpu_cfg (const char *cfgname, const char *endp)
1284 {
1285 int i;
1286 for (i = 0; i < NIOS2_FPU_CONFIG_NUM; i++)
1287 {
1288 bool match = !(endp != NULL
1289 ? strncmp (custom_fpu_config[i].name, cfgname,
1290 endp - cfgname)
1291 : strcmp (custom_fpu_config[i].name, cfgname));
1292 if (match)
1293 return &custom_fpu_config[i];
1294 }
1295 return NULL;
1296 }
1297
1298 /* Use CFGNAME to lookup FPU config, ENDP if not NULL marks end of string.
1299 OVERRIDE is true if loaded config codes should overwrite current state. */
1300 static void
nios2_handle_custom_fpu_cfg(const char * cfgname,const char * endp,bool override)1301 nios2_handle_custom_fpu_cfg (const char *cfgname, const char *endp,
1302 bool override)
1303 {
1304 struct nios2_fpu_config *cfg = nios2_match_custom_fpu_cfg (cfgname, endp);
1305 if (cfg)
1306 {
1307 unsigned int i;
1308 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
1309 if (cfg->code[i] >= 0)
1310 nios2_set_fpu_custom_code ((enum n2fpu_code) i, cfg->code[i],
1311 override);
1312 if (cfg->set_sp_constants)
1313 flag_single_precision_constant = 1;
1314 }
1315 else
1316 warning (0, "ignoring unrecognized switch %<-mcustom-fpu-cfg%> "
1317 "value %<%s%>", cfgname);
1318
1319 /* Guard against errors in the standard configurations. */
1320 nios2_custom_check_insns ();
1321 }
1322
1323 /* Check individual FPU insn options, and register custom code. */
1324 static void
nios2_handle_custom_fpu_insn_option(int fpu_insn_index)1325 nios2_handle_custom_fpu_insn_option (int fpu_insn_index)
1326 {
1327 int param = N2FPU_N (fpu_insn_index);
1328
1329 if (param >= 0 && param <= 255)
1330 nios2_register_custom_code (param, CCS_FPU, fpu_insn_index);
1331
1332 /* Valid values are 0-255, but also allow -1 so that the
1333 -mno-custom-<opt> switches work. */
1334 else if (param != -1)
1335 error ("switch %<-mcustom-%s%> value %d must be between 0 and 255",
1336 N2FPU_NAME (fpu_insn_index), param);
1337 }
1338
1339 /* Allocate a chunk of memory for per-function machine-dependent data. */
1340 static struct machine_function *
nios2_init_machine_status(void)1341 nios2_init_machine_status (void)
1342 {
1343 return ggc_cleared_alloc<machine_function> ();
1344 }
1345
1346 /* Implement TARGET_OPTION_OVERRIDE. */
1347 static void
nios2_option_override(void)1348 nios2_option_override (void)
1349 {
1350 unsigned int i;
1351
1352 #ifdef SUBTARGET_OVERRIDE_OPTIONS
1353 SUBTARGET_OVERRIDE_OPTIONS;
1354 #endif
1355
1356 /* Check for unsupported options. */
1357 if (flag_pic && !TARGET_LINUX_ABI)
1358 sorry ("position-independent code requires the Linux ABI");
1359 if (flag_pic && stack_limit_rtx
1360 && GET_CODE (stack_limit_rtx) == SYMBOL_REF)
1361 sorry ("PIC support for %<-fstack-limit-symbol%>");
1362
1363 /* Function to allocate machine-dependent function status. */
1364 init_machine_status = &nios2_init_machine_status;
1365
1366 nios2_section_threshold
1367 = (OPTION_SET_P (g_switch_value)
1368 ? g_switch_value : NIOS2_DEFAULT_GVALUE);
1369
1370 if (nios2_gpopt_option == gpopt_unspecified)
1371 {
1372 /* Default to -mgpopt unless -fpic or -fPIC. */
1373 if (flag_pic)
1374 nios2_gpopt_option = gpopt_none;
1375 else
1376 nios2_gpopt_option = gpopt_local;
1377 }
1378
1379 /* GP-relative and r0-relative addressing don't make sense for PIC. */
1380 if (flag_pic)
1381 {
1382 if (nios2_gpopt_option != gpopt_none)
1383 error ("%<-mgpopt%> not supported with PIC");
1384 if (nios2_gprel_sec)
1385 error ("%<-mgprel-sec=%> not supported with PIC");
1386 if (nios2_r0rel_sec)
1387 error ("%<-mr0rel-sec=%> not supported with PIC");
1388 }
1389
1390 /* Process -mgprel-sec= and -m0rel-sec=. */
1391 if (nios2_gprel_sec)
1392 {
1393 if (regcomp (&nios2_gprel_sec_regex, nios2_gprel_sec,
1394 REG_EXTENDED | REG_NOSUB))
1395 error ("%<-mgprel-sec=%> argument is not a valid regular expression");
1396 }
1397 if (nios2_r0rel_sec)
1398 {
1399 if (regcomp (&nios2_r0rel_sec_regex, nios2_r0rel_sec,
1400 REG_EXTENDED | REG_NOSUB))
1401 error ("%<-mr0rel-sec=%> argument is not a valid regular expression");
1402 }
1403
1404 /* If we don't have mul, we don't have mulx either! */
1405 if (!TARGET_HAS_MUL && TARGET_HAS_MULX)
1406 target_flags &= ~MASK_HAS_MULX;
1407
1408 /* Optional BMX and CDX instructions only make sense for R2. */
1409 if (!TARGET_ARCH_R2)
1410 {
1411 if (TARGET_HAS_BMX)
1412 error ("BMX instructions are only supported with R2 architecture");
1413 if (TARGET_HAS_CDX)
1414 error ("CDX instructions are only supported with R2 architecture");
1415 }
1416
1417 /* R2 is little-endian only. */
1418 if (TARGET_ARCH_R2 && TARGET_BIG_ENDIAN)
1419 error ("R2 architecture is little-endian only");
1420
1421 /* Initialize default FPU configurations. */
1422 nios2_init_fpu_configs ();
1423
1424 /* Set up default handling for floating point custom instructions.
1425
1426 Putting things in this order means that the -mcustom-fpu-cfg=
1427 switch will always be overridden by individual -mcustom-fadds=
1428 switches, regardless of the order in which they were specified
1429 on the command line.
1430
1431 This behavior of prioritization of individual -mcustom-<insn>=
1432 options before the -mcustom-fpu-cfg= switch is maintained for
1433 compatibility. */
1434 if (nios2_custom_fpu_cfg_string && *nios2_custom_fpu_cfg_string)
1435 nios2_handle_custom_fpu_cfg (nios2_custom_fpu_cfg_string, NULL, false);
1436
1437 /* Handle options for individual FPU insns. */
1438 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
1439 nios2_handle_custom_fpu_insn_option (i);
1440
1441 nios2_custom_check_insns ();
1442
1443 /* Save the initial options in case the user does function specific
1444 options. */
1445 target_option_default_node = target_option_current_node
1446 = build_target_option_node (&global_options, &global_options_set);
1447 }
1448
1449
1450 /* Return true if CST is a constant within range of movi/movui/movhi. */
1451 static bool
nios2_simple_const_p(const_rtx cst)1452 nios2_simple_const_p (const_rtx cst)
1453 {
1454 if (!CONST_INT_P (cst))
1455 return false;
1456 HOST_WIDE_INT val = INTVAL (cst);
1457 return SMALL_INT (val) || SMALL_INT_UNSIGNED (val) || UPPER16_INT (val);
1458 }
1459
1460 /* Compute a (partial) cost for rtx X. Return true if the complete
1461 cost has been computed, and false if subexpressions should be
1462 scanned. In either case, *TOTAL contains the cost result. */
1463 static bool
nios2_rtx_costs(rtx x,machine_mode mode,int outer_code,int opno,int * total,bool speed)1464 nios2_rtx_costs (rtx x, machine_mode mode,
1465 int outer_code,
1466 int opno,
1467 int *total, bool speed)
1468 {
1469 int code = GET_CODE (x);
1470
1471 switch (code)
1472 {
1473 case CONST_INT:
1474 if (INTVAL (x) == 0 || nios2_simple_const_p (x))
1475 {
1476 *total = COSTS_N_INSNS (0);
1477 return true;
1478 }
1479 else
1480 {
1481 /* High + lo_sum. */
1482 *total = COSTS_N_INSNS (1);
1483 return true;
1484 }
1485
1486 case LABEL_REF:
1487 case SYMBOL_REF:
1488 case CONST:
1489 case CONST_DOUBLE:
1490 if (gprel_constant_p (x) || r0rel_constant_p (x))
1491 {
1492 *total = COSTS_N_INSNS (1);
1493 return true;
1494 }
1495 else
1496 {
1497 /* High + lo_sum. */
1498 *total = COSTS_N_INSNS (1);
1499 return true;
1500 }
1501
1502 case HIGH:
1503 {
1504 /* This is essentially a constant. */
1505 *total = COSTS_N_INSNS (0);
1506 return true;
1507 }
1508
1509 case LO_SUM:
1510 {
1511 *total = COSTS_N_INSNS (0);
1512 return true;
1513 }
1514
1515 case AND:
1516 {
1517 /* Recognize 'nor' insn pattern. */
1518 if (GET_CODE (XEXP (x, 0)) == NOT
1519 && GET_CODE (XEXP (x, 1)) == NOT)
1520 {
1521 *total = COSTS_N_INSNS (1);
1522 return true;
1523 }
1524 return false;
1525 }
1526
1527 /* For insns that have an execution latency (3 cycles), don't
1528 penalize by the full amount since we can often schedule
1529 to avoid it. */
1530 case MULT:
1531 {
1532 if (!TARGET_HAS_MUL)
1533 *total = COSTS_N_INSNS (5); /* Guess? */
1534 else if (speed)
1535 *total = COSTS_N_INSNS (2); /* Latency adjustment. */
1536 else
1537 *total = COSTS_N_INSNS (1);
1538 if (TARGET_HAS_MULX && GET_MODE (x) == DImode)
1539 {
1540 enum rtx_code c0 = GET_CODE (XEXP (x, 0));
1541 enum rtx_code c1 = GET_CODE (XEXP (x, 1));
1542 if ((c0 == SIGN_EXTEND && c1 == SIGN_EXTEND)
1543 || (c0 == ZERO_EXTEND && c1 == ZERO_EXTEND))
1544 /* This is the <mul>sidi3 pattern, which expands into 4 insns,
1545 2 multiplies and 2 moves. */
1546 {
1547 *total = *total * 2 + COSTS_N_INSNS (2);
1548 return true;
1549 }
1550 }
1551 return false;
1552 }
1553
1554 case DIV:
1555 {
1556 if (!TARGET_HAS_DIV)
1557 *total = COSTS_N_INSNS (5); /* Guess? */
1558 else if (speed)
1559 *total = COSTS_N_INSNS (2); /* Latency adjustment. */
1560 else
1561 *total = COSTS_N_INSNS (1);
1562 return false;
1563 }
1564
1565 case ASHIFT:
1566 case ASHIFTRT:
1567 case LSHIFTRT:
1568 case ROTATE:
1569 {
1570 if (!speed)
1571 *total = COSTS_N_INSNS (1);
1572 else
1573 *total = COSTS_N_INSNS (2); /* Latency adjustment. */
1574 return false;
1575 }
1576
1577 case ZERO_EXTRACT:
1578 if (TARGET_HAS_BMX)
1579 {
1580 *total = COSTS_N_INSNS (1);
1581 return true;
1582 }
1583 return false;
1584
1585 case SIGN_EXTEND:
1586 {
1587 if (MEM_P (XEXP (x, 0)))
1588 *total = COSTS_N_INSNS (1);
1589 else
1590 *total = COSTS_N_INSNS (3);
1591 return false;
1592 }
1593
1594 case MEM:
1595 {
1596 rtx addr = XEXP (x, 0);
1597
1598 /* Account for cost of different addressing modes. */
1599 *total = nios2_address_cost (addr, mode, ADDR_SPACE_GENERIC, speed);
1600
1601 if (outer_code == SET && opno == 0)
1602 /* Stores execute in 1 cycle accounted for by
1603 the outer SET. */
1604 ;
1605 else if (outer_code == SET || outer_code == SIGN_EXTEND
1606 || outer_code == ZERO_EXTEND)
1607 /* Latency adjustment. */
1608 {
1609 if (speed)
1610 *total += COSTS_N_INSNS (1);
1611 }
1612 else
1613 /* This is going to have to be split into a load. */
1614 *total += COSTS_N_INSNS (speed ? 2 : 1);
1615 return true;
1616 }
1617
1618 default:
1619 return false;
1620 }
1621 }
1622
1623 /* Implement TARGET_PREFERRED_RELOAD_CLASS. */
1624 static reg_class_t
nios2_preferred_reload_class(rtx x ATTRIBUTE_UNUSED,reg_class_t regclass)1625 nios2_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t regclass)
1626 {
1627 return regclass == NO_REGS ? GENERAL_REGS : regclass;
1628 }
1629
1630 /* Emit a call to __tls_get_addr. TI is the argument to this function.
1631 RET is an RTX for the return value location. The entire insn sequence
1632 is returned. */
1633 static GTY(()) rtx nios2_tls_symbol;
1634
1635 static rtx
nios2_call_tls_get_addr(rtx ti)1636 nios2_call_tls_get_addr (rtx ti)
1637 {
1638 rtx arg = gen_rtx_REG (Pmode, FIRST_ARG_REGNO);
1639 rtx ret = gen_rtx_REG (Pmode, FIRST_RETVAL_REGNO);
1640 rtx fn;
1641 rtx_insn *insn;
1642
1643 if (!nios2_tls_symbol)
1644 nios2_tls_symbol = init_one_libfunc ("__tls_get_addr");
1645
1646 emit_move_insn (arg, ti);
1647 fn = gen_rtx_MEM (QImode, nios2_tls_symbol);
1648 insn = emit_call_insn (gen_call_value (ret, fn, const0_rtx));
1649 RTL_CONST_CALL_P (insn) = 1;
1650 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), ret);
1651 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), arg);
1652
1653 return ret;
1654 }
1655
1656 /* Return true for large offsets requiring hiadj/lo relocation pairs. */
1657 static bool
nios2_large_offset_p(int unspec)1658 nios2_large_offset_p (int unspec)
1659 {
1660 gcc_assert (nios2_unspec_reloc_name (unspec) != NULL);
1661
1662 if (flag_pic == 2
1663 /* FIXME: TLS GOT offset relocations will eventually also get this
1664 treatment, after binutils support for those are also completed. */
1665 && (unspec == UNSPEC_PIC_SYM || unspec == UNSPEC_PIC_CALL_SYM))
1666 return true;
1667
1668 /* 'gotoff' offsets are always hiadj/lo. */
1669 if (unspec == UNSPEC_PIC_GOTOFF_SYM)
1670 return true;
1671
1672 return false;
1673 }
1674
1675 /* Return true for conforming unspec relocations. Also used in
1676 constraints.md and predicates.md. */
1677 bool
nios2_unspec_reloc_p(rtx op)1678 nios2_unspec_reloc_p (rtx op)
1679 {
1680 return (GET_CODE (op) == CONST
1681 && GET_CODE (XEXP (op, 0)) == UNSPEC
1682 && ! nios2_large_offset_p (XINT (XEXP (op, 0), 1)));
1683 }
1684
1685 static bool
nios2_large_unspec_reloc_p(rtx op)1686 nios2_large_unspec_reloc_p (rtx op)
1687 {
1688 return (GET_CODE (op) == CONST
1689 && GET_CODE (XEXP (op, 0)) == UNSPEC
1690 && nios2_large_offset_p (XINT (XEXP (op, 0), 1)));
1691 }
1692
1693 /* Helper to generate unspec constant. */
1694 static rtx
nios2_unspec_offset(rtx loc,int unspec)1695 nios2_unspec_offset (rtx loc, int unspec)
1696 {
1697 return gen_rtx_CONST (Pmode, gen_rtx_UNSPEC (Pmode, gen_rtvec (1, loc),
1698 unspec));
1699 }
1700
1701 /* Generate GOT pointer based address with large offset. */
1702 static rtx
nios2_large_got_address(rtx offset,rtx tmp)1703 nios2_large_got_address (rtx offset, rtx tmp)
1704 {
1705 if (!tmp)
1706 tmp = gen_reg_rtx (Pmode);
1707 emit_move_insn (tmp, offset);
1708 return gen_rtx_PLUS (Pmode, tmp, pic_offset_table_rtx);
1709 }
1710
1711 /* Generate a GOT pointer based address. */
1712 static rtx
nios2_got_address(rtx loc,int unspec)1713 nios2_got_address (rtx loc, int unspec)
1714 {
1715 rtx offset = nios2_unspec_offset (loc, unspec);
1716 crtl->uses_pic_offset_table = 1;
1717
1718 if (nios2_large_offset_p (unspec))
1719 return force_reg (Pmode, nios2_large_got_address (offset, NULL_RTX));
1720
1721 return gen_rtx_PLUS (Pmode, pic_offset_table_rtx, offset);
1722 }
1723
1724 /* Generate the code to access LOC, a thread local SYMBOL_REF. The
1725 return value will be a valid address and move_operand (either a REG
1726 or a LO_SUM). */
1727 static rtx
nios2_legitimize_tls_address(rtx loc)1728 nios2_legitimize_tls_address (rtx loc)
1729 {
1730 rtx tmp, mem, tp;
1731 enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
1732
1733 switch (model)
1734 {
1735 case TLS_MODEL_GLOBAL_DYNAMIC:
1736 tmp = gen_reg_rtx (Pmode);
1737 emit_move_insn (tmp, nios2_got_address (loc, UNSPEC_ADD_TLS_GD));
1738 return nios2_call_tls_get_addr (tmp);
1739
1740 case TLS_MODEL_LOCAL_DYNAMIC:
1741 tmp = gen_reg_rtx (Pmode);
1742 emit_move_insn (tmp, nios2_got_address (loc, UNSPEC_ADD_TLS_LDM));
1743 return gen_rtx_PLUS (Pmode, nios2_call_tls_get_addr (tmp),
1744 nios2_unspec_offset (loc, UNSPEC_ADD_TLS_LDO));
1745
1746 case TLS_MODEL_INITIAL_EXEC:
1747 tmp = gen_reg_rtx (Pmode);
1748 mem = gen_const_mem (Pmode, nios2_got_address (loc, UNSPEC_LOAD_TLS_IE));
1749 emit_move_insn (tmp, mem);
1750 tp = gen_rtx_REG (Pmode, TP_REGNO);
1751 return gen_rtx_PLUS (Pmode, tp, tmp);
1752
1753 case TLS_MODEL_LOCAL_EXEC:
1754 tp = gen_rtx_REG (Pmode, TP_REGNO);
1755 return gen_rtx_PLUS (Pmode, tp,
1756 nios2_unspec_offset (loc, UNSPEC_ADD_TLS_LE));
1757 default:
1758 gcc_unreachable ();
1759 }
1760 }
1761
1762 /* Divide Support
1763
1764 If -O3 is used, we want to output a table lookup for
1765 divides between small numbers (both num and den >= 0
1766 and < 0x10). The overhead of this method in the worst
1767 case is 40 bytes in the text section (10 insns) and
1768 256 bytes in the data section. Additional divides do
1769 not incur additional penalties in the data section.
1770
1771 Code speed is improved for small divides by about 5x
1772 when using this method in the worse case (~9 cycles
1773 vs ~45). And in the worst case divides not within the
1774 table are penalized by about 10% (~5 cycles vs ~45).
1775 However in the typical case the penalty is not as bad
1776 because doing the long divide in only 45 cycles is
1777 quite optimistic.
1778
1779 ??? would be nice to have some benchmarks other
1780 than Dhrystone to back this up.
1781
1782 This bit of expansion is to create this instruction
1783 sequence as rtl.
1784 or $8, $4, $5
1785 slli $9, $4, 4
1786 cmpgeui $3, $8, 16
1787 beq $3, $0, .L3
1788 or $10, $9, $5
1789 add $12, $11, divide_table
1790 ldbu $2, 0($12)
1791 br .L1
1792 .L3:
1793 call slow_div
1794 .L1:
1795 # continue here with result in $2
1796
1797 ??? Ideally I would like the libcall block to contain all
1798 of this code, but I don't know how to do that. What it
1799 means is that if the divide can be eliminated, it may not
1800 completely disappear.
1801
1802 ??? The __divsi3_table label should ideally be moved out
1803 of this block and into a global. If it is placed into the
1804 sdata section we can save even more cycles by doing things
1805 gp relative. */
1806 void
nios2_emit_expensive_div(rtx * operands,machine_mode mode)1807 nios2_emit_expensive_div (rtx *operands, machine_mode mode)
1808 {
1809 rtx or_result, shift_left_result;
1810 rtx lookup_value;
1811 rtx_code_label *lab1, *lab3;
1812 rtx_insn *insns;
1813 rtx libfunc;
1814 rtx final_result;
1815 rtx_insn *tmp;
1816 rtx table;
1817
1818 /* It may look a little generic, but only SImode is supported for now. */
1819 gcc_assert (mode == SImode);
1820 libfunc = optab_libfunc (sdiv_optab, SImode);
1821
1822 lab1 = gen_label_rtx ();
1823 lab3 = gen_label_rtx ();
1824
1825 or_result = expand_simple_binop (SImode, IOR,
1826 operands[1], operands[2],
1827 0, 0, OPTAB_LIB_WIDEN);
1828
1829 emit_cmp_and_jump_insns (or_result, GEN_INT (15), GTU, 0,
1830 GET_MODE (or_result), 0, lab3);
1831 JUMP_LABEL (get_last_insn ()) = lab3;
1832
1833 shift_left_result = expand_simple_binop (SImode, ASHIFT,
1834 operands[1], GEN_INT (4),
1835 0, 0, OPTAB_LIB_WIDEN);
1836
1837 lookup_value = expand_simple_binop (SImode, IOR,
1838 shift_left_result, operands[2],
1839 0, 0, OPTAB_LIB_WIDEN);
1840 table = gen_rtx_PLUS (SImode, lookup_value,
1841 gen_rtx_SYMBOL_REF (SImode, "__divsi3_table"));
1842 convert_move (operands[0], gen_rtx_MEM (QImode, table), 1);
1843
1844 tmp = emit_jump_insn (gen_jump (lab1));
1845 JUMP_LABEL (tmp) = lab1;
1846 emit_barrier ();
1847
1848 emit_label (lab3);
1849 LABEL_NUSES (lab3) = 1;
1850
1851 start_sequence ();
1852 final_result = emit_library_call_value (libfunc, NULL_RTX,
1853 LCT_CONST, SImode,
1854 operands[1], SImode,
1855 operands[2], SImode);
1856
1857 insns = get_insns ();
1858 end_sequence ();
1859 emit_libcall_block (insns, operands[0], final_result,
1860 gen_rtx_DIV (SImode, operands[1], operands[2]));
1861
1862 emit_label (lab1);
1863 LABEL_NUSES (lab1) = 1;
1864 }
1865
1866
1867 /* Branches and compares. */
1868
1869 /* Return in *ALT_CODE and *ALT_OP, an alternate equivalent constant
1870 comparison, e.g. >= 1 into > 0. */
1871 static void
nios2_alternate_compare_const(enum rtx_code code,rtx op,enum rtx_code * alt_code,rtx * alt_op,machine_mode mode)1872 nios2_alternate_compare_const (enum rtx_code code, rtx op,
1873 enum rtx_code *alt_code, rtx *alt_op,
1874 machine_mode mode)
1875 {
1876 gcc_assert (CONST_INT_P (op));
1877
1878 HOST_WIDE_INT opval = INTVAL (op);
1879 enum rtx_code scode = signed_condition (code);
1880 bool dec_p = (scode == LT || scode == GE);
1881
1882 if (code == EQ || code == NE)
1883 {
1884 *alt_code = code;
1885 *alt_op = op;
1886 return;
1887 }
1888
1889 *alt_op = (dec_p
1890 ? gen_int_mode (opval - 1, mode)
1891 : gen_int_mode (opval + 1, mode));
1892
1893 /* The required conversion between [>,>=] and [<,<=] is captured
1894 by a reverse + swap of condition codes. */
1895 *alt_code = reverse_condition (swap_condition (code));
1896
1897 {
1898 /* Test if the incremented/decremented value crosses the over/underflow
1899 boundary. Supposedly, such boundary cases should already be transformed
1900 into always-true/false or EQ conditions, so use an assertion here. */
1901 unsigned HOST_WIDE_INT alt_opval = INTVAL (*alt_op);
1902 if (code == scode)
1903 alt_opval ^= (1 << (GET_MODE_BITSIZE (mode) - 1));
1904 alt_opval &= GET_MODE_MASK (mode);
1905 gcc_assert (dec_p ? alt_opval != GET_MODE_MASK (mode) : alt_opval != 0);
1906 }
1907 }
1908
1909 /* Return true if the constant comparison is supported by nios2. */
1910 static bool
nios2_valid_compare_const_p(enum rtx_code code,rtx op)1911 nios2_valid_compare_const_p (enum rtx_code code, rtx op)
1912 {
1913 gcc_assert (CONST_INT_P (op));
1914 switch (code)
1915 {
1916 case EQ: case NE: case GE: case LT:
1917 return SMALL_INT (INTVAL (op));
1918 case GEU: case LTU:
1919 return SMALL_INT_UNSIGNED (INTVAL (op));
1920 default:
1921 return false;
1922 }
1923 }
1924
1925 /* Checks if the FPU comparison in *CMP, *OP1, and *OP2 can be supported in
1926 the current configuration. Perform modifications if MODIFY_P is true.
1927 Returns true if FPU compare can be done. */
1928
1929 bool
nios2_validate_fpu_compare(machine_mode mode,rtx * cmp,rtx * op1,rtx * op2,bool modify_p)1930 nios2_validate_fpu_compare (machine_mode mode, rtx *cmp, rtx *op1, rtx *op2,
1931 bool modify_p)
1932 {
1933 bool rev_p = false;
1934 enum rtx_code code = GET_CODE (*cmp);
1935
1936 if (!nios2_fpu_compare_enabled (code, mode))
1937 {
1938 code = swap_condition (code);
1939 if (nios2_fpu_compare_enabled (code, mode))
1940 rev_p = true;
1941 else
1942 return false;
1943 }
1944
1945 if (modify_p)
1946 {
1947 if (rev_p)
1948 {
1949 rtx tmp = *op1;
1950 *op1 = *op2;
1951 *op2 = tmp;
1952 }
1953 *op1 = force_reg (mode, *op1);
1954 *op2 = force_reg (mode, *op2);
1955 *cmp = gen_rtx_fmt_ee (code, mode, *op1, *op2);
1956 }
1957 return true;
1958 }
1959
1960 /* Checks and modifies the comparison in *CMP, *OP1, and *OP2 into valid
1961 nios2 supported form. Returns true if success. */
1962 bool
nios2_validate_compare(machine_mode mode,rtx * cmp,rtx * op1,rtx * op2)1963 nios2_validate_compare (machine_mode mode, rtx *cmp, rtx *op1, rtx *op2)
1964 {
1965 enum rtx_code code = GET_CODE (*cmp);
1966 enum rtx_code alt_code;
1967 rtx alt_op2;
1968
1969 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
1970 return nios2_validate_fpu_compare (mode, cmp, op1, op2, true);
1971
1972 if (CONST_INT_P (*op2) && *op2 != const0_rtx)
1973 {
1974 /* Create alternate constant compare. */
1975 nios2_alternate_compare_const (code, *op2, &alt_code, &alt_op2, mode);
1976
1977 /* If alterate op2 is zero(0), we can use it directly, possibly
1978 swapping the compare code. */
1979 if (alt_op2 == const0_rtx)
1980 {
1981 code = alt_code;
1982 *op2 = alt_op2;
1983 goto check_rebuild_cmp;
1984 }
1985
1986 /* Check if either constant compare can be used. */
1987 if (nios2_valid_compare_const_p (code, *op2))
1988 return true;
1989 else if (nios2_valid_compare_const_p (alt_code, alt_op2))
1990 {
1991 code = alt_code;
1992 *op2 = alt_op2;
1993 goto rebuild_cmp;
1994 }
1995
1996 /* We have to force op2 into a register now. Try to pick one
1997 with a lower cost. */
1998 if (! nios2_simple_const_p (*op2)
1999 && nios2_simple_const_p (alt_op2))
2000 {
2001 code = alt_code;
2002 *op2 = alt_op2;
2003 }
2004 *op2 = force_reg (mode, *op2);
2005 }
2006 else if (!reg_or_0_operand (*op2, mode))
2007 *op2 = force_reg (mode, *op2);
2008
2009 check_rebuild_cmp:
2010 if (code == GT || code == GTU || code == LE || code == LEU)
2011 {
2012 rtx t = *op1; *op1 = *op2; *op2 = t;
2013 code = swap_condition (code);
2014 }
2015 rebuild_cmp:
2016 *cmp = gen_rtx_fmt_ee (code, mode, *op1, *op2);
2017 return true;
2018 }
2019
2020
2021 /* Addressing modes and constants. */
2022
2023 /* Symbol references and other 32-bit constants are split into
2024 high/lo_sum pairs during the split1 pass. After that, they are not
2025 considered legitimate addresses.
2026 This function returns true if in a pre-split context where these
2027 constants are allowed. */
2028 static bool
nios2_large_constant_allowed(void)2029 nios2_large_constant_allowed (void)
2030 {
2031 /* The reload_completed check is for the benefit of
2032 nios2_asm_output_mi_thunk and perhaps other places that try to
2033 emulate a post-reload pass. */
2034 return !(cfun->curr_properties & PROP_rtl_split_insns) && !reload_completed;
2035 }
2036
2037 /* Return true if X is constant expression with a reference to an
2038 "ordinary" symbol; not GOT-relative, not GP-relative, not TLS. */
2039 static bool
nios2_symbolic_constant_p(rtx x)2040 nios2_symbolic_constant_p (rtx x)
2041 {
2042 rtx base, offset;
2043
2044 if (flag_pic)
2045 return false;
2046 if (GET_CODE (x) == LABEL_REF)
2047 return true;
2048 else if (CONSTANT_P (x))
2049 {
2050 split_const (x, &base, &offset);
2051 return (SYMBOL_REF_P (base)
2052 && !SYMBOL_REF_TLS_MODEL (base)
2053 && !gprel_constant_p (base)
2054 && !r0rel_constant_p (base)
2055 && SMALL_INT (INTVAL (offset)));
2056 }
2057 return false;
2058 }
2059
2060 /* Return true if X is an expression of the form
2061 (PLUS reg large_constant). */
2062 static bool
nios2_plus_large_constant_p(rtx x)2063 nios2_plus_large_constant_p (rtx x)
2064 {
2065 return (GET_CODE (x) == PLUS
2066 && REG_P (XEXP (x, 0))
2067 && nios2_large_constant_p (XEXP (x, 1)));
2068 }
2069
2070 /* Implement TARGET_LEGITIMATE_CONSTANT_P. */
2071 static bool
nios2_legitimate_constant_p(machine_mode mode ATTRIBUTE_UNUSED,rtx x)2072 nios2_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
2073 {
2074 rtx base, offset;
2075 split_const (x, &base, &offset);
2076 return GET_CODE (base) != SYMBOL_REF || !SYMBOL_REF_TLS_MODEL (base);
2077 }
2078
2079 /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
2080 static bool
nios2_cannot_force_const_mem(machine_mode mode ATTRIBUTE_UNUSED,rtx x)2081 nios2_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
2082 {
2083 return nios2_legitimate_constant_p (mode, x) == false;
2084 }
2085
2086 /* Return true if register REGNO is a valid base register.
2087 STRICT_P is true if REG_OK_STRICT is in effect. */
2088
2089 bool
nios2_regno_ok_for_base_p(int regno,bool strict_p)2090 nios2_regno_ok_for_base_p (int regno, bool strict_p)
2091 {
2092 if (!HARD_REGISTER_NUM_P (regno))
2093 {
2094 if (!strict_p)
2095 return true;
2096
2097 if (!reg_renumber)
2098 return false;
2099
2100 regno = reg_renumber[regno];
2101 }
2102
2103 /* The fake registers will be eliminated to either the stack or
2104 hard frame pointer, both of which are usually valid base registers.
2105 Reload deals with the cases where the eliminated form isn't valid. */
2106 return (GP_REG_P (regno)
2107 || regno == FRAME_POINTER_REGNUM
2108 || regno == ARG_POINTER_REGNUM);
2109 }
2110
2111 /* Return true if OFFSET is permitted in a load/store address expression.
2112 Normally any 16-bit value is permitted, but on R2 if we may be emitting
2113 the IO forms of these instructions we must restrict the offset to fit
2114 in a 12-bit field instead. */
2115
2116 static bool
nios2_valid_addr_offset_p(rtx offset)2117 nios2_valid_addr_offset_p (rtx offset)
2118 {
2119 return (CONST_INT_P (offset)
2120 && ((TARGET_ARCH_R2 && (TARGET_BYPASS_CACHE
2121 || TARGET_BYPASS_CACHE_VOLATILE))
2122 ? SMALL_INT12 (INTVAL (offset))
2123 : SMALL_INT (INTVAL (offset))));
2124 }
2125
2126 /* Return true if the address expression formed by BASE + OFFSET is
2127 valid. */
2128 static bool
nios2_valid_addr_expr_p(rtx base,rtx offset,bool strict_p)2129 nios2_valid_addr_expr_p (rtx base, rtx offset, bool strict_p)
2130 {
2131 if (!strict_p && GET_CODE (base) == SUBREG)
2132 base = SUBREG_REG (base);
2133 return (REG_P (base)
2134 && nios2_regno_ok_for_base_p (REGNO (base), strict_p)
2135 && (offset == NULL_RTX
2136 || nios2_valid_addr_offset_p (offset)
2137 || (nios2_large_constant_allowed ()
2138 && nios2_symbolic_constant_p (offset))
2139 || nios2_unspec_reloc_p (offset)));
2140 }
2141
2142 /* Implement TARGET_LEGITIMATE_ADDRESS_P. */
2143 static bool
nios2_legitimate_address_p(machine_mode mode ATTRIBUTE_UNUSED,rtx operand,bool strict_p)2144 nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
2145 rtx operand, bool strict_p)
2146 {
2147 switch (GET_CODE (operand))
2148 {
2149 /* Direct. */
2150 case SYMBOL_REF:
2151 if (SYMBOL_REF_TLS_MODEL (operand))
2152 return false;
2153
2154 /* Else, fall through. */
2155 case CONST:
2156 if (gprel_constant_p (operand) || r0rel_constant_p (operand))
2157 return true;
2158
2159 /* Else, fall through. */
2160 case LABEL_REF:
2161 if (nios2_large_constant_allowed ()
2162 && nios2_symbolic_constant_p (operand))
2163 return true;
2164 return false;
2165
2166 case CONST_INT:
2167 if (r0rel_constant_p (operand))
2168 return true;
2169 return nios2_large_constant_allowed ();
2170
2171 case CONST_DOUBLE:
2172 return false;
2173
2174 /* Register indirect. */
2175 case REG:
2176 return nios2_regno_ok_for_base_p (REGNO (operand), strict_p);
2177
2178 /* Register indirect with displacement. */
2179 case PLUS:
2180 {
2181 rtx op0 = XEXP (operand, 0);
2182 rtx op1 = XEXP (operand, 1);
2183
2184 if (nios2_valid_addr_expr_p (op0, op1, strict_p)
2185 || nios2_valid_addr_expr_p (op1, op0, strict_p))
2186 return true;
2187 }
2188 break;
2189
2190 /* %lo(constant)(reg)
2191 This requires a 16-bit relocation and isn't valid with R2
2192 io-variant load/stores. */
2193 case LO_SUM:
2194 if (TARGET_ARCH_R2
2195 && (TARGET_BYPASS_CACHE || TARGET_BYPASS_CACHE_VOLATILE))
2196 return false;
2197 else
2198 {
2199 rtx op0 = XEXP (operand, 0);
2200 rtx op1 = XEXP (operand, 1);
2201
2202 return (REG_P (op0)
2203 && nios2_regno_ok_for_base_p (REGNO (op0), strict_p)
2204 && nios2_large_constant_p (op1));
2205 }
2206
2207 default:
2208 break;
2209 }
2210 return false;
2211 }
2212
2213 /* Implement TARGET_ADDRESS_COST.
2214 Experimentation has shown that we get better code by penalizing the
2215 the (plus reg symbolic_constant) and (plus reg (const ...)) forms
2216 but giving (plus reg symbol_ref) address modes the same cost as those
2217 that don't require splitting. Also, from a theoretical point of view:
2218 - This is in line with the recommendation in the GCC internals
2219 documentation to make address forms involving multiple
2220 registers more expensive than single-register forms.
2221 - OTOH it still encourages fwprop1 to propagate constants into
2222 address expressions more aggressively.
2223 - We should discourage splitting (symbol + offset) into hi/lo pairs
2224 to allow CSE'ing the symbol when it's used with more than one offset,
2225 but not so heavily as to avoid this addressing mode at all. */
2226 static int
nios2_address_cost(rtx address,machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as ATTRIBUTE_UNUSED,bool speed ATTRIBUTE_UNUSED)2227 nios2_address_cost (rtx address,
2228 machine_mode mode ATTRIBUTE_UNUSED,
2229 addr_space_t as ATTRIBUTE_UNUSED,
2230 bool speed ATTRIBUTE_UNUSED)
2231 {
2232 if (nios2_plus_large_constant_p (address))
2233 return COSTS_N_INSNS (1);
2234 if (nios2_large_constant_p (address))
2235 {
2236 if (GET_CODE (address) == CONST)
2237 return COSTS_N_INSNS (1);
2238 else
2239 return COSTS_N_INSNS (0);
2240 }
2241 return COSTS_N_INSNS (0);
2242 }
2243
2244 /* Return true if X is a MEM whose address expression involves a large (32-bit)
2245 constant. */
2246 bool
nios2_large_constant_memory_operand_p(rtx x)2247 nios2_large_constant_memory_operand_p (rtx x)
2248 {
2249 rtx addr;
2250
2251 if (GET_CODE (x) != MEM)
2252 return false;
2253 addr = XEXP (x, 0);
2254
2255 return (nios2_large_constant_p (addr)
2256 || nios2_plus_large_constant_p (addr));
2257 }
2258
2259
2260 /* Return true if X is something that needs to be split into a
2261 high/lo_sum pair. */
2262 bool
nios2_large_constant_p(rtx x)2263 nios2_large_constant_p (rtx x)
2264 {
2265 return (nios2_symbolic_constant_p (x)
2266 || nios2_large_unspec_reloc_p (x)
2267 || (CONST_INT_P (x) && !SMALL_INT (INTVAL (x))));
2268 }
2269
2270 /* Given an RTX X that satisfies nios2_large_constant_p, split it into
2271 high and lo_sum parts using TEMP as a scratch register. Emit the high
2272 instruction and return the lo_sum expression.
2273 Also handle special cases involving constant integers. */
2274 rtx
nios2_split_large_constant(rtx x,rtx temp)2275 nios2_split_large_constant (rtx x, rtx temp)
2276 {
2277 if (CONST_INT_P (x))
2278 {
2279 HOST_WIDE_INT val = INTVAL (x);
2280 if (SMALL_INT (val))
2281 return x;
2282 else if (SMALL_INT_UNSIGNED (val) || UPPER16_INT (val))
2283 {
2284 emit_move_insn (temp, x);
2285 return temp;
2286 }
2287 else
2288 {
2289 HOST_WIDE_INT high = (val + 0x8000) & ~0xffff;
2290 HOST_WIDE_INT low = val - high;
2291 emit_move_insn (temp, gen_int_mode (high, Pmode));
2292 return gen_rtx_PLUS (Pmode, temp, gen_int_mode (low, Pmode));
2293 }
2294 }
2295
2296 emit_insn (gen_rtx_SET (temp, gen_rtx_HIGH (Pmode, copy_rtx (x))));
2297 return gen_rtx_LO_SUM (Pmode, temp, copy_rtx (x));
2298 }
2299
2300 /* Split an RTX of the form
2301 (plus op0 op1)
2302 where op1 is a large constant into
2303 (set temp (high op1))
2304 (set temp (plus op0 temp))
2305 (lo_sum temp op1)
2306 returning the lo_sum expression as the value. */
2307 static rtx
nios2_split_plus_large_constant(rtx op0,rtx op1)2308 nios2_split_plus_large_constant (rtx op0, rtx op1)
2309 {
2310 rtx temp = gen_reg_rtx (Pmode);
2311 op0 = force_reg (Pmode, op0);
2312
2313 emit_insn (gen_rtx_SET (temp, gen_rtx_HIGH (Pmode, copy_rtx (op1))));
2314 emit_insn (gen_rtx_SET (temp, gen_rtx_PLUS (Pmode, op0, temp)));
2315 return gen_rtx_LO_SUM (Pmode, temp, copy_rtx (op1));
2316 }
2317
2318 /* Given a MEM OP with an address that includes a splittable symbol or
2319 other large constant, emit some instructions to do the split and
2320 return a new MEM. */
2321 rtx
nios2_split_large_constant_memory_operand(rtx op)2322 nios2_split_large_constant_memory_operand (rtx op)
2323 {
2324 rtx addr = XEXP (op, 0);
2325
2326 if (nios2_large_constant_p (addr))
2327 addr = nios2_split_large_constant (addr, gen_reg_rtx (Pmode));
2328 else if (nios2_plus_large_constant_p (addr))
2329 addr = nios2_split_plus_large_constant (XEXP (addr, 0), XEXP (addr, 1));
2330 else
2331 gcc_unreachable ();
2332 return replace_equiv_address (op, addr, false);
2333 }
2334
2335 /* Return true if SECTION is a small section name. */
2336 static bool
nios2_small_section_name_p(const char * section)2337 nios2_small_section_name_p (const char *section)
2338 {
2339 return (strcmp (section, ".sbss") == 0
2340 || startswith (section, ".sbss.")
2341 || strcmp (section, ".sdata") == 0
2342 || startswith (section, ".sdata.")
2343 || (nios2_gprel_sec
2344 && regexec (&nios2_gprel_sec_regex, section, 0, NULL, 0) == 0));
2345 }
2346
2347 /* Return true if SECTION is a r0-relative section name. */
2348 static bool
nios2_r0rel_section_name_p(const char * section)2349 nios2_r0rel_section_name_p (const char *section)
2350 {
2351 return (nios2_r0rel_sec
2352 && regexec (&nios2_r0rel_sec_regex, section, 0, NULL, 0) == 0);
2353 }
2354
2355 /* Return true if EXP should be placed in the small data section. */
2356 static bool
nios2_in_small_data_p(const_tree exp)2357 nios2_in_small_data_p (const_tree exp)
2358 {
2359 /* We want to merge strings, so we never consider them small data. */
2360 if (TREE_CODE (exp) == STRING_CST)
2361 return false;
2362
2363 if (TREE_CODE (exp) == VAR_DECL)
2364 {
2365 if (DECL_SECTION_NAME (exp))
2366 {
2367 const char *section = DECL_SECTION_NAME (exp);
2368 if (nios2_small_section_name_p (section))
2369 return true;
2370 }
2371 else if (flexible_array_type_p (TREE_TYPE (exp))
2372 && (!TREE_PUBLIC (exp) || DECL_EXTERNAL (exp)))
2373 {
2374 /* We really should not consider any objects of any flexibly-sized
2375 type to be small data, but pre-GCC 10 did not test
2376 for this and just fell through to the next case. Thus older
2377 code compiled with -mgpopt=global could contain GP-relative
2378 accesses to objects defined in this compilation unit with
2379 external linkage. We retain the possible small-data treatment
2380 of such definitions for backward ABI compatibility, but
2381 no longer generate GP-relative accesses for external
2382 references (so that the ABI could be changed in the future
2383 with less potential impact), or objects with internal
2384 linkage. */
2385 return false;
2386 }
2387 else
2388 {
2389 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
2390
2391 /* If this is an incomplete type with size 0, then we can't put it
2392 in sdata because it might be too big when completed. */
2393 if (size > 0
2394 && (unsigned HOST_WIDE_INT) size <= nios2_section_threshold)
2395 return true;
2396 }
2397 }
2398
2399 return false;
2400 }
2401
2402 /* Return true if symbol is in small data section. */
2403
2404 static bool
nios2_symbol_ref_in_small_data_p(rtx sym)2405 nios2_symbol_ref_in_small_data_p (rtx sym)
2406 {
2407 tree decl;
2408
2409 gcc_assert (GET_CODE (sym) == SYMBOL_REF);
2410 decl = SYMBOL_REF_DECL (sym);
2411
2412 /* TLS variables are not accessed through the GP. */
2413 if (SYMBOL_REF_TLS_MODEL (sym) != 0)
2414 return false;
2415
2416 /* On Nios II R2, there is no GP-relative relocation that can be
2417 used with "io" instructions. So, if we are implicitly generating
2418 those instructions, we cannot emit GP-relative accesses. */
2419 if (TARGET_ARCH_R2
2420 && (TARGET_BYPASS_CACHE || TARGET_BYPASS_CACHE_VOLATILE))
2421 return false;
2422
2423 /* If the user has explicitly placed the symbol in a small data section
2424 via an attribute, generate gp-relative addressing even if the symbol
2425 is external, weak, or larger than we'd automatically put in the
2426 small data section. OTOH, if the symbol is located in some
2427 non-small-data section, we can't use gp-relative accesses on it
2428 unless the user has requested gpopt_data or gpopt_all. */
2429
2430 switch (nios2_gpopt_option)
2431 {
2432 case gpopt_none:
2433 /* Don't generate a gp-relative addressing mode if that's been
2434 disabled. */
2435 return false;
2436
2437 case gpopt_local:
2438 /* Use GP-relative addressing for small data symbols that are
2439 not external or weak or uninitialized common, plus any symbols
2440 that have explicitly been placed in a small data section. */
2441 if (decl && DECL_SECTION_NAME (decl))
2442 return nios2_small_section_name_p (DECL_SECTION_NAME (decl));
2443 return (SYMBOL_REF_SMALL_P (sym)
2444 && !SYMBOL_REF_EXTERNAL_P (sym)
2445 && !(decl && DECL_WEAK (decl))
2446 && !(decl && DECL_COMMON (decl)
2447 && (DECL_INITIAL (decl) == NULL
2448 || (!in_lto_p
2449 && DECL_INITIAL (decl) == error_mark_node))));
2450
2451 case gpopt_global:
2452 /* Use GP-relative addressing for small data symbols, even if
2453 they are external or weak. Note that SYMBOL_REF_SMALL_P
2454 is also true of symbols that have explicitly been placed
2455 in a small data section. */
2456 return SYMBOL_REF_SMALL_P (sym);
2457
2458 case gpopt_data:
2459 /* Use GP-relative addressing for all data symbols regardless
2460 of the object size, but not for code symbols. This option
2461 is equivalent to the user asserting that the entire data
2462 section is accessible from the GP. */
2463 return !SYMBOL_REF_FUNCTION_P (sym);
2464
2465 case gpopt_all:
2466 /* Use GP-relative addressing for everything, including code.
2467 Effectively, the user has asserted that the entire program
2468 fits within the 64K range of the GP offset. */
2469 return true;
2470
2471 default:
2472 /* We shouldn't get here. */
2473 return false;
2474 }
2475 }
2476
2477 /* Likewise for r0-relative addressing. */
2478 static bool
nios2_symbol_ref_in_r0rel_data_p(rtx sym)2479 nios2_symbol_ref_in_r0rel_data_p (rtx sym)
2480 {
2481 tree decl;
2482
2483 gcc_assert (GET_CODE (sym) == SYMBOL_REF);
2484 decl = SYMBOL_REF_DECL (sym);
2485
2486 /* TLS variables are not accessed through r0. */
2487 if (SYMBOL_REF_TLS_MODEL (sym) != 0)
2488 return false;
2489
2490 /* On Nios II R2, there is no r0-relative relocation that can be
2491 used with "io" instructions. So, if we are implicitly generating
2492 those instructions, we cannot emit r0-relative accesses. */
2493 if (TARGET_ARCH_R2
2494 && (TARGET_BYPASS_CACHE || TARGET_BYPASS_CACHE_VOLATILE))
2495 return false;
2496
2497 /* If the user has explicitly placed the symbol in a r0rel section
2498 via an attribute, generate r0-relative addressing. */
2499 if (decl && DECL_SECTION_NAME (decl))
2500 return nios2_r0rel_section_name_p (DECL_SECTION_NAME (decl));
2501 return false;
2502 }
2503
2504 /* Implement TARGET_SECTION_TYPE_FLAGS. */
2505
2506 static unsigned int
nios2_section_type_flags(tree decl,const char * name,int reloc)2507 nios2_section_type_flags (tree decl, const char *name, int reloc)
2508 {
2509 unsigned int flags;
2510
2511 flags = default_section_type_flags (decl, name, reloc);
2512
2513 if (nios2_small_section_name_p (name))
2514 flags |= SECTION_SMALL;
2515
2516 return flags;
2517 }
2518
2519 /* Return true if SYMBOL_REF X binds locally. */
2520
2521 static bool
nios2_symbol_binds_local_p(const_rtx x)2522 nios2_symbol_binds_local_p (const_rtx x)
2523 {
2524 return (SYMBOL_REF_DECL (x)
2525 ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
2526 : SYMBOL_REF_LOCAL_P (x));
2527 }
2528
2529 /* Position independent code related. */
2530
2531 /* Emit code to load the PIC register. */
2532 static void
nios2_load_pic_register(void)2533 nios2_load_pic_register (void)
2534 {
2535 rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
2536
2537 emit_insn (gen_load_got_register (pic_offset_table_rtx, tmp));
2538 emit_insn (gen_add3_insn (pic_offset_table_rtx, pic_offset_table_rtx, tmp));
2539 }
2540
2541 /* Generate a PIC address as a MEM rtx. */
2542 static rtx
nios2_load_pic_address(rtx sym,int unspec,rtx tmp)2543 nios2_load_pic_address (rtx sym, int unspec, rtx tmp)
2544 {
2545 if (flag_pic == 2
2546 && GET_CODE (sym) == SYMBOL_REF
2547 && nios2_symbol_binds_local_p (sym))
2548 /* Under -fPIC, generate a GOTOFF address for local symbols. */
2549 {
2550 rtx offset = nios2_unspec_offset (sym, UNSPEC_PIC_GOTOFF_SYM);
2551 crtl->uses_pic_offset_table = 1;
2552 return nios2_large_got_address (offset, tmp);
2553 }
2554
2555 return gen_const_mem (Pmode, nios2_got_address (sym, unspec));
2556 }
2557
2558 /* Nonzero if the constant value X is a legitimate general operand
2559 when generating PIC code. It is given that flag_pic is on and
2560 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
2561 bool
nios2_legitimate_pic_operand_p(rtx x)2562 nios2_legitimate_pic_operand_p (rtx x)
2563 {
2564 if (nios2_large_unspec_reloc_p (x))
2565 return true;
2566
2567 return ! (GET_CODE (x) == SYMBOL_REF
2568 || GET_CODE (x) == LABEL_REF || GET_CODE (x) == CONST);
2569 }
2570
2571 /* Return TRUE if X is a thread-local symbol. */
2572 static bool
nios2_tls_symbol_p(rtx x)2573 nios2_tls_symbol_p (rtx x)
2574 {
2575 return (targetm.have_tls && GET_CODE (x) == SYMBOL_REF
2576 && SYMBOL_REF_TLS_MODEL (x) != 0);
2577 }
2578
2579 /* Legitimize addresses that are CONSTANT_P expressions. */
2580 static rtx
nios2_legitimize_constant_address(rtx addr)2581 nios2_legitimize_constant_address (rtx addr)
2582 {
2583 rtx base, offset;
2584 split_const (addr, &base, &offset);
2585
2586 if (nios2_tls_symbol_p (base))
2587 base = nios2_legitimize_tls_address (base);
2588 else if (flag_pic)
2589 base = nios2_load_pic_address (base, UNSPEC_PIC_SYM, NULL_RTX);
2590 else if (!nios2_large_constant_allowed ()
2591 && nios2_symbolic_constant_p (addr))
2592 return nios2_split_large_constant (addr, gen_reg_rtx (Pmode));
2593 else if (CONST_INT_P (addr))
2594 {
2595 HOST_WIDE_INT val = INTVAL (addr);
2596 if (SMALL_INT (val))
2597 /* Use r0-relative addressing. */
2598 return addr;
2599 else if (!nios2_large_constant_allowed ())
2600 /* Split into high/lo pair. */
2601 return nios2_split_large_constant (addr, gen_reg_rtx (Pmode));
2602 }
2603 else
2604 return addr;
2605
2606 if (offset != const0_rtx)
2607 {
2608 gcc_assert (can_create_pseudo_p ());
2609 return gen_rtx_PLUS (Pmode, force_reg (Pmode, base),
2610 (CONST_INT_P (offset)
2611 ? (SMALL_INT (INTVAL (offset))
2612 ? offset : force_reg (Pmode, offset))
2613 : offset));
2614 }
2615 return base;
2616 }
2617
2618 /* Implement TARGET_LEGITIMIZE_ADDRESS. */
2619 static rtx
nios2_legitimize_address(rtx x,rtx oldx ATTRIBUTE_UNUSED,machine_mode mode ATTRIBUTE_UNUSED)2620 nios2_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
2621 machine_mode mode ATTRIBUTE_UNUSED)
2622 {
2623 rtx op0, op1;
2624
2625 if (CONSTANT_P (x))
2626 return nios2_legitimize_constant_address (x);
2627
2628 /* Remaining cases all involve something + a constant. */
2629 if (GET_CODE (x) != PLUS)
2630 return x;
2631
2632 op0 = XEXP (x, 0);
2633 op1 = XEXP (x, 1);
2634
2635 /* Target-independent code turns (exp + constant) into plain
2636 register indirect. Although subsequent optimization passes will
2637 eventually sort that out, ivopts uses the unoptimized form for
2638 computing its cost model, so we get better results by generating
2639 the correct form from the start. */
2640 if (nios2_valid_addr_offset_p (op1))
2641 return gen_rtx_PLUS (Pmode, force_reg (Pmode, op0), copy_rtx (op1));
2642
2643 /* We may need to split symbolic constants now. */
2644 else if (nios2_symbolic_constant_p (op1))
2645 {
2646 if (nios2_large_constant_allowed ())
2647 return gen_rtx_PLUS (Pmode, force_reg (Pmode, op0), copy_rtx (op1));
2648 else
2649 return nios2_split_plus_large_constant (op0, op1);
2650 }
2651
2652 /* For the TLS LE (Local Exec) model, the compiler may try to
2653 combine constant offsets with unspec relocs, creating address RTXs
2654 looking like this:
2655 (plus:SI (reg:SI 23 r23)
2656 (const:SI
2657 (plus:SI
2658 (unspec:SI [(symbol_ref:SI ("var"))] UNSPEC_ADD_TLS_LE)
2659 (const_int 48 [0x30]))))
2660
2661 This usually happens when 'var' is a thread-local struct variable,
2662 and access of a field in var causes the addend.
2663
2664 We typically want this combining, so transform the above into this
2665 form, which is allowed:
2666 (plus:SI (reg:SI 23 r23)
2667 (const:SI
2668 (unspec:SI
2669 [(const:SI
2670 (plus:SI (symbol_ref:SI ("var"))
2671 (const_int 48 [0x30])))] UNSPEC_ADD_TLS_LE)))
2672
2673 Which will be output as '%tls_le(var+48)(r23)' in assembly. */
2674 else if (GET_CODE (op1) == CONST)
2675 {
2676 rtx unspec, offset;
2677 split_const (op1, &unspec, &offset);
2678 if (GET_CODE (unspec) == UNSPEC
2679 && !nios2_large_offset_p (XINT (unspec, 1))
2680 && offset != const0_rtx)
2681 {
2682 rtx reg = force_reg (Pmode, op0);
2683 unspec = copy_rtx (unspec);
2684 XVECEXP (unspec, 0, 0)
2685 = plus_constant (Pmode, XVECEXP (unspec, 0, 0), INTVAL (offset));
2686 return gen_rtx_PLUS (Pmode, reg, gen_rtx_CONST (Pmode, unspec));
2687 }
2688 }
2689
2690 return x;
2691 }
2692
2693 static rtx
nios2_delegitimize_address(rtx x)2694 nios2_delegitimize_address (rtx x)
2695 {
2696 x = delegitimize_mem_from_attrs (x);
2697
2698 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC)
2699 {
2700 switch (XINT (XEXP (x, 0), 1))
2701 {
2702 case UNSPEC_PIC_SYM:
2703 case UNSPEC_PIC_CALL_SYM:
2704 case UNSPEC_PIC_GOTOFF_SYM:
2705 case UNSPEC_ADD_TLS_GD:
2706 case UNSPEC_ADD_TLS_LDM:
2707 case UNSPEC_LOAD_TLS_IE:
2708 case UNSPEC_ADD_TLS_LE:
2709 x = XVECEXP (XEXP (x, 0), 0, 0);
2710 gcc_assert (CONSTANT_P (x));
2711 break;
2712 }
2713 }
2714 return x;
2715 }
2716
2717 /* Main expander function for RTL moves. */
2718 bool
nios2_emit_move_sequence(rtx * operands,machine_mode mode)2719 nios2_emit_move_sequence (rtx *operands, machine_mode mode)
2720 {
2721 rtx to = operands[0];
2722 rtx from = operands[1];
2723
2724 if (!register_operand (to, mode) && !reg_or_0_operand (from, mode))
2725 {
2726 gcc_assert (can_create_pseudo_p ());
2727 from = copy_to_mode_reg (mode, from);
2728 }
2729
2730 if (CONSTANT_P (from))
2731 {
2732 if (CONST_INT_P (from))
2733 {
2734 if (!SMALL_INT (INTVAL (from))
2735 && !SMALL_INT_UNSIGNED (INTVAL (from))
2736 && !UPPER16_INT (INTVAL (from)))
2737 {
2738 HOST_WIDE_INT high = (INTVAL (from) + 0x8000) & ~0xffff;
2739 HOST_WIDE_INT low = INTVAL (from) & 0xffff;
2740 emit_move_insn (to, gen_int_mode (high, SImode));
2741 emit_insn (gen_add2_insn (to, gen_int_mode (low, HImode)));
2742 set_unique_reg_note (get_last_insn (), REG_EQUAL,
2743 copy_rtx (from));
2744 return true;
2745 }
2746 }
2747 else if (gprel_constant_p (from) || r0rel_constant_p (from))
2748 /* Handled directly by movsi_internal as gp + offset
2749 or r0 + offset. */
2750 ;
2751 else if (nios2_large_constant_p (from))
2752 /* This case covers either a regular symbol reference or an UNSPEC
2753 representing a 32-bit offset. We split the former
2754 only conditionally and the latter always. */
2755 {
2756 if (!nios2_large_constant_allowed ()
2757 || nios2_large_unspec_reloc_p (from))
2758 {
2759 rtx lo = nios2_split_large_constant (from, to);
2760 emit_insn (gen_rtx_SET (to, lo));
2761 set_unique_reg_note (get_last_insn (), REG_EQUAL,
2762 copy_rtx (operands[1]));
2763 return true;
2764 }
2765 }
2766 else
2767 /* This is a TLS or PIC symbol. */
2768 {
2769 from = nios2_legitimize_constant_address (from);
2770 if (CONSTANT_P (from))
2771 {
2772 emit_insn (gen_rtx_SET (to,
2773 gen_rtx_HIGH (Pmode, copy_rtx (from))));
2774 emit_insn (gen_rtx_SET (to, gen_rtx_LO_SUM (Pmode, to, from)));
2775 set_unique_reg_note (get_last_insn (), REG_EQUAL,
2776 copy_rtx (operands[1]));
2777 return true;
2778 }
2779 }
2780 }
2781
2782 operands[0] = to;
2783 operands[1] = from;
2784 return false;
2785 }
2786
2787 /* The function with address *ADDR is being called. If the address
2788 needs to be loaded from the GOT, emit the instruction to do so and
2789 update *ADDR to point to the rtx for the loaded value.
2790 If REG != NULL_RTX, it is used as the target/scratch register in the
2791 GOT address calculation. */
2792 void
nios2_adjust_call_address(rtx * call_op,rtx reg)2793 nios2_adjust_call_address (rtx *call_op, rtx reg)
2794 {
2795 if (MEM_P (*call_op))
2796 call_op = &XEXP (*call_op, 0);
2797
2798 rtx addr = *call_op;
2799 if (flag_pic && CONSTANT_P (addr))
2800 {
2801 rtx tmp = reg ? reg : NULL_RTX;
2802 if (!reg)
2803 reg = gen_reg_rtx (Pmode);
2804 addr = nios2_load_pic_address (addr, UNSPEC_PIC_CALL_SYM, tmp);
2805 emit_insn (gen_rtx_SET (reg, addr));
2806 *call_op = reg;
2807 }
2808 }
2809
2810
2811 /* Output assembly language related definitions. */
2812
2813 /* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P. */
2814 static bool
nios2_print_operand_punct_valid_p(unsigned char code)2815 nios2_print_operand_punct_valid_p (unsigned char code)
2816 {
2817 return (code == '.' || code == '!');
2818 }
2819
2820
2821 /* Print the operand OP to file stream FILE modified by LETTER.
2822 LETTER can be one of:
2823
2824 i: print i/hi/ui suffixes (used for mov instruction variants),
2825 when OP is the appropriate immediate operand.
2826
2827 u: like 'i', except without "ui" suffix case (used for cmpgeu/cmpltu)
2828
2829 o: print "io" if OP needs volatile access (due to TARGET_BYPASS_CACHE
2830 or TARGET_BYPASS_CACHE_VOLATILE).
2831
2832 x: print i/hi/ci/chi suffixes for the and instruction,
2833 when OP is the appropriate immediate operand.
2834
2835 z: prints the third register immediate operand in assembly
2836 instructions. Outputs const0_rtx as the 'zero' register
2837 instead of '0'.
2838
2839 y: same as 'z', but for specifically for logical instructions,
2840 where the processing for immediates are slightly different.
2841
2842 H: for %hiadj
2843 L: for %lo
2844 D: for the upper 32-bits of a 64-bit double value
2845 R: prints reverse condition.
2846 A: prints (reg) operand for ld[s]ex and st[s]ex.
2847
2848 .: print .n suffix for 16-bit instructions.
2849 !: print r.n suffix for 16-bit instructions. Used for jmpr.n.
2850 */
2851 static void
nios2_print_operand(FILE * file,rtx op,int letter)2852 nios2_print_operand (FILE *file, rtx op, int letter)
2853 {
2854
2855 /* First take care of the format letters that just insert a string
2856 into the output stream. */
2857 switch (letter)
2858 {
2859 case '.':
2860 if (current_output_insn && get_attr_length (current_output_insn) == 2)
2861 fprintf (file, ".n");
2862 return;
2863
2864 case '!':
2865 if (current_output_insn && get_attr_length (current_output_insn) == 2)
2866 fprintf (file, "r.n");
2867 return;
2868
2869 case 'x':
2870 if (CONST_INT_P (op))
2871 {
2872 HOST_WIDE_INT val = INTVAL (op);
2873 HOST_WIDE_INT low = val & 0xffff;
2874 HOST_WIDE_INT high = (val >> 16) & 0xffff;
2875
2876 if (val != 0)
2877 {
2878 if (high != 0)
2879 {
2880 if (low != 0)
2881 {
2882 gcc_assert (TARGET_ARCH_R2);
2883 if (high == 0xffff)
2884 fprintf (file, "c");
2885 else if (low == 0xffff)
2886 fprintf (file, "ch");
2887 else
2888 gcc_unreachable ();
2889 }
2890 else
2891 fprintf (file, "h");
2892 }
2893 fprintf (file, "i");
2894 }
2895 }
2896 return;
2897
2898 case 'u':
2899 case 'i':
2900 if (CONST_INT_P (op))
2901 {
2902 HOST_WIDE_INT val = INTVAL (op);
2903 HOST_WIDE_INT low = val & 0xffff;
2904 HOST_WIDE_INT high = (val >> 16) & 0xffff;
2905 if (val != 0)
2906 {
2907 if (low == 0 && high != 0)
2908 fprintf (file, "h");
2909 else if (high == 0 && (low & 0x8000) != 0 && letter != 'u')
2910 fprintf (file, "u");
2911 }
2912 }
2913 if (CONSTANT_P (op) && op != const0_rtx)
2914 fprintf (file, "i");
2915 return;
2916
2917 case 'o':
2918 if (GET_CODE (op) == MEM
2919 && ((MEM_VOLATILE_P (op) && TARGET_BYPASS_CACHE_VOLATILE)
2920 || TARGET_BYPASS_CACHE))
2921 {
2922 gcc_assert (current_output_insn
2923 && get_attr_length (current_output_insn) == 4);
2924 fprintf (file, "io");
2925 }
2926 return;
2927
2928 default:
2929 break;
2930 }
2931
2932 /* Handle comparison operator names. */
2933 if (comparison_operator (op, VOIDmode))
2934 {
2935 enum rtx_code cond = GET_CODE (op);
2936 if (letter == 0)
2937 {
2938 fprintf (file, "%s", GET_RTX_NAME (cond));
2939 return;
2940 }
2941 if (letter == 'R')
2942 {
2943 fprintf (file, "%s", GET_RTX_NAME (reverse_condition (cond)));
2944 return;
2945 }
2946 }
2947
2948 /* Now handle the cases where we actually need to format an operand. */
2949 switch (GET_CODE (op))
2950 {
2951 case REG:
2952 if (letter == 0 || letter == 'z' || letter == 'y')
2953 {
2954 fprintf (file, "%s", reg_names[REGNO (op)]);
2955 return;
2956 }
2957 else if (letter == 'D')
2958 {
2959 fprintf (file, "%s", reg_names[REGNO (op)+1]);
2960 return;
2961 }
2962 break;
2963
2964 case CONST_INT:
2965 {
2966 rtx int_rtx = op;
2967 HOST_WIDE_INT val = INTVAL (int_rtx);
2968 HOST_WIDE_INT low = val & 0xffff;
2969 HOST_WIDE_INT high = (val >> 16) & 0xffff;
2970
2971 if (letter == 'y')
2972 {
2973 if (val == 0)
2974 fprintf (file, "zero");
2975 else
2976 {
2977 if (high != 0)
2978 {
2979 if (low != 0)
2980 {
2981 gcc_assert (TARGET_ARCH_R2);
2982 if (high == 0xffff)
2983 /* andci. */
2984 int_rtx = gen_int_mode (low, SImode);
2985 else if (low == 0xffff)
2986 /* andchi. */
2987 int_rtx = gen_int_mode (high, SImode);
2988 else
2989 gcc_unreachable ();
2990 }
2991 else
2992 /* andhi. */
2993 int_rtx = gen_int_mode (high, SImode);
2994 }
2995 else
2996 /* andi. */
2997 int_rtx = gen_int_mode (low, SImode);
2998 output_addr_const (file, int_rtx);
2999 }
3000 return;
3001 }
3002 else if (letter == 'z')
3003 {
3004 if (val == 0)
3005 fprintf (file, "zero");
3006 else
3007 {
3008 if (low == 0 && high != 0)
3009 int_rtx = gen_int_mode (high, SImode);
3010 else if (low != 0)
3011 {
3012 gcc_assert (high == 0 || high == 0xffff);
3013 int_rtx = gen_int_mode (low, high == 0 ? SImode : HImode);
3014 }
3015 else
3016 gcc_unreachable ();
3017 output_addr_const (file, int_rtx);
3018 }
3019 return;
3020 }
3021 }
3022
3023 /* Else, fall through. */
3024
3025 case CONST:
3026 case LABEL_REF:
3027 case SYMBOL_REF:
3028 case CONST_DOUBLE:
3029 if (letter == 0 || letter == 'z')
3030 {
3031 output_addr_const (file, op);
3032 return;
3033 }
3034 else if (letter == 'H' || letter == 'L')
3035 {
3036 fprintf (file, "%%");
3037 if (GET_CODE (op) == CONST
3038 && GET_CODE (XEXP (op, 0)) == UNSPEC)
3039 {
3040 rtx unspec = XEXP (op, 0);
3041 int unspec_reloc = XINT (unspec, 1);
3042 gcc_assert (nios2_large_offset_p (unspec_reloc));
3043 fprintf (file, "%s_", nios2_unspec_reloc_name (unspec_reloc));
3044 op = XVECEXP (unspec, 0, 0);
3045 }
3046 fprintf (file, letter == 'H' ? "hiadj(" : "lo(");
3047 output_addr_const (file, op);
3048 fprintf (file, ")");
3049 return;
3050 }
3051 break;
3052
3053 case SUBREG:
3054 case MEM:
3055 if (letter == 'A')
3056 {
3057 /* Address of '(reg)' form, with no index. */
3058 fprintf (file, "(%s)", reg_names[REGNO (XEXP (op, 0))]);
3059 return;
3060 }
3061 if (letter == 0)
3062 {
3063 output_address (VOIDmode, op);
3064 return;
3065 }
3066 break;
3067
3068 case CODE_LABEL:
3069 if (letter == 0)
3070 {
3071 output_addr_const (file, op);
3072 return;
3073 }
3074 break;
3075
3076 default:
3077 break;
3078 }
3079
3080 debug_rtx (op);
3081 output_operand_lossage ("Unsupported operand for code '%c'", letter);
3082 gcc_unreachable ();
3083 }
3084
3085 /* Return true if this is a GP-relative accessible reference. */
3086 bool
gprel_constant_p(rtx op)3087 gprel_constant_p (rtx op)
3088 {
3089 if (GET_CODE (op) == SYMBOL_REF
3090 && nios2_symbol_ref_in_small_data_p (op))
3091 return true;
3092 else if (GET_CODE (op) == CONST
3093 && GET_CODE (XEXP (op, 0)) == PLUS)
3094 return gprel_constant_p (XEXP (XEXP (op, 0), 0));
3095
3096 return false;
3097 }
3098
3099 /* Likewise if this is a zero-relative accessible reference. */
3100 bool
r0rel_constant_p(rtx op)3101 r0rel_constant_p (rtx op)
3102 {
3103 if (GET_CODE (op) == SYMBOL_REF
3104 && nios2_symbol_ref_in_r0rel_data_p (op))
3105 return true;
3106 else if (GET_CODE (op) == CONST
3107 && GET_CODE (XEXP (op, 0)) == PLUS)
3108 return r0rel_constant_p (XEXP (XEXP (op, 0), 0));
3109 else if (GET_CODE (op) == CONST_INT
3110 && SMALL_INT (INTVAL (op)))
3111 return true;
3112
3113 return false;
3114 }
3115
3116 /* Return the name string for a supported unspec reloc offset. */
3117 static const char *
nios2_unspec_reloc_name(int unspec)3118 nios2_unspec_reloc_name (int unspec)
3119 {
3120 switch (unspec)
3121 {
3122 case UNSPEC_PIC_SYM:
3123 return "got";
3124 case UNSPEC_PIC_CALL_SYM:
3125 return "call";
3126 case UNSPEC_PIC_GOTOFF_SYM:
3127 return "gotoff";
3128 case UNSPEC_LOAD_TLS_IE:
3129 return "tls_ie";
3130 case UNSPEC_ADD_TLS_LE:
3131 return "tls_le";
3132 case UNSPEC_ADD_TLS_GD:
3133 return "tls_gd";
3134 case UNSPEC_ADD_TLS_LDM:
3135 return "tls_ldm";
3136 case UNSPEC_ADD_TLS_LDO:
3137 return "tls_ldo";
3138 default:
3139 return NULL;
3140 }
3141 }
3142
3143 /* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */
3144 static bool
nios2_output_addr_const_extra(FILE * file,rtx op)3145 nios2_output_addr_const_extra (FILE *file, rtx op)
3146 {
3147 const char *name;
3148 gcc_assert (GET_CODE (op) == UNSPEC);
3149
3150 /* Support for printing out const unspec relocations. */
3151 name = nios2_unspec_reloc_name (XINT (op, 1));
3152 if (name)
3153 {
3154 fprintf (file, "%%%s(", name);
3155 output_addr_const (file, XVECEXP (op, 0, 0));
3156 fprintf (file, ")");
3157 return true;
3158 }
3159 return false;
3160 }
3161
3162 /* Implement TARGET_PRINT_OPERAND_ADDRESS. */
3163 static void
nios2_print_operand_address(FILE * file,machine_mode mode,rtx op)3164 nios2_print_operand_address (FILE *file, machine_mode mode, rtx op)
3165 {
3166 switch (GET_CODE (op))
3167 {
3168 case CONST:
3169 case CONST_INT:
3170 case LABEL_REF:
3171 case CONST_DOUBLE:
3172 case SYMBOL_REF:
3173 if (gprel_constant_p (op))
3174 {
3175 fprintf (file, "%%gprel(");
3176 output_addr_const (file, op);
3177 fprintf (file, ")(%s)", reg_names[GP_REGNO]);
3178 return;
3179 }
3180 else if (r0rel_constant_p (op))
3181 {
3182 if (CONST_INT_P (op))
3183 {
3184 output_addr_const (file, op);
3185 fprintf (file, "(r0)");
3186 return;
3187 }
3188 else
3189 {
3190 fprintf (file, "%%lo(");
3191 output_addr_const (file, op);
3192 fprintf (file, ")(r0)");
3193 return;
3194 }
3195 }
3196 break;
3197
3198 case PLUS:
3199 {
3200 rtx op0 = XEXP (op, 0);
3201 rtx op1 = XEXP (op, 1);
3202
3203 if (REG_P (op0) && CONSTANT_P (op1))
3204 {
3205 output_addr_const (file, op1);
3206 fprintf (file, "(%s)", reg_names[REGNO (op0)]);
3207 return;
3208 }
3209 else if (REG_P (op1) && CONSTANT_P (op0))
3210 {
3211 output_addr_const (file, op0);
3212 fprintf (file, "(%s)", reg_names[REGNO (op1)]);
3213 return;
3214 }
3215 }
3216 break;
3217
3218 case LO_SUM:
3219 {
3220 rtx op0 = XEXP (op, 0);
3221 rtx op1 = XEXP (op, 1);
3222
3223 if (REG_P (op0) && CONSTANT_P (op1))
3224 {
3225 nios2_print_operand (file, op1, 'L');
3226 fprintf (file, "(%s)", reg_names[REGNO (op0)]);
3227 return;
3228 }
3229 }
3230 break;
3231
3232 case REG:
3233 fprintf (file, "0(%s)", reg_names[REGNO (op)]);
3234 return;
3235
3236 case MEM:
3237 {
3238 rtx base = XEXP (op, 0);
3239 nios2_print_operand_address (file, mode, base);
3240 return;
3241 }
3242 default:
3243 break;
3244 }
3245
3246 fprintf (stderr, "Missing way to print address\n");
3247 debug_rtx (op);
3248 gcc_unreachable ();
3249 }
3250
3251 /* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL. */
3252 static void
nios2_output_dwarf_dtprel(FILE * file,int size,rtx x)3253 nios2_output_dwarf_dtprel (FILE *file, int size, rtx x)
3254 {
3255 gcc_assert (size == 4);
3256 fprintf (file, "\t.4byte\t%%tls_ldo(");
3257 output_addr_const (file, x);
3258 fprintf (file, ")");
3259 }
3260
3261 /* Implemet TARGET_ASM_FILE_END. */
3262
3263 static void
nios2_asm_file_end(void)3264 nios2_asm_file_end (void)
3265 {
3266 /* The Nios II Linux stack is mapped non-executable by default, so add a
3267 .note.GNU-stack section for switching to executable stacks only when
3268 trampolines are generated. */
3269 if (TARGET_LINUX_ABI && trampolines_created)
3270 file_end_indicate_exec_stack ();
3271 }
3272
3273 /* Implement TARGET_ASM_FUNCTION_PROLOGUE. */
3274 static void
nios2_asm_function_prologue(FILE * file)3275 nios2_asm_function_prologue (FILE *file)
3276 {
3277 if (flag_verbose_asm || flag_debug_asm)
3278 {
3279 nios2_compute_frame_layout ();
3280 nios2_dump_frame_layout (file);
3281 }
3282 }
3283
3284 /* Emit assembly of custom FPU instructions. */
3285 const char *
nios2_fpu_insn_asm(enum n2fpu_code code)3286 nios2_fpu_insn_asm (enum n2fpu_code code)
3287 {
3288 static char buf[256];
3289 const char *op1, *op2, *op3;
3290 int ln = 256, n = 0;
3291
3292 int N = N2FPU_N (code);
3293 int num_operands = N2FPU (code).num_operands;
3294 const char *insn_name = N2FPU_NAME (code);
3295 tree ftype = nios2_ftype (N2FPU_FTCODE (code));
3296 machine_mode dst_mode = TYPE_MODE (TREE_TYPE (ftype));
3297 machine_mode src_mode = TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (ftype)));
3298
3299 /* Prepare X register for DF input operands. */
3300 if (GET_MODE_SIZE (src_mode) == 8 && num_operands == 3)
3301 n = snprintf (buf, ln, "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t",
3302 N2FPU_N (n2fpu_fwrx));
3303
3304 if (src_mode == SFmode)
3305 {
3306 if (dst_mode == VOIDmode)
3307 {
3308 /* The fwry case. */
3309 op1 = op3 = "zero";
3310 op2 = "%0";
3311 num_operands -= 1;
3312 }
3313 else
3314 {
3315 op1 = (dst_mode == DFmode ? "%D0" : "%0");
3316 op2 = "%1";
3317 op3 = (num_operands == 2 ? "zero" : "%2");
3318 }
3319 }
3320 else if (src_mode == DFmode)
3321 {
3322 if (dst_mode == VOIDmode)
3323 {
3324 /* The fwrx case. */
3325 op1 = "zero";
3326 op2 = "%0";
3327 op3 = "%D0";
3328 num_operands -= 1;
3329 }
3330 else
3331 {
3332 op1 = (dst_mode == DFmode ? "%D0" : "%0");
3333 op2 = (num_operands == 2 ? "%1" : "%2");
3334 op3 = (num_operands == 2 ? "%D1" : "%D2");
3335 }
3336 }
3337 else if (src_mode == VOIDmode)
3338 {
3339 /* frdxlo, frdxhi, frdy cases. */
3340 gcc_assert (dst_mode == SFmode);
3341 op1 = "%0";
3342 op2 = op3 = "zero";
3343 }
3344 else if (src_mode == SImode)
3345 {
3346 /* Conversion operators. */
3347 gcc_assert (num_operands == 2);
3348 op1 = (dst_mode == DFmode ? "%D0" : "%0");
3349 op2 = "%1";
3350 op3 = "zero";
3351 }
3352 else
3353 gcc_unreachable ();
3354
3355 /* Main instruction string. */
3356 n += snprintf (buf + n, ln - n, "custom\t%d, %s, %s, %s # %s %%0%s%s",
3357 N, op1, op2, op3, insn_name,
3358 (num_operands >= 2 ? ", %1" : ""),
3359 (num_operands == 3 ? ", %2" : ""));
3360
3361 /* Extraction of Y register for DF results. */
3362 if (dst_mode == DFmode)
3363 snprintf (buf + n, ln - n, "\n\tcustom\t%d, %%0, zero, zero # frdy %%0",
3364 N2FPU_N (n2fpu_frdy));
3365 return buf;
3366 }
3367
3368
3369
3370 /* Function argument related. */
3371
3372 /* Define where to put the arguments to a function. Value is zero to
3373 push the argument on the stack, or a hard register in which to
3374 store the argument.
3375
3376 CUM is a variable of type CUMULATIVE_ARGS which gives info about
3377 the preceding args and about the function being called.
3378 ARG is a description of the argument. */
3379
3380 static rtx
nios2_function_arg(cumulative_args_t cum_v,const function_arg_info & arg)3381 nios2_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
3382 {
3383 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3384 rtx return_rtx = NULL_RTX;
3385
3386 if (cum->regs_used < NUM_ARG_REGS)
3387 return_rtx = gen_rtx_REG (arg.mode, FIRST_ARG_REGNO + cum->regs_used);
3388
3389 return return_rtx;
3390 }
3391
3392 /* Return number of bytes, at the beginning of the argument, that must be
3393 put in registers. 0 is the argument is entirely in registers or entirely
3394 in memory. */
3395
3396 static int
nios2_arg_partial_bytes(cumulative_args_t cum_v,const function_arg_info & arg)3397 nios2_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
3398 {
3399 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3400 HOST_WIDE_INT param_size = arg.promoted_size_in_bytes ();
3401 gcc_assert (param_size >= 0);
3402
3403 /* Convert to words (round up). */
3404 param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
3405
3406 if (cum->regs_used < NUM_ARG_REGS
3407 && cum->regs_used + param_size > NUM_ARG_REGS)
3408 return (NUM_ARG_REGS - cum->regs_used) * UNITS_PER_WORD;
3409
3410 return 0;
3411 }
3412
3413 /* Update the data in CUM to advance over argument ARG. */
3414
3415 static void
nios2_function_arg_advance(cumulative_args_t cum_v,const function_arg_info & arg)3416 nios2_function_arg_advance (cumulative_args_t cum_v,
3417 const function_arg_info &arg)
3418 {
3419 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3420 HOST_WIDE_INT param_size = arg.promoted_size_in_bytes ();
3421 gcc_assert (param_size >= 0);
3422
3423 /* Convert to words (round up). */
3424 param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
3425
3426 if (cum->regs_used + param_size > NUM_ARG_REGS)
3427 cum->regs_used = NUM_ARG_REGS;
3428 else
3429 cum->regs_used += param_size;
3430 }
3431
3432 static pad_direction
nios2_function_arg_padding(machine_mode mode,const_tree type)3433 nios2_function_arg_padding (machine_mode mode, const_tree type)
3434 {
3435 /* On little-endian targets, the first byte of every stack argument
3436 is passed in the first byte of the stack slot. */
3437 if (!BYTES_BIG_ENDIAN)
3438 return PAD_UPWARD;
3439
3440 /* Otherwise, integral types are padded downward: the last byte of a
3441 stack argument is passed in the last byte of the stack slot. */
3442 if (type != 0
3443 ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
3444 : GET_MODE_CLASS (mode) == MODE_INT)
3445 return PAD_DOWNWARD;
3446
3447 /* Arguments smaller than a stack slot are padded downward. */
3448 if (mode != BLKmode)
3449 return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY
3450 ? PAD_UPWARD : PAD_DOWNWARD);
3451
3452 return ((int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
3453 ? PAD_UPWARD : PAD_DOWNWARD);
3454 }
3455
3456 pad_direction
nios2_block_reg_padding(machine_mode mode,tree type,int first ATTRIBUTE_UNUSED)3457 nios2_block_reg_padding (machine_mode mode, tree type,
3458 int first ATTRIBUTE_UNUSED)
3459 {
3460 return nios2_function_arg_padding (mode, type);
3461 }
3462
3463 /* Emit RTL insns to initialize the variable parts of a trampoline.
3464 FNADDR is an RTX for the address of the function's pure code.
3465 CXT is an RTX for the static chain value for the function.
3466 On Nios II, we handle this by a library call. */
3467 static void
nios2_trampoline_init(rtx m_tramp,tree fndecl,rtx cxt)3468 nios2_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
3469 {
3470 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
3471 rtx ctx_reg = force_reg (Pmode, cxt);
3472 rtx addr = force_reg (Pmode, XEXP (m_tramp, 0));
3473
3474 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__trampoline_setup"),
3475 LCT_NORMAL, VOIDmode, addr, Pmode, fnaddr, Pmode,
3476 ctx_reg, Pmode);
3477 }
3478
3479 /* Implement TARGET_FUNCTION_VALUE. */
3480 static rtx
nios2_function_value(const_tree ret_type,const_tree fn ATTRIBUTE_UNUSED,bool outgoing ATTRIBUTE_UNUSED)3481 nios2_function_value (const_tree ret_type, const_tree fn ATTRIBUTE_UNUSED,
3482 bool outgoing ATTRIBUTE_UNUSED)
3483 {
3484 return gen_rtx_REG (TYPE_MODE (ret_type), FIRST_RETVAL_REGNO);
3485 }
3486
3487 /* Implement TARGET_LIBCALL_VALUE. */
3488 static rtx
nios2_libcall_value(machine_mode mode,const_rtx fun ATTRIBUTE_UNUSED)3489 nios2_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
3490 {
3491 return gen_rtx_REG (mode, FIRST_RETVAL_REGNO);
3492 }
3493
3494 /* Implement TARGET_FUNCTION_VALUE_REGNO_P. */
3495 static bool
nios2_function_value_regno_p(const unsigned int regno)3496 nios2_function_value_regno_p (const unsigned int regno)
3497 {
3498 return regno == FIRST_RETVAL_REGNO;
3499 }
3500
3501 /* Implement TARGET_RETURN_IN_MEMORY. */
3502 static bool
nios2_return_in_memory(const_tree type,const_tree fntype ATTRIBUTE_UNUSED)3503 nios2_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
3504 {
3505 return (int_size_in_bytes (type) > (2 * UNITS_PER_WORD)
3506 || int_size_in_bytes (type) == -1);
3507 }
3508
3509 /* TODO: It may be possible to eliminate the copyback and implement
3510 own va_arg type. */
3511 static void
nios2_setup_incoming_varargs(cumulative_args_t cum_v,const function_arg_info & arg,int * pretend_size,int second_time)3512 nios2_setup_incoming_varargs (cumulative_args_t cum_v,
3513 const function_arg_info &arg,
3514 int *pretend_size, int second_time)
3515 {
3516 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3517 CUMULATIVE_ARGS local_cum;
3518 cumulative_args_t local_cum_v = pack_cumulative_args (&local_cum);
3519 int regs_to_push;
3520 int pret_size;
3521
3522 cfun->machine->uses_anonymous_args = 1;
3523 local_cum = *cum;
3524 nios2_function_arg_advance (local_cum_v, arg);
3525
3526 regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
3527
3528 /* If we can use CDX stwm to push the arguments on the stack,
3529 nios2_expand_prologue will do that instead. */
3530 if (!TARGET_HAS_CDX && !second_time && regs_to_push > 0)
3531 {
3532 rtx ptr = virtual_incoming_args_rtx;
3533 rtx mem = gen_rtx_MEM (BLKmode, ptr);
3534 emit_insn (gen_blockage ());
3535 move_block_from_reg (local_cum.regs_used + FIRST_ARG_REGNO, mem,
3536 regs_to_push);
3537 emit_insn (gen_blockage ());
3538 }
3539
3540 pret_size = regs_to_push * UNITS_PER_WORD;
3541 if (pret_size)
3542 *pretend_size = pret_size;
3543 }
3544
3545
3546
3547 /* Init FPU builtins. */
3548 static void
nios2_init_fpu_builtins(int start_code)3549 nios2_init_fpu_builtins (int start_code)
3550 {
3551 tree fndecl;
3552 char builtin_name[64] = "__builtin_custom_";
3553 unsigned int i, n = strlen ("__builtin_custom_");
3554
3555 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
3556 {
3557 snprintf (builtin_name + n, sizeof (builtin_name) - n,
3558 "%s", N2FPU_NAME (i));
3559 fndecl =
3560 add_builtin_function (builtin_name, nios2_ftype (N2FPU_FTCODE (i)),
3561 start_code + i, BUILT_IN_MD, NULL, NULL_TREE);
3562 nios2_register_builtin_fndecl (start_code + i, fndecl);
3563 }
3564 }
3565
3566 /* Helper function for expanding FPU builtins. */
3567 static rtx
nios2_expand_fpu_builtin(tree exp,unsigned int code,rtx target)3568 nios2_expand_fpu_builtin (tree exp, unsigned int code, rtx target)
3569 {
3570 struct expand_operand ops[MAX_RECOG_OPERANDS];
3571 enum insn_code icode = N2FPU_ICODE (code);
3572 int nargs, argno, opno = 0;
3573 int num_operands = N2FPU (code).num_operands;
3574 machine_mode dst_mode = TYPE_MODE (TREE_TYPE (exp));
3575 bool has_target_p = (dst_mode != VOIDmode);
3576
3577 if (N2FPU_N (code) < 0)
3578 fatal_error (input_location,
3579 "cannot call %<__builtin_custom_%s%> without specifying "
3580 "switch %<-mcustom-%s%>",
3581 N2FPU_NAME (code), N2FPU_NAME (code));
3582 if (has_target_p)
3583 create_output_operand (&ops[opno++], target, dst_mode);
3584 else
3585 /* Subtract away the count of the VOID return, mainly for fwrx/fwry. */
3586 num_operands -= 1;
3587 nargs = call_expr_nargs (exp);
3588 for (argno = 0; argno < nargs; argno++)
3589 {
3590 tree arg = CALL_EXPR_ARG (exp, argno);
3591 create_input_operand (&ops[opno++], expand_normal (arg),
3592 TYPE_MODE (TREE_TYPE (arg)));
3593 }
3594 if (!maybe_expand_insn (icode, num_operands, ops))
3595 {
3596 error ("invalid argument to built-in function");
3597 return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
3598 }
3599 return has_target_p ? ops[0].value : const0_rtx;
3600 }
3601
3602 /* Nios II has custom instruction built-in functions of the forms:
3603 __builtin_custom_n
3604 __builtin_custom_nX
3605 __builtin_custom_nXX
3606 __builtin_custom_Xn
3607 __builtin_custom_XnX
3608 __builtin_custom_XnXX
3609
3610 where each X could be either 'i' (int), 'f' (float), or 'p' (void*).
3611 Therefore with 0-1 return values, and 0-2 arguments, we have a
3612 total of (3 + 1) * (1 + 3 + 9) == 52 custom builtin functions.
3613 */
3614 #define NUM_CUSTOM_BUILTINS ((3 + 1) * (1 + 3 + 9))
3615 static char custom_builtin_name[NUM_CUSTOM_BUILTINS][5];
3616
3617 static void
nios2_init_custom_builtins(int start_code)3618 nios2_init_custom_builtins (int start_code)
3619 {
3620 tree builtin_ftype, ret_type, fndecl;
3621 char builtin_name[32] = "__builtin_custom_";
3622 int n = strlen ("__builtin_custom_");
3623 int builtin_code = 0;
3624 int lhs, rhs1, rhs2;
3625
3626 struct { tree type; const char *c; } op[4];
3627 /* z */ op[0].c = ""; op[0].type = NULL_TREE;
3628 /* f */ op[1].c = "f"; op[1].type = float_type_node;
3629 /* i */ op[2].c = "i"; op[2].type = integer_type_node;
3630 /* p */ op[3].c = "p"; op[3].type = ptr_type_node;
3631
3632 /* We enumerate through the possible operand types to create all the
3633 __builtin_custom_XnXX function tree types. Note that these may slightly
3634 overlap with the function types created for other fixed builtins. */
3635
3636 for (lhs = 0; lhs < 4; lhs++)
3637 for (rhs1 = 0; rhs1 < 4; rhs1++)
3638 for (rhs2 = 0; rhs2 < 4; rhs2++)
3639 {
3640 if (rhs1 == 0 && rhs2 != 0)
3641 continue;
3642 ret_type = (op[lhs].type ? op[lhs].type : void_type_node);
3643 builtin_ftype
3644 = build_function_type_list (ret_type, integer_type_node,
3645 op[rhs1].type, op[rhs2].type,
3646 NULL_TREE);
3647 /* Save copy of parameter string into custom_builtin_name[]. */
3648 snprintf (custom_builtin_name[builtin_code], 5, "%sn%s%s",
3649 op[lhs].c, op[rhs1].c, op[rhs2].c);
3650 strncpy (builtin_name + n, custom_builtin_name[builtin_code], 5);
3651 fndecl =
3652 add_builtin_function (builtin_name, builtin_ftype,
3653 start_code + builtin_code,
3654 BUILT_IN_MD, NULL, NULL_TREE);
3655 nios2_register_builtin_fndecl (start_code + builtin_code, fndecl);
3656 builtin_code += 1;
3657 }
3658 }
3659
3660 /* Helper function for expanding custom builtins. */
3661 static rtx
nios2_expand_custom_builtin(tree exp,unsigned int index,rtx target)3662 nios2_expand_custom_builtin (tree exp, unsigned int index, rtx target)
3663 {
3664 bool has_target_p = (TREE_TYPE (exp) != void_type_node);
3665 machine_mode tmode = VOIDmode;
3666 int nargs, argno;
3667 rtx value, insn, unspec_args[3];
3668 tree arg;
3669
3670 /* XnXX form. */
3671 if (has_target_p)
3672 {
3673 tmode = TYPE_MODE (TREE_TYPE (exp));
3674 if (!target || GET_MODE (target) != tmode
3675 || !REG_P (target))
3676 target = gen_reg_rtx (tmode);
3677 }
3678
3679 nargs = call_expr_nargs (exp);
3680 for (argno = 0; argno < nargs; argno++)
3681 {
3682 arg = CALL_EXPR_ARG (exp, argno);
3683 value = expand_normal (arg);
3684 unspec_args[argno] = value;
3685 if (argno == 0)
3686 {
3687 if (!custom_insn_opcode (value, VOIDmode))
3688 error ("custom instruction opcode must be a compile-time "
3689 "constant in the range 0-255 for %<__builtin_custom_%s%>",
3690 custom_builtin_name[index]);
3691 }
3692 else
3693 /* For other arguments, force into a register. */
3694 unspec_args[argno] = force_reg (TYPE_MODE (TREE_TYPE (arg)),
3695 unspec_args[argno]);
3696 }
3697 /* Fill remaining unspec operands with zero. */
3698 for (; argno < 3; argno++)
3699 unspec_args[argno] = const0_rtx;
3700
3701 insn = (has_target_p
3702 ? gen_rtx_SET (target,
3703 gen_rtx_UNSPEC_VOLATILE (tmode,
3704 gen_rtvec_v (3, unspec_args),
3705 UNSPECV_CUSTOM_XNXX))
3706 : gen_rtx_UNSPEC_VOLATILE (VOIDmode, gen_rtvec_v (3, unspec_args),
3707 UNSPECV_CUSTOM_NXX));
3708 emit_insn (insn);
3709 return has_target_p ? target : const0_rtx;
3710 }
3711
3712
3713
3714
3715 /* Main definition of built-in functions. Nios II has a small number of fixed
3716 builtins, plus a large number of FPU insn builtins, and builtins for
3717 generating custom instructions. */
3718
3719 struct nios2_builtin_desc
3720 {
3721 enum insn_code icode;
3722 enum nios2_arch_type arch;
3723 enum nios2_ftcode ftype;
3724 const char *name;
3725 };
3726
3727 #define N2_BUILTINS \
3728 N2_BUILTIN_DEF (sync, R1, N2_FTYPE_VOID_VOID) \
3729 N2_BUILTIN_DEF (ldbio, R1, N2_FTYPE_SI_CVPTR) \
3730 N2_BUILTIN_DEF (ldbuio, R1, N2_FTYPE_UI_CVPTR) \
3731 N2_BUILTIN_DEF (ldhio, R1, N2_FTYPE_SI_CVPTR) \
3732 N2_BUILTIN_DEF (ldhuio, R1, N2_FTYPE_UI_CVPTR) \
3733 N2_BUILTIN_DEF (ldwio, R1, N2_FTYPE_SI_CVPTR) \
3734 N2_BUILTIN_DEF (stbio, R1, N2_FTYPE_VOID_VPTR_SI) \
3735 N2_BUILTIN_DEF (sthio, R1, N2_FTYPE_VOID_VPTR_SI) \
3736 N2_BUILTIN_DEF (stwio, R1, N2_FTYPE_VOID_VPTR_SI) \
3737 N2_BUILTIN_DEF (rdctl, R1, N2_FTYPE_SI_SI) \
3738 N2_BUILTIN_DEF (wrctl, R1, N2_FTYPE_VOID_SI_SI) \
3739 N2_BUILTIN_DEF (rdprs, R1, N2_FTYPE_SI_SI_SI) \
3740 N2_BUILTIN_DEF (flushd, R1, N2_FTYPE_VOID_VPTR) \
3741 N2_BUILTIN_DEF (flushda, R1, N2_FTYPE_VOID_VPTR) \
3742 N2_BUILTIN_DEF (wrpie, R2, N2_FTYPE_SI_SI) \
3743 N2_BUILTIN_DEF (eni, R2, N2_FTYPE_VOID_SI) \
3744 N2_BUILTIN_DEF (ldex, R2, N2_FTYPE_SI_CVPTR) \
3745 N2_BUILTIN_DEF (ldsex, R2, N2_FTYPE_SI_CVPTR) \
3746 N2_BUILTIN_DEF (stex, R2, N2_FTYPE_SI_VPTR_SI) \
3747 N2_BUILTIN_DEF (stsex, R2, N2_FTYPE_SI_VPTR_SI)
3748
3749 enum nios2_builtin_code {
3750 #define N2_BUILTIN_DEF(name, arch, ftype) NIOS2_BUILTIN_ ## name,
3751 N2_BUILTINS
3752 #undef N2_BUILTIN_DEF
3753 NUM_FIXED_NIOS2_BUILTINS
3754 };
3755
3756 static const struct nios2_builtin_desc nios2_builtins[] = {
3757 #define N2_BUILTIN_DEF(name, arch, ftype) \
3758 { CODE_FOR_ ## name, ARCH_ ## arch, ftype, "__builtin_" #name },
3759 N2_BUILTINS
3760 #undef N2_BUILTIN_DEF
3761 };
3762
3763 /* Start/ends of FPU/custom insn builtin index ranges. */
3764 static unsigned int nios2_fpu_builtin_base;
3765 static unsigned int nios2_custom_builtin_base;
3766 static unsigned int nios2_custom_builtin_end;
3767
3768 /* Implement TARGET_INIT_BUILTINS. */
3769 static void
nios2_init_builtins(void)3770 nios2_init_builtins (void)
3771 {
3772 unsigned int i;
3773
3774 /* Initialize fixed builtins. */
3775 for (i = 0; i < ARRAY_SIZE (nios2_builtins); i++)
3776 {
3777 const struct nios2_builtin_desc *d = &nios2_builtins[i];
3778 tree fndecl =
3779 add_builtin_function (d->name, nios2_ftype (d->ftype), i,
3780 BUILT_IN_MD, NULL, NULL);
3781 nios2_register_builtin_fndecl (i, fndecl);
3782 }
3783
3784 /* Initialize FPU builtins. */
3785 nios2_fpu_builtin_base = ARRAY_SIZE (nios2_builtins);
3786 nios2_init_fpu_builtins (nios2_fpu_builtin_base);
3787
3788 /* Initialize custom insn builtins. */
3789 nios2_custom_builtin_base
3790 = nios2_fpu_builtin_base + ARRAY_SIZE (nios2_fpu_insn);
3791 nios2_custom_builtin_end
3792 = nios2_custom_builtin_base + NUM_CUSTOM_BUILTINS;
3793 nios2_init_custom_builtins (nios2_custom_builtin_base);
3794 }
3795
3796 /* Array of fndecls for TARGET_BUILTIN_DECL. */
3797 #define NIOS2_NUM_BUILTINS \
3798 (ARRAY_SIZE (nios2_builtins) + ARRAY_SIZE (nios2_fpu_insn) + NUM_CUSTOM_BUILTINS)
3799 static GTY(()) tree nios2_builtin_decls[NIOS2_NUM_BUILTINS];
3800
3801 static void
nios2_register_builtin_fndecl(unsigned code,tree fndecl)3802 nios2_register_builtin_fndecl (unsigned code, tree fndecl)
3803 {
3804 nios2_builtin_decls[code] = fndecl;
3805 }
3806
3807 /* Implement TARGET_BUILTIN_DECL. */
3808 static tree
nios2_builtin_decl(unsigned code,bool initialize_p ATTRIBUTE_UNUSED)3809 nios2_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
3810 {
3811 gcc_assert (nios2_custom_builtin_end == ARRAY_SIZE (nios2_builtin_decls));
3812
3813 if (code >= nios2_custom_builtin_end)
3814 return error_mark_node;
3815
3816 if (code >= nios2_fpu_builtin_base
3817 && code < nios2_custom_builtin_base
3818 && ! N2FPU_ENABLED_P (code - nios2_fpu_builtin_base))
3819 return error_mark_node;
3820
3821 return nios2_builtin_decls[code];
3822 }
3823
3824
3825 /* Low-level built-in expand routine. */
3826 static rtx
nios2_expand_builtin_insn(const struct nios2_builtin_desc * d,int n,struct expand_operand * ops,bool has_target_p)3827 nios2_expand_builtin_insn (const struct nios2_builtin_desc *d, int n,
3828 struct expand_operand *ops, bool has_target_p)
3829 {
3830 if (maybe_expand_insn (d->icode, n, ops))
3831 return has_target_p ? ops[0].value : const0_rtx;
3832 else
3833 {
3834 error ("invalid argument to built-in function %s", d->name);
3835 return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
3836 }
3837 }
3838
3839 /* Expand ldio/stio and ldex/ldsex/stex/stsex form load-store
3840 instruction builtins. */
3841 static rtx
nios2_expand_ldst_builtin(tree exp,rtx target,const struct nios2_builtin_desc * d)3842 nios2_expand_ldst_builtin (tree exp, rtx target,
3843 const struct nios2_builtin_desc *d)
3844 {
3845 bool has_target_p;
3846 rtx addr, mem, val;
3847 struct expand_operand ops[MAX_RECOG_OPERANDS];
3848 machine_mode mode = insn_data[d->icode].operand[0].mode;
3849
3850 addr = expand_normal (CALL_EXPR_ARG (exp, 0));
3851 mem = gen_rtx_MEM (mode, addr);
3852
3853 if (insn_data[d->icode].operand[0].allows_mem)
3854 {
3855 /* stxio/stex/stsex. */
3856 val = expand_normal (CALL_EXPR_ARG (exp, 1));
3857 if (CONST_INT_P (val))
3858 val = force_reg (mode, gen_int_mode (INTVAL (val), mode));
3859 val = simplify_gen_subreg (mode, val, GET_MODE (val), 0);
3860 create_output_operand (&ops[0], mem, mode);
3861 create_input_operand (&ops[1], val, mode);
3862 if (insn_data[d->icode].n_operands == 3)
3863 {
3864 /* stex/stsex status value, returned as result of function. */
3865 create_output_operand (&ops[2], target, mode);
3866 has_target_p = true;
3867 }
3868 else
3869 has_target_p = false;
3870 }
3871 else
3872 {
3873 /* ldxio. */
3874 create_output_operand (&ops[0], target, mode);
3875 create_input_operand (&ops[1], mem, mode);
3876 has_target_p = true;
3877 }
3878 return nios2_expand_builtin_insn (d, insn_data[d->icode].n_operands, ops,
3879 has_target_p);
3880 }
3881
3882 /* Expand rdctl/wrctl builtins. */
3883 static rtx
nios2_expand_rdwrctl_builtin(tree exp,rtx target,const struct nios2_builtin_desc * d)3884 nios2_expand_rdwrctl_builtin (tree exp, rtx target,
3885 const struct nios2_builtin_desc *d)
3886 {
3887 bool has_target_p = (insn_data[d->icode].operand[0].predicate
3888 == register_operand);
3889 rtx ctlcode = expand_normal (CALL_EXPR_ARG (exp, 0));
3890 struct expand_operand ops[MAX_RECOG_OPERANDS];
3891 if (!rdwrctl_operand (ctlcode, VOIDmode))
3892 {
3893 error ("control register number must be in range 0-31 for %s",
3894 d->name);
3895 return has_target_p ? gen_reg_rtx (SImode) : const0_rtx;
3896 }
3897 if (has_target_p)
3898 {
3899 create_output_operand (&ops[0], target, SImode);
3900 create_integer_operand (&ops[1], INTVAL (ctlcode));
3901 }
3902 else
3903 {
3904 rtx val = expand_normal (CALL_EXPR_ARG (exp, 1));
3905 create_integer_operand (&ops[0], INTVAL (ctlcode));
3906 create_input_operand (&ops[1], val, SImode);
3907 }
3908 return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
3909 }
3910
3911 static rtx
nios2_expand_rdprs_builtin(tree exp,rtx target,const struct nios2_builtin_desc * d)3912 nios2_expand_rdprs_builtin (tree exp, rtx target,
3913 const struct nios2_builtin_desc *d)
3914 {
3915 rtx reg = expand_normal (CALL_EXPR_ARG (exp, 0));
3916 rtx imm = expand_normal (CALL_EXPR_ARG (exp, 1));
3917 struct expand_operand ops[MAX_RECOG_OPERANDS];
3918
3919 if (!rdwrctl_operand (reg, VOIDmode))
3920 {
3921 error ("register number must be in range 0-31 for %s",
3922 d->name);
3923 return gen_reg_rtx (SImode);
3924 }
3925
3926 if (!rdprs_dcache_operand (imm, VOIDmode))
3927 {
3928 error ("immediate value must fit into a %d-bit integer for %s",
3929 (TARGET_ARCH_R2) ? 12 : 16, d->name);
3930 return gen_reg_rtx (SImode);
3931 }
3932
3933 create_output_operand (&ops[0], target, SImode);
3934 create_input_operand (&ops[1], reg, SImode);
3935 create_integer_operand (&ops[2], INTVAL (imm));
3936
3937 return nios2_expand_builtin_insn (d, 3, ops, true);
3938 }
3939
3940 static rtx
nios2_expand_cache_builtin(tree exp,rtx target ATTRIBUTE_UNUSED,const struct nios2_builtin_desc * d)3941 nios2_expand_cache_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
3942 const struct nios2_builtin_desc *d)
3943 {
3944 rtx mem, addr;
3945 struct expand_operand ops[MAX_RECOG_OPERANDS];
3946
3947 addr = expand_normal (CALL_EXPR_ARG (exp, 0));
3948 mem = gen_rtx_MEM (SImode, addr);
3949
3950 create_input_operand (&ops[0], mem, SImode);
3951
3952 return nios2_expand_builtin_insn (d, 1, ops, false);
3953 }
3954
3955 static rtx
nios2_expand_wrpie_builtin(tree exp,rtx target,const struct nios2_builtin_desc * d)3956 nios2_expand_wrpie_builtin (tree exp, rtx target,
3957 const struct nios2_builtin_desc *d)
3958 {
3959 rtx val;
3960 struct expand_operand ops[MAX_RECOG_OPERANDS];
3961
3962 val = expand_normal (CALL_EXPR_ARG (exp, 0));
3963 create_input_operand (&ops[1], val, SImode);
3964 create_output_operand (&ops[0], target, SImode);
3965
3966 return nios2_expand_builtin_insn (d, 2, ops, true);
3967 }
3968
3969 static rtx
nios2_expand_eni_builtin(tree exp,rtx target ATTRIBUTE_UNUSED,const struct nios2_builtin_desc * d)3970 nios2_expand_eni_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
3971 const struct nios2_builtin_desc *d)
3972 {
3973 rtx imm = expand_normal (CALL_EXPR_ARG (exp, 0));
3974 struct expand_operand ops[MAX_RECOG_OPERANDS];
3975
3976 if (INTVAL (imm) != 0 && INTVAL (imm) != 1)
3977 {
3978 error ("the ENI instruction operand must be either 0 or 1");
3979 return const0_rtx;
3980 }
3981 create_integer_operand (&ops[0], INTVAL (imm));
3982
3983 return nios2_expand_builtin_insn (d, 1, ops, false);
3984 }
3985
3986 /* Implement TARGET_EXPAND_BUILTIN. Expand an expression EXP that calls
3987 a built-in function, with result going to TARGET if that's convenient
3988 (and in mode MODE if that's convenient).
3989 SUBTARGET may be used as the target for computing one of EXP's operands.
3990 IGNORE is nonzero if the value is to be ignored. */
3991
3992 static rtx
nios2_expand_builtin(tree exp,rtx target,rtx subtarget ATTRIBUTE_UNUSED,machine_mode mode ATTRIBUTE_UNUSED,int ignore ATTRIBUTE_UNUSED)3993 nios2_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
3994 machine_mode mode ATTRIBUTE_UNUSED,
3995 int ignore ATTRIBUTE_UNUSED)
3996 {
3997 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
3998 unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
3999
4000 if (fcode < nios2_fpu_builtin_base)
4001 {
4002 const struct nios2_builtin_desc *d = &nios2_builtins[fcode];
4003
4004 if (d->arch > nios2_arch_option)
4005 {
4006 error ("built-in function %s requires Nios II R%d",
4007 d->name, (int) d->arch);
4008 /* Given it is invalid, just generate a normal call. */
4009 return expand_call (exp, target, ignore);
4010 }
4011
4012 switch (fcode)
4013 {
4014 case NIOS2_BUILTIN_sync:
4015 emit_insn (gen_sync ());
4016 return const0_rtx;
4017
4018 case NIOS2_BUILTIN_ldbio:
4019 case NIOS2_BUILTIN_ldbuio:
4020 case NIOS2_BUILTIN_ldhio:
4021 case NIOS2_BUILTIN_ldhuio:
4022 case NIOS2_BUILTIN_ldwio:
4023 case NIOS2_BUILTIN_stbio:
4024 case NIOS2_BUILTIN_sthio:
4025 case NIOS2_BUILTIN_stwio:
4026 case NIOS2_BUILTIN_ldex:
4027 case NIOS2_BUILTIN_ldsex:
4028 case NIOS2_BUILTIN_stex:
4029 case NIOS2_BUILTIN_stsex:
4030 return nios2_expand_ldst_builtin (exp, target, d);
4031
4032 case NIOS2_BUILTIN_rdctl:
4033 case NIOS2_BUILTIN_wrctl:
4034 return nios2_expand_rdwrctl_builtin (exp, target, d);
4035
4036 case NIOS2_BUILTIN_rdprs:
4037 return nios2_expand_rdprs_builtin (exp, target, d);
4038
4039 case NIOS2_BUILTIN_flushd:
4040 case NIOS2_BUILTIN_flushda:
4041 return nios2_expand_cache_builtin (exp, target, d);
4042
4043 case NIOS2_BUILTIN_wrpie:
4044 return nios2_expand_wrpie_builtin (exp, target, d);
4045
4046 case NIOS2_BUILTIN_eni:
4047 return nios2_expand_eni_builtin (exp, target, d);
4048
4049 default:
4050 gcc_unreachable ();
4051 }
4052 }
4053 else if (fcode < nios2_custom_builtin_base)
4054 /* FPU builtin range. */
4055 return nios2_expand_fpu_builtin (exp, fcode - nios2_fpu_builtin_base,
4056 target);
4057 else if (fcode < nios2_custom_builtin_end)
4058 /* Custom insn builtin range. */
4059 return nios2_expand_custom_builtin (exp, fcode - nios2_custom_builtin_base,
4060 target);
4061 else
4062 gcc_unreachable ();
4063 }
4064
4065 /* Implement TARGET_INIT_LIBFUNCS. */
4066 static void ATTRIBUTE_UNUSED
nios2_init_libfuncs(void)4067 nios2_init_libfuncs (void)
4068 {
4069 init_sync_libfuncs (UNITS_PER_WORD);
4070 }
4071
4072
4073
4074 /* Register a custom code use, and signal error if a conflict was found. */
4075 static void
nios2_register_custom_code(unsigned int N,enum nios2_ccs_code status,int index)4076 nios2_register_custom_code (unsigned int N, enum nios2_ccs_code status,
4077 int index)
4078 {
4079 gcc_assert (N <= 255);
4080
4081 if (status == CCS_FPU)
4082 {
4083 if (custom_code_status[N] == CCS_FPU && index != custom_code_index[N])
4084 {
4085 custom_code_conflict = true;
4086 error ("switch %<-mcustom-%s%> conflicts with "
4087 "switch %<-mcustom-%s%>",
4088 N2FPU_NAME (custom_code_index[N]), N2FPU_NAME (index));
4089 }
4090 else if (custom_code_status[N] == CCS_BUILTIN_CALL)
4091 {
4092 custom_code_conflict = true;
4093 error ("call to %<__builtin_custom_%s%> conflicts with "
4094 "switch %<-mcustom-%s%>",
4095 custom_builtin_name[custom_code_index[N]],
4096 N2FPU_NAME (index));
4097 }
4098 }
4099 else if (status == CCS_BUILTIN_CALL)
4100 {
4101 if (custom_code_status[N] == CCS_FPU)
4102 {
4103 custom_code_conflict = true;
4104 error ("call to %<__builtin_custom_%s%> conflicts with "
4105 "switch %<-mcustom-%s%>",
4106 custom_builtin_name[index],
4107 N2FPU_NAME (custom_code_index[N]));
4108 }
4109 else
4110 {
4111 /* Note that code conflicts between different __builtin_custom_xnxx
4112 calls are not checked. */
4113 }
4114 }
4115 else
4116 gcc_unreachable ();
4117
4118 custom_code_status[N] = status;
4119 custom_code_index[N] = index;
4120 }
4121
4122 /* Mark a custom code as not in use. */
4123 static void
nios2_deregister_custom_code(unsigned int N)4124 nios2_deregister_custom_code (unsigned int N)
4125 {
4126 if (N <= 255)
4127 {
4128 custom_code_status[N] = CCS_UNUSED;
4129 custom_code_index[N] = 0;
4130 }
4131 }
4132
4133 /* Target attributes can affect per-function option state, so we need to
4134 save/restore the custom code tracking info using the
4135 TARGET_OPTION_SAVE/TARGET_OPTION_RESTORE hooks. */
4136
4137 static void
nios2_option_save(struct cl_target_option * ptr,struct gcc_options * opts ATTRIBUTE_UNUSED,struct gcc_options * opts_set ATTRIBUTE_UNUSED)4138 nios2_option_save (struct cl_target_option *ptr,
4139 struct gcc_options *opts ATTRIBUTE_UNUSED,
4140 struct gcc_options *opts_set ATTRIBUTE_UNUSED)
4141 {
4142 unsigned int i;
4143 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
4144 ptr->saved_fpu_custom_code[i] = N2FPU_N (i);
4145 memcpy (ptr->saved_custom_code_status, custom_code_status,
4146 sizeof (custom_code_status));
4147 memcpy (ptr->saved_custom_code_index, custom_code_index,
4148 sizeof (custom_code_index));
4149 }
4150
4151 static void
nios2_option_restore(struct gcc_options * opts ATTRIBUTE_UNUSED,struct gcc_options * opts_set ATTRIBUTE_UNUSED,struct cl_target_option * ptr)4152 nios2_option_restore (struct gcc_options *opts ATTRIBUTE_UNUSED,
4153 struct gcc_options *opts_set ATTRIBUTE_UNUSED,
4154 struct cl_target_option *ptr)
4155 {
4156 unsigned int i;
4157 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
4158 N2FPU_N (i) = ptr->saved_fpu_custom_code[i];
4159 memcpy (custom_code_status, ptr->saved_custom_code_status,
4160 sizeof (custom_code_status));
4161 memcpy (custom_code_index, ptr->saved_custom_code_index,
4162 sizeof (custom_code_index));
4163 }
4164
4165 static bool
nios2_can_inline_p(tree caller,tree callee)4166 nios2_can_inline_p (tree caller, tree callee)
4167 {
4168 tree callee_opts = DECL_FUNCTION_SPECIFIC_TARGET (callee);
4169 tree caller_opts = DECL_FUNCTION_SPECIFIC_TARGET (caller);
4170 struct cl_target_option *callee_ptr, *caller_ptr;
4171 unsigned int i;
4172
4173 if (! callee_opts)
4174 callee_opts = target_option_default_node;
4175 if (! caller_opts)
4176 caller_opts = target_option_default_node;
4177
4178 /* If both caller and callee have attributes, assume that if the
4179 pointer is different, the two functions have different target
4180 options since build_target_option_node uses a hash table for the
4181 options. */
4182 if (callee_opts == caller_opts)
4183 return true;
4184
4185 /* The only target options we recognize via function attributes are
4186 those related to custom instructions. If we failed the above test,
4187 check that any custom instructions enabled in the callee are also
4188 enabled with the same value in the caller. */
4189 callee_ptr = TREE_TARGET_OPTION (callee_opts);
4190 caller_ptr = TREE_TARGET_OPTION (caller_opts);
4191 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
4192 if (callee_ptr->saved_fpu_custom_code[i] != -1
4193 && (callee_ptr->saved_fpu_custom_code[i]
4194 != caller_ptr->saved_fpu_custom_code[i]))
4195 return false;
4196 return true;
4197 }
4198
4199 /* Inner function to process the attribute((target(...))), take an argument and
4200 set the current options from the argument. If we have a list, recursively
4201 go over the list. */
4202
4203 static bool
nios2_valid_target_attribute_rec(tree args)4204 nios2_valid_target_attribute_rec (tree args)
4205 {
4206 if (TREE_CODE (args) == TREE_LIST)
4207 {
4208 bool ret = true;
4209 for (; args; args = TREE_CHAIN (args))
4210 if (TREE_VALUE (args)
4211 && !nios2_valid_target_attribute_rec (TREE_VALUE (args)))
4212 ret = false;
4213 return ret;
4214 }
4215 else if (TREE_CODE (args) == STRING_CST)
4216 {
4217 char *argstr = ASTRDUP (TREE_STRING_POINTER (args));
4218 while (argstr && *argstr != '\0')
4219 {
4220 bool no_opt = false, end_p = false;
4221 char *eq = NULL, *p;
4222 while (ISSPACE (*argstr))
4223 argstr++;
4224 p = argstr;
4225 while (*p != '\0' && *p != ',')
4226 {
4227 if (!eq && *p == '=')
4228 eq = p;
4229 ++p;
4230 }
4231 if (*p == '\0')
4232 end_p = true;
4233 else
4234 *p = '\0';
4235 if (eq) *eq = '\0';
4236
4237 if (startswith (argstr, "no-"))
4238 {
4239 no_opt = true;
4240 argstr += 3;
4241 }
4242 if (startswith (argstr, "custom-fpu-cfg"))
4243 {
4244 char *end_eq = p;
4245 if (no_opt)
4246 {
4247 error ("%<custom-fpu-cfg%> option does not support %<no-%>");
4248 return false;
4249 }
4250 if (!eq)
4251 {
4252 error ("%<custom-fpu-cfg%> option requires configuration "
4253 "argument");
4254 return false;
4255 }
4256 /* Increment and skip whitespace. */
4257 while (ISSPACE (*(++eq))) ;
4258 /* Decrement and skip to before any trailing whitespace. */
4259 while (ISSPACE (*(--end_eq))) ;
4260
4261 nios2_handle_custom_fpu_cfg (eq, end_eq + 1, true);
4262 }
4263 else if (startswith (argstr, "custom-"))
4264 {
4265 int code = -1;
4266 unsigned int i;
4267 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
4268 if (startswith (argstr + 7, N2FPU_NAME (i)))
4269 {
4270 /* Found insn. */
4271 code = i;
4272 break;
4273 }
4274 if (code >= 0)
4275 {
4276 if (no_opt)
4277 {
4278 if (eq)
4279 {
4280 error ("%<no-custom-%s%> does not accept arguments",
4281 N2FPU_NAME (code));
4282 return false;
4283 }
4284 /* Disable option by setting to -1. */
4285 nios2_deregister_custom_code (N2FPU_N (code));
4286 N2FPU_N (code) = -1;
4287 }
4288 else
4289 {
4290 char *t;
4291 if (eq)
4292 while (ISSPACE (*(++eq))) ;
4293 if (!eq || eq == p)
4294 {
4295 error ("%<custom-%s=%> requires argument",
4296 N2FPU_NAME (code));
4297 return false;
4298 }
4299 for (t = eq; t != p; ++t)
4300 {
4301 if (ISSPACE (*t))
4302 continue;
4303 if (!ISDIGIT (*t))
4304 {
4305 error ("%<custom-%s=%> argument should be "
4306 "a non-negative integer", N2FPU_NAME (code));
4307 return false;
4308 }
4309 }
4310 /* Set option to argument. */
4311 N2FPU_N (code) = atoi (eq);
4312 nios2_handle_custom_fpu_insn_option (code);
4313 }
4314 }
4315 else
4316 {
4317 error ("%<custom-%s=%> is not recognized as FPU instruction",
4318 argstr + 7);
4319 return false;
4320 }
4321 }
4322 else
4323 {
4324 error ("invalid custom instruction option %qs", argstr);
4325 return false;
4326 }
4327
4328 if (end_p)
4329 break;
4330 else
4331 argstr = p + 1;
4332 }
4333 return true;
4334 }
4335 else
4336 gcc_unreachable ();
4337 }
4338
4339 /* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. */
4340
4341 static tree
nios2_valid_target_attribute_tree(tree args)4342 nios2_valid_target_attribute_tree (tree args)
4343 {
4344 if (!nios2_valid_target_attribute_rec (args))
4345 return NULL_TREE;
4346 nios2_custom_check_insns ();
4347 return build_target_option_node (&global_options, &global_options_set);
4348 }
4349
4350 /* Hook to validate attribute((target("string"))). */
4351
4352 static bool
nios2_valid_target_attribute_p(tree fndecl,tree ARG_UNUSED (name),tree args,int ARG_UNUSED (flags))4353 nios2_valid_target_attribute_p (tree fndecl, tree ARG_UNUSED (name),
4354 tree args, int ARG_UNUSED (flags))
4355 {
4356 struct cl_target_option cur_target;
4357 bool ret = true;
4358 tree old_optimize
4359 = build_optimization_node (&global_options, &global_options_set);
4360 tree new_target, new_optimize;
4361 tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
4362
4363 /* If the function changed the optimization levels as well as setting target
4364 options, start with the optimizations specified. */
4365 if (func_optimize && func_optimize != old_optimize)
4366 cl_optimization_restore (&global_options, &global_options_set,
4367 TREE_OPTIMIZATION (func_optimize));
4368
4369 /* The target attributes may also change some optimization flags, so update
4370 the optimization options if necessary. */
4371 cl_target_option_save (&cur_target, &global_options, &global_options_set);
4372 new_target = nios2_valid_target_attribute_tree (args);
4373 new_optimize = build_optimization_node (&global_options, &global_options_set);
4374
4375 if (!new_target)
4376 ret = false;
4377
4378 else if (fndecl)
4379 {
4380 DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
4381
4382 if (old_optimize != new_optimize)
4383 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
4384 }
4385
4386 cl_target_option_restore (&global_options, &global_options_set, &cur_target);
4387
4388 if (old_optimize != new_optimize)
4389 cl_optimization_restore (&global_options, &global_options_set,
4390 TREE_OPTIMIZATION (old_optimize));
4391 return ret;
4392 }
4393
4394 /* Remember the last target of nios2_set_current_function. */
4395 static GTY(()) tree nios2_previous_fndecl;
4396
4397 /* Establish appropriate back-end context for processing the function
4398 FNDECL. The argument might be NULL to indicate processing at top
4399 level, outside of any function scope. */
4400 static void
nios2_set_current_function(tree fndecl)4401 nios2_set_current_function (tree fndecl)
4402 {
4403 tree old_tree = (nios2_previous_fndecl
4404 ? DECL_FUNCTION_SPECIFIC_TARGET (nios2_previous_fndecl)
4405 : NULL_TREE);
4406
4407 tree new_tree = (fndecl
4408 ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl)
4409 : NULL_TREE);
4410
4411 if (fndecl && fndecl != nios2_previous_fndecl)
4412 {
4413 nios2_previous_fndecl = fndecl;
4414 if (old_tree == new_tree)
4415 ;
4416
4417 else if (new_tree)
4418 {
4419 cl_target_option_restore (&global_options, &global_options_set,
4420 TREE_TARGET_OPTION (new_tree));
4421 target_reinit ();
4422 }
4423
4424 else if (old_tree)
4425 {
4426 struct cl_target_option *def
4427 = TREE_TARGET_OPTION (target_option_current_node);
4428
4429 cl_target_option_restore (&global_options, &global_options_set, def);
4430 target_reinit ();
4431 }
4432 }
4433 }
4434
4435 /* Hook to validate the current #pragma GCC target and set the FPU custom
4436 code option state. If ARGS is NULL, then POP_TARGET is used to reset
4437 the options. */
4438 static bool
nios2_pragma_target_parse(tree args,tree pop_target)4439 nios2_pragma_target_parse (tree args, tree pop_target)
4440 {
4441 tree cur_tree;
4442 if (! args)
4443 {
4444 cur_tree = ((pop_target)
4445 ? pop_target
4446 : target_option_default_node);
4447 cl_target_option_restore (&global_options, &global_options_set,
4448 TREE_TARGET_OPTION (cur_tree));
4449 }
4450 else
4451 {
4452 cur_tree = nios2_valid_target_attribute_tree (args);
4453 if (!cur_tree)
4454 return false;
4455 }
4456
4457 target_option_current_node = cur_tree;
4458 return true;
4459 }
4460
4461 /* Implement TARGET_MERGE_DECL_ATTRIBUTES.
4462 We are just using this hook to add some additional error checking to
4463 the default behavior. GCC does not provide a target hook for merging
4464 the target options, and only correctly handles merging empty vs non-empty
4465 option data; see merge_decls() in c-decl.cc.
4466 So here we require either that at least one of the decls has empty
4467 target options, or that the target options/data be identical. */
4468 static tree
nios2_merge_decl_attributes(tree olddecl,tree newdecl)4469 nios2_merge_decl_attributes (tree olddecl, tree newdecl)
4470 {
4471 tree oldopts = lookup_attribute ("target", DECL_ATTRIBUTES (olddecl));
4472 tree newopts = lookup_attribute ("target", DECL_ATTRIBUTES (newdecl));
4473 if (newopts && oldopts && newopts != oldopts)
4474 {
4475 tree oldtree = DECL_FUNCTION_SPECIFIC_TARGET (olddecl);
4476 tree newtree = DECL_FUNCTION_SPECIFIC_TARGET (newdecl);
4477 if (oldtree && newtree && oldtree != newtree)
4478 {
4479 struct cl_target_option *olddata = TREE_TARGET_OPTION (oldtree);
4480 struct cl_target_option *newdata = TREE_TARGET_OPTION (newtree);
4481 if (olddata != newdata
4482 && memcmp (olddata, newdata, sizeof (struct cl_target_option)))
4483 error ("%qE redeclared with conflicting %qs attributes",
4484 DECL_NAME (newdecl), "target");
4485 }
4486 }
4487 return merge_attributes (DECL_ATTRIBUTES (olddecl),
4488 DECL_ATTRIBUTES (newdecl));
4489 }
4490
4491 /* Implement TARGET_ASM_OUTPUT_MI_THUNK. */
4492 static void
nios2_asm_output_mi_thunk(FILE * file,tree thunk_fndecl ATTRIBUTE_UNUSED,HOST_WIDE_INT delta,HOST_WIDE_INT vcall_offset,tree function)4493 nios2_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
4494 HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
4495 tree function)
4496 {
4497 const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
4498 rtx this_rtx, funexp;
4499 rtx_insn *insn;
4500
4501 /* Pretend to be a post-reload pass while generating rtl. */
4502 reload_completed = 1;
4503
4504 if (flag_pic)
4505 nios2_load_pic_register ();
4506
4507 /* Mark the end of the (empty) prologue. */
4508 emit_note (NOTE_INSN_PROLOGUE_END);
4509
4510 /* Find the "this" pointer. If the function returns a structure,
4511 the structure return pointer is in $5. */
4512 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
4513 this_rtx = gen_rtx_REG (Pmode, FIRST_ARG_REGNO + 1);
4514 else
4515 this_rtx = gen_rtx_REG (Pmode, FIRST_ARG_REGNO);
4516
4517 /* Add DELTA to THIS_RTX. */
4518 nios2_emit_add_constant (this_rtx, delta);
4519
4520 /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */
4521 if (vcall_offset)
4522 {
4523 rtx tmp;
4524
4525 tmp = gen_rtx_REG (Pmode, 2);
4526 emit_move_insn (tmp, gen_rtx_MEM (Pmode, this_rtx));
4527 nios2_emit_add_constant (tmp, vcall_offset);
4528 emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
4529 emit_insn (gen_add2_insn (this_rtx, tmp));
4530 }
4531
4532 /* Generate a tail call to the target function. */
4533 if (!TREE_USED (function))
4534 {
4535 assemble_external (function);
4536 TREE_USED (function) = 1;
4537 }
4538 funexp = XEXP (DECL_RTL (function), 0);
4539 /* Function address needs to be constructed under PIC,
4540 provide r2 to use here. */
4541 nios2_adjust_call_address (&funexp, gen_rtx_REG (Pmode, 2));
4542 insn = emit_call_insn (gen_sibcall_internal (funexp, const0_rtx));
4543 SIBLING_CALL_P (insn) = 1;
4544
4545 /* Run just enough of rest_of_compilation to get the insns emitted.
4546 There's not really enough bulk here to make other passes such as
4547 instruction scheduling worth while. */
4548 insn = get_insns ();
4549 shorten_branches (insn);
4550 assemble_start_function (thunk_fndecl, fnname);
4551 final_start_function (insn, file, 1);
4552 final (insn, file, 1);
4553 final_end_function ();
4554 assemble_end_function (thunk_fndecl, fnname);
4555
4556 /* Stop pretending to be a post-reload pass. */
4557 reload_completed = 0;
4558 }
4559
4560
4561 /* Utility function to break a memory address into
4562 base register + constant offset. Return false if something
4563 unexpected is seen. */
4564 static bool
split_mem_address(rtx addr,rtx * base_reg,rtx * offset)4565 split_mem_address (rtx addr, rtx *base_reg, rtx *offset)
4566 {
4567 if (REG_P (addr))
4568 {
4569 *base_reg = addr;
4570 *offset = const0_rtx;
4571 return true;
4572 }
4573 else if (GET_CODE (addr) == PLUS)
4574 {
4575 *base_reg = XEXP (addr, 0);
4576 *offset = XEXP (addr, 1);
4577 return true;
4578 }
4579 return false;
4580 }
4581
4582 /* Splits out the operands of an ALU insn, places them in *LHS, *RHS1, *RHS2. */
4583 static void
split_alu_insn(rtx_insn * insn,rtx * lhs,rtx * rhs1,rtx * rhs2)4584 split_alu_insn (rtx_insn *insn, rtx *lhs, rtx *rhs1, rtx *rhs2)
4585 {
4586 rtx pat = PATTERN (insn);
4587 gcc_assert (GET_CODE (pat) == SET);
4588 *lhs = SET_DEST (pat);
4589 *rhs1 = XEXP (SET_SRC (pat), 0);
4590 if (GET_RTX_CLASS (GET_CODE (SET_SRC (pat))) != RTX_UNARY)
4591 *rhs2 = XEXP (SET_SRC (pat), 1);
4592 return;
4593 }
4594
4595 /* Returns true if OP is a REG and assigned a CDX reg. */
4596 static bool
cdxreg(rtx op)4597 cdxreg (rtx op)
4598 {
4599 return REG_P (op) && (!reload_completed || CDX_REG_P (REGNO (op)));
4600 }
4601
4602 /* Returns true if OP is within range of CDX addi.n immediates. */
4603 static bool
cdx_add_immed(rtx op)4604 cdx_add_immed (rtx op)
4605 {
4606 if (CONST_INT_P (op))
4607 {
4608 HOST_WIDE_INT ival = INTVAL (op);
4609 return ival <= 128 && ival > 0 && (ival & (ival - 1)) == 0;
4610 }
4611 return false;
4612 }
4613
4614 /* Returns true if OP is within range of CDX andi.n immediates. */
4615 static bool
cdx_and_immed(rtx op)4616 cdx_and_immed (rtx op)
4617 {
4618 if (CONST_INT_P (op))
4619 {
4620 HOST_WIDE_INT ival = INTVAL (op);
4621 return (ival == 1 || ival == 2 || ival == 3 || ival == 4
4622 || ival == 8 || ival == 0xf || ival == 0x10
4623 || ival == 0x1f || ival == 0x20
4624 || ival == 0x3f || ival == 0x7f
4625 || ival == 0x80 || ival == 0xff || ival == 0x7ff
4626 || ival == 0xff00 || ival == 0xffff);
4627 }
4628 return false;
4629 }
4630
4631 /* Returns true if OP is within range of CDX movi.n immediates. */
4632 static bool
cdx_mov_immed(rtx op)4633 cdx_mov_immed (rtx op)
4634 {
4635 if (CONST_INT_P (op))
4636 {
4637 HOST_WIDE_INT ival = INTVAL (op);
4638 return ((ival >= 0 && ival <= 124)
4639 || ival == 0xff || ival == -2 || ival == -1);
4640 }
4641 return false;
4642 }
4643
4644 /* Returns true if OP is within range of CDX slli.n/srli.n immediates. */
4645 static bool
cdx_shift_immed(rtx op)4646 cdx_shift_immed (rtx op)
4647 {
4648 if (CONST_INT_P (op))
4649 {
4650 HOST_WIDE_INT ival = INTVAL (op);
4651 return (ival == 1 || ival == 2 || ival == 3 || ival == 8
4652 || ival == 12 || ival == 16 || ival == 24
4653 || ival == 31);
4654 }
4655 return false;
4656 }
4657
4658
4659
4660 /* Classification of different kinds of add instructions. */
4661 enum nios2_add_insn_kind {
4662 nios2_add_n_kind,
4663 nios2_addi_n_kind,
4664 nios2_subi_n_kind,
4665 nios2_spaddi_n_kind,
4666 nios2_spinci_n_kind,
4667 nios2_spdeci_n_kind,
4668 nios2_add_kind,
4669 nios2_addi_kind
4670 };
4671
4672 static const char *nios2_add_insn_names[] = {
4673 "add.n", "addi.n", "subi.n", "spaddi.n", "spinci.n", "spdeci.n",
4674 "add", "addi" };
4675 static bool nios2_add_insn_narrow[] = {
4676 true, true, true, true, true, true,
4677 false, false};
4678
4679 /* Function to classify kinds of add instruction patterns. */
4680 static enum nios2_add_insn_kind
nios2_add_insn_classify(rtx_insn * insn ATTRIBUTE_UNUSED,rtx lhs,rtx rhs1,rtx rhs2)4681 nios2_add_insn_classify (rtx_insn *insn ATTRIBUTE_UNUSED,
4682 rtx lhs, rtx rhs1, rtx rhs2)
4683 {
4684 if (TARGET_HAS_CDX)
4685 {
4686 if (cdxreg (lhs) && cdxreg (rhs1))
4687 {
4688 if (cdxreg (rhs2))
4689 return nios2_add_n_kind;
4690 if (CONST_INT_P (rhs2))
4691 {
4692 HOST_WIDE_INT ival = INTVAL (rhs2);
4693 if (ival > 0 && cdx_add_immed (rhs2))
4694 return nios2_addi_n_kind;
4695 if (ival < 0 && cdx_add_immed (GEN_INT (-ival)))
4696 return nios2_subi_n_kind;
4697 }
4698 }
4699 else if (rhs1 == stack_pointer_rtx
4700 && CONST_INT_P (rhs2))
4701 {
4702 HOST_WIDE_INT imm7 = INTVAL (rhs2) >> 2;
4703 HOST_WIDE_INT rem = INTVAL (rhs2) & 3;
4704 if (rem == 0 && (imm7 & ~0x7f) == 0)
4705 {
4706 if (cdxreg (lhs))
4707 return nios2_spaddi_n_kind;
4708 if (lhs == stack_pointer_rtx)
4709 return nios2_spinci_n_kind;
4710 }
4711 imm7 = -INTVAL(rhs2) >> 2;
4712 rem = -INTVAL (rhs2) & 3;
4713 if (lhs == stack_pointer_rtx
4714 && rem == 0 && (imm7 & ~0x7f) == 0)
4715 return nios2_spdeci_n_kind;
4716 }
4717 }
4718 return ((REG_P (rhs2) || rhs2 == const0_rtx)
4719 ? nios2_add_kind : nios2_addi_kind);
4720 }
4721
4722 /* Emit assembly language for the different kinds of add instructions. */
4723 const char*
nios2_add_insn_asm(rtx_insn * insn,rtx * operands)4724 nios2_add_insn_asm (rtx_insn *insn, rtx *operands)
4725 {
4726 static char buf[256];
4727 int ln = 256;
4728 enum nios2_add_insn_kind kind
4729 = nios2_add_insn_classify (insn, operands[0], operands[1], operands[2]);
4730 if (kind == nios2_subi_n_kind)
4731 snprintf (buf, ln, "subi.n\t%%0, %%1, %d", (int) -INTVAL (operands[2]));
4732 else if (kind == nios2_spaddi_n_kind)
4733 snprintf (buf, ln, "spaddi.n\t%%0, %%2");
4734 else if (kind == nios2_spinci_n_kind)
4735 snprintf (buf, ln, "spinci.n\t%%2");
4736 else if (kind == nios2_spdeci_n_kind)
4737 snprintf (buf, ln, "spdeci.n\t%d", (int) -INTVAL (operands[2]));
4738 else
4739 snprintf (buf, ln, "%s\t%%0, %%1, %%z2", nios2_add_insn_names[(int)kind]);
4740 return buf;
4741 }
4742
4743 /* This routine, which the default "length" attribute computation is
4744 based on, encapsulates information about all the cases where CDX
4745 provides a narrow 2-byte instruction form. */
4746 bool
nios2_cdx_narrow_form_p(rtx_insn * insn)4747 nios2_cdx_narrow_form_p (rtx_insn *insn)
4748 {
4749 rtx pat, lhs, rhs1 = NULL_RTX, rhs2 = NULL_RTX;
4750 enum attr_type type;
4751 if (!TARGET_HAS_CDX)
4752 return false;
4753 type = get_attr_type (insn);
4754 pat = PATTERN (insn);
4755 gcc_assert (reload_completed);
4756 switch (type)
4757 {
4758 case TYPE_CONTROL:
4759 if (GET_CODE (pat) == SIMPLE_RETURN)
4760 return true;
4761 if (GET_CODE (pat) == PARALLEL)
4762 pat = XVECEXP (pat, 0, 0);
4763 if (GET_CODE (pat) == SET)
4764 pat = SET_SRC (pat);
4765 if (GET_CODE (pat) == IF_THEN_ELSE)
4766 {
4767 /* Conditional branch patterns; for these we
4768 only check the comparison to find beqz.n/bnez.n cases.
4769 For the 'nios2_cbranch' pattern, we cannot also check
4770 the branch range here. That will be done at the md
4771 pattern "length" attribute computation. */
4772 rtx cmp = XEXP (pat, 0);
4773 return ((GET_CODE (cmp) == EQ || GET_CODE (cmp) == NE)
4774 && cdxreg (XEXP (cmp, 0))
4775 && XEXP (cmp, 1) == const0_rtx);
4776 }
4777 if (GET_CODE (pat) == TRAP_IF)
4778 /* trap.n is always usable. */
4779 return true;
4780 if (GET_CODE (pat) == CALL)
4781 pat = XEXP (XEXP (pat, 0), 0);
4782 if (REG_P (pat))
4783 /* Control instructions taking a register operand are indirect
4784 jumps and calls. The CDX instructions have a 5-bit register
4785 field so any reg is valid. */
4786 return true;
4787 else
4788 {
4789 gcc_assert (!insn_variable_length_p (insn));
4790 return false;
4791 }
4792 case TYPE_ADD:
4793 {
4794 enum nios2_add_insn_kind kind;
4795 split_alu_insn (insn, &lhs, &rhs1, &rhs2);
4796 kind = nios2_add_insn_classify (insn, lhs, rhs1, rhs2);
4797 return nios2_add_insn_narrow[(int)kind];
4798 }
4799 case TYPE_LD:
4800 {
4801 bool ret;
4802 HOST_WIDE_INT offset, rem = 0;
4803 rtx addr, reg = SET_DEST (pat), mem = SET_SRC (pat);
4804 if (GET_CODE (mem) == SIGN_EXTEND)
4805 /* No CDX form for sign-extended load. */
4806 return false;
4807 if (GET_CODE (mem) == ZERO_EXTEND)
4808 /* The load alternatives in the zero_extend* patterns. */
4809 mem = XEXP (mem, 0);
4810 if (MEM_P (mem))
4811 {
4812 /* ldxio. */
4813 if ((MEM_VOLATILE_P (mem) && TARGET_BYPASS_CACHE_VOLATILE)
4814 || TARGET_BYPASS_CACHE)
4815 return false;
4816 addr = XEXP (mem, 0);
4817 /* GP-based and R0-based references are never narrow. */
4818 if (gprel_constant_p (addr) || r0rel_constant_p (addr))
4819 return false;
4820 /* %lo requires a 16-bit relocation and is never narrow. */
4821 if (GET_CODE (addr) == LO_SUM)
4822 return false;
4823 ret = split_mem_address (addr, &rhs1, &rhs2);
4824 gcc_assert (ret);
4825 }
4826 else
4827 return false;
4828
4829 offset = INTVAL (rhs2);
4830 if (GET_MODE (mem) == SImode)
4831 {
4832 rem = offset & 3;
4833 offset >>= 2;
4834 /* ldwsp.n case. */
4835 if (rtx_equal_p (rhs1, stack_pointer_rtx)
4836 && rem == 0 && (offset & ~0x1f) == 0)
4837 return true;
4838 }
4839 else if (GET_MODE (mem) == HImode)
4840 {
4841 rem = offset & 1;
4842 offset >>= 1;
4843 }
4844 /* ldbu.n, ldhu.n, ldw.n cases. */
4845 return (cdxreg (reg) && cdxreg (rhs1)
4846 && rem == 0 && (offset & ~0xf) == 0);
4847 }
4848 case TYPE_ST:
4849 if (GET_CODE (pat) == PARALLEL)
4850 /* stex, stsex. */
4851 return false;
4852 else
4853 {
4854 bool ret;
4855 HOST_WIDE_INT offset, rem = 0;
4856 rtx addr, reg = SET_SRC (pat), mem = SET_DEST (pat);
4857 if (!MEM_P (mem))
4858 return false;
4859 /* stxio. */
4860 if ((MEM_VOLATILE_P (mem) && TARGET_BYPASS_CACHE_VOLATILE)
4861 || TARGET_BYPASS_CACHE)
4862 return false;
4863 addr = XEXP (mem, 0);
4864 /* GP-based and r0-based references are never narrow. */
4865 if (gprel_constant_p (addr) || r0rel_constant_p (addr))
4866 return false;
4867 /* %lo requires a 16-bit relocation and is never narrow. */
4868 if (GET_CODE (addr) == LO_SUM)
4869 return false;
4870 ret = split_mem_address (addr, &rhs1, &rhs2);
4871 gcc_assert (ret);
4872 offset = INTVAL (rhs2);
4873 if (GET_MODE (mem) == SImode)
4874 {
4875 rem = offset & 3;
4876 offset >>= 2;
4877 /* stwsp.n case. */
4878 if (rtx_equal_p (rhs1, stack_pointer_rtx)
4879 && rem == 0 && (offset & ~0x1f) == 0)
4880 return true;
4881 /* stwz.n case. */
4882 else if (reg == const0_rtx && cdxreg (rhs1)
4883 && rem == 0 && (offset & ~0x3f) == 0)
4884 return true;
4885 }
4886 else if (GET_MODE (mem) == HImode)
4887 {
4888 rem = offset & 1;
4889 offset >>= 1;
4890 }
4891 else
4892 {
4893 gcc_assert (GET_MODE (mem) == QImode);
4894 /* stbz.n case. */
4895 if (reg == const0_rtx && cdxreg (rhs1)
4896 && (offset & ~0x3f) == 0)
4897 return true;
4898 }
4899
4900 /* stbu.n, sthu.n, stw.n cases. */
4901 return (cdxreg (reg) && cdxreg (rhs1)
4902 && rem == 0 && (offset & ~0xf) == 0);
4903 }
4904 case TYPE_MOV:
4905 lhs = SET_DEST (pat);
4906 rhs1 = SET_SRC (pat);
4907 if (CONST_INT_P (rhs1))
4908 return (cdxreg (lhs) && cdx_mov_immed (rhs1));
4909 gcc_assert (REG_P (lhs) && REG_P (rhs1));
4910 return true;
4911
4912 case TYPE_AND:
4913 /* Some zero_extend* alternatives are and insns. */
4914 if (GET_CODE (SET_SRC (pat)) == ZERO_EXTEND)
4915 return (cdxreg (SET_DEST (pat))
4916 && cdxreg (XEXP (SET_SRC (pat), 0)));
4917 split_alu_insn (insn, &lhs, &rhs1, &rhs2);
4918 if (CONST_INT_P (rhs2))
4919 return (cdxreg (lhs) && cdxreg (rhs1) && cdx_and_immed (rhs2));
4920 return (cdxreg (lhs) && cdxreg (rhs2)
4921 && (!reload_completed || rtx_equal_p (lhs, rhs1)));
4922
4923 case TYPE_OR:
4924 case TYPE_XOR:
4925 /* Note the two-address limitation for CDX form. */
4926 split_alu_insn (insn, &lhs, &rhs1, &rhs2);
4927 return (cdxreg (lhs) && cdxreg (rhs2)
4928 && (!reload_completed || rtx_equal_p (lhs, rhs1)));
4929
4930 case TYPE_SUB:
4931 split_alu_insn (insn, &lhs, &rhs1, &rhs2);
4932 return (cdxreg (lhs) && cdxreg (rhs1) && cdxreg (rhs2));
4933
4934 case TYPE_NEG:
4935 case TYPE_NOT:
4936 split_alu_insn (insn, &lhs, &rhs1, NULL);
4937 return (cdxreg (lhs) && cdxreg (rhs1));
4938
4939 case TYPE_SLL:
4940 case TYPE_SRL:
4941 split_alu_insn (insn, &lhs, &rhs1, &rhs2);
4942 return (cdxreg (lhs)
4943 && ((cdxreg (rhs1) && cdx_shift_immed (rhs2))
4944 || (cdxreg (rhs2)
4945 && (!reload_completed || rtx_equal_p (lhs, rhs1)))));
4946 case TYPE_NOP:
4947 case TYPE_PUSH:
4948 case TYPE_POP:
4949 return true;
4950 default:
4951 break;
4952 }
4953 return false;
4954 }
4955
4956 /* Main function to implement the pop_operation predicate that
4957 check pop.n insn pattern integrity. The CDX pop.n patterns mostly
4958 hardcode the restored registers, so the main checking is for the
4959 SP offsets. */
4960 bool
pop_operation_p(rtx op)4961 pop_operation_p (rtx op)
4962 {
4963 int i;
4964 HOST_WIDE_INT last_offset = -1, len = XVECLEN (op, 0);
4965 rtx base_reg, offset;
4966
4967 if (len < 3 /* At least has a return, SP-update, and RA restore. */
4968 || GET_CODE (XVECEXP (op, 0, 0)) != RETURN
4969 || !base_reg_adjustment_p (XVECEXP (op, 0, 1), &base_reg, &offset)
4970 || !rtx_equal_p (base_reg, stack_pointer_rtx)
4971 || !CONST_INT_P (offset)
4972 || (INTVAL (offset) & 3) != 0)
4973 return false;
4974
4975 for (i = len - 1; i > 1; i--)
4976 {
4977 rtx set = XVECEXP (op, 0, i);
4978 rtx curr_base_reg, curr_offset;
4979
4980 if (GET_CODE (set) != SET || !MEM_P (SET_SRC (set))
4981 || !split_mem_address (XEXP (SET_SRC (set), 0),
4982 &curr_base_reg, &curr_offset)
4983 || !rtx_equal_p (base_reg, curr_base_reg)
4984 || !CONST_INT_P (curr_offset))
4985 return false;
4986 if (i == len - 1)
4987 {
4988 last_offset = INTVAL (curr_offset);
4989 if ((last_offset & 3) != 0 || last_offset > 60)
4990 return false;
4991 }
4992 else
4993 {
4994 last_offset += 4;
4995 if (INTVAL (curr_offset) != last_offset)
4996 return false;
4997 }
4998 }
4999 if (last_offset < 0 || last_offset + 4 != INTVAL (offset))
5000 return false;
5001
5002 return true;
5003 }
5004
5005
5006 /* Masks of registers that are valid for CDX ldwm/stwm instructions.
5007 The instruction can encode subsets drawn from either R2-R13 or
5008 R14-R23 + FP + RA. */
5009 #define CDX_LDSTWM_VALID_REGS_0 0x00003ffc
5010 #define CDX_LDSTWM_VALID_REGS_1 0x90ffc000
5011
5012 static bool
nios2_ldstwm_regset_p(unsigned int regno,unsigned int * regset)5013 nios2_ldstwm_regset_p (unsigned int regno, unsigned int *regset)
5014 {
5015 if (*regset == 0)
5016 {
5017 if (CDX_LDSTWM_VALID_REGS_0 & (1 << regno))
5018 *regset = CDX_LDSTWM_VALID_REGS_0;
5019 else if (CDX_LDSTWM_VALID_REGS_1 & (1 << regno))
5020 *regset = CDX_LDSTWM_VALID_REGS_1;
5021 else
5022 return false;
5023 return true;
5024 }
5025 else
5026 return (*regset & (1 << regno)) != 0;
5027 }
5028
5029 /* Main function to implement ldwm_operation/stwm_operation
5030 predicates that check ldwm/stwm insn pattern integrity. */
5031 bool
ldstwm_operation_p(rtx op,bool load_p)5032 ldstwm_operation_p (rtx op, bool load_p)
5033 {
5034 int start, i, end = XVECLEN (op, 0) - 1, last_regno = -1;
5035 unsigned int regset = 0;
5036 rtx base_reg, offset;
5037 rtx first_elt = XVECEXP (op, 0, 0);
5038 bool inc_p = true;
5039 bool wb_p = base_reg_adjustment_p (first_elt, &base_reg, &offset);
5040 if (GET_CODE (XVECEXP (op, 0, end)) == RETURN)
5041 end--;
5042 start = wb_p ? 1 : 0;
5043 for (i = start; i <= end; i++)
5044 {
5045 int regno;
5046 rtx reg, mem, elt = XVECEXP (op, 0, i);
5047 /* Return early if not a SET at all. */
5048 if (GET_CODE (elt) != SET)
5049 return false;
5050 reg = load_p ? SET_DEST (elt) : SET_SRC (elt);
5051 mem = load_p ? SET_SRC (elt) : SET_DEST (elt);
5052 if (!REG_P (reg) || !MEM_P (mem))
5053 return false;
5054 regno = REGNO (reg);
5055 if (!nios2_ldstwm_regset_p (regno, ®set))
5056 return false;
5057 /* If no writeback to determine direction, use offset of first MEM. */
5058 if (wb_p)
5059 inc_p = INTVAL (offset) > 0;
5060 else if (i == start)
5061 {
5062 rtx first_base, first_offset;
5063 if (!split_mem_address (XEXP (mem, 0),
5064 &first_base, &first_offset))
5065 return false;
5066 if (!REG_P (first_base) || !CONST_INT_P (first_offset))
5067 return false;
5068 base_reg = first_base;
5069 inc_p = INTVAL (first_offset) >= 0;
5070 }
5071 /* Ensure that the base register is not loaded into. */
5072 if (load_p && regno == (int) REGNO (base_reg))
5073 return false;
5074 /* Check for register order inc/dec integrity. */
5075 if (last_regno >= 0)
5076 {
5077 if (inc_p && last_regno >= regno)
5078 return false;
5079 if (!inc_p && last_regno <= regno)
5080 return false;
5081 }
5082 last_regno = regno;
5083 }
5084 return true;
5085 }
5086
5087 /* Helper for nios2_ldst_parallel, for generating a parallel vector
5088 SET element. */
5089 static rtx
gen_ldst(bool load_p,int regno,rtx base_mem,int offset)5090 gen_ldst (bool load_p, int regno, rtx base_mem, int offset)
5091 {
5092 rtx reg = gen_rtx_REG (SImode, regno);
5093 rtx mem = adjust_address_nv (base_mem, SImode, offset);
5094 return gen_rtx_SET (load_p ? reg : mem,
5095 load_p ? mem : reg);
5096 }
5097
5098 /* A general routine for creating the body RTL pattern of
5099 ldwm/stwm/push.n/pop.n insns.
5100 LOAD_P: true/false for load/store direction.
5101 REG_INC_P: whether registers are incrementing/decrementing in the
5102 *RTL vector* (not necessarily the order defined in the ISA specification).
5103 OFFSET_INC_P: Same as REG_INC_P, but for the memory offset order.
5104 BASE_MEM: starting MEM.
5105 BASE_UPDATE: amount to update base register; zero means no writeback.
5106 REGMASK: register mask to load/store.
5107 RET_P: true if to tag a (return) element at the end.
5108
5109 Note that this routine does not do any checking. It's the job of the
5110 caller to do the right thing, and the insn patterns to do the
5111 safe-guarding. */
5112 static rtx
nios2_ldst_parallel(bool load_p,bool reg_inc_p,bool offset_inc_p,rtx base_mem,int base_update,unsigned HOST_WIDE_INT regmask,bool ret_p)5113 nios2_ldst_parallel (bool load_p, bool reg_inc_p, bool offset_inc_p,
5114 rtx base_mem, int base_update,
5115 unsigned HOST_WIDE_INT regmask, bool ret_p)
5116 {
5117 rtvec p;
5118 int regno, b = 0, i = 0, n = 0, len = popcount_hwi (regmask);
5119 if (ret_p) len++, i++, b++;
5120 if (base_update != 0) len++, i++;
5121 p = rtvec_alloc (len);
5122 for (regno = (reg_inc_p ? 0 : 31);
5123 regno != (reg_inc_p ? 32 : -1);
5124 regno += (reg_inc_p ? 1 : -1))
5125 if ((regmask & (1 << regno)) != 0)
5126 {
5127 int offset = (offset_inc_p ? 4 : -4) * n++;
5128 RTVEC_ELT (p, i++) = gen_ldst (load_p, regno, base_mem, offset);
5129 }
5130 if (ret_p)
5131 RTVEC_ELT (p, 0) = ret_rtx;
5132 if (base_update != 0)
5133 {
5134 rtx reg, offset;
5135 if (!split_mem_address (XEXP (base_mem, 0), ®, &offset))
5136 gcc_unreachable ();
5137 RTVEC_ELT (p, b) =
5138 gen_rtx_SET (reg, plus_constant (Pmode, reg, base_update));
5139 }
5140 return gen_rtx_PARALLEL (VOIDmode, p);
5141 }
5142
5143 /* CDX ldwm/stwm peephole optimization pattern related routines. */
5144
5145 /* Data structure and sorting function for ldwm/stwm peephole optimizers. */
5146 struct ldstwm_operand
5147 {
5148 int offset; /* Offset from base register. */
5149 rtx reg; /* Register to store at this offset. */
5150 rtx mem; /* Original mem. */
5151 bool bad; /* True if this load/store can't be combined. */
5152 bool rewrite; /* True if we should rewrite using scratch. */
5153 };
5154
5155 static int
compare_ldstwm_operands(const void * arg1,const void * arg2)5156 compare_ldstwm_operands (const void *arg1, const void *arg2)
5157 {
5158 const struct ldstwm_operand *op1 = (const struct ldstwm_operand *) arg1;
5159 const struct ldstwm_operand *op2 = (const struct ldstwm_operand *) arg2;
5160 if (op1->bad)
5161 return op2->bad ? 0 : 1;
5162 else if (op2->bad)
5163 return -1;
5164 else
5165 return op1->offset - op2->offset;
5166 }
5167
5168 /* Helper function: return true if a load/store using REGNO with address
5169 BASEREG and offset OFFSET meets the constraints for a 2-byte CDX ldw.n,
5170 stw.n, ldwsp.n, or stwsp.n instruction. */
5171 static bool
can_use_cdx_ldstw(int regno,int basereg,int offset)5172 can_use_cdx_ldstw (int regno, int basereg, int offset)
5173 {
5174 if (CDX_REG_P (regno) && CDX_REG_P (basereg)
5175 && (offset & 0x3) == 0 && offset >= 0 && offset < 0x40)
5176 return true;
5177 else if (basereg == SP_REGNO
5178 && offset >= 0 && offset < 0x80 && (offset & 0x3) == 0)
5179 return true;
5180 return false;
5181 }
5182
5183 /* This function is called from peephole2 optimizers to try to merge
5184 a series of individual loads and stores into a ldwm or stwm. It
5185 can also rewrite addresses inside the individual loads and stores
5186 using a common base register using a scratch register and smaller
5187 offsets if that allows them to use CDX ldw.n or stw.n instructions
5188 instead of 4-byte loads or stores.
5189 N is the number of insns we are trying to merge. SCRATCH is non-null
5190 if there is a scratch register available. The OPERANDS array contains
5191 alternating REG (even) and MEM (odd) operands. */
5192 bool
gen_ldstwm_peep(bool load_p,int n,rtx scratch,rtx * operands)5193 gen_ldstwm_peep (bool load_p, int n, rtx scratch, rtx *operands)
5194 {
5195 /* CDX ldwm/stwm instructions allow a maximum of 12 registers to be
5196 specified. */
5197 #define MAX_LDSTWM_OPS 12
5198 struct ldstwm_operand sort[MAX_LDSTWM_OPS];
5199 int basereg = -1;
5200 int baseoffset;
5201 int i, m, lastoffset, lastreg;
5202 unsigned int regmask = 0, usemask = 0, regset;
5203 bool needscratch;
5204 int newbasereg;
5205 int nbytes;
5206
5207 if (!TARGET_HAS_CDX)
5208 return false;
5209 if (n < 2 || n > MAX_LDSTWM_OPS)
5210 return false;
5211
5212 /* Check all the operands for validity and initialize the sort array.
5213 The places where we return false here are all situations that aren't
5214 expected to ever happen -- invalid patterns, invalid registers, etc. */
5215 for (i = 0; i < n; i++)
5216 {
5217 rtx base, offset;
5218 rtx reg = operands[i];
5219 rtx mem = operands[i + n];
5220 int r, o, regno;
5221 bool bad = false;
5222
5223 if (!REG_P (reg) || !MEM_P (mem))
5224 return false;
5225
5226 regno = REGNO (reg);
5227 if (regno > 31)
5228 return false;
5229 if (load_p && (regmask & (1 << regno)) != 0)
5230 return false;
5231 regmask |= 1 << regno;
5232
5233 if (!split_mem_address (XEXP (mem, 0), &base, &offset))
5234 return false;
5235 r = REGNO (base);
5236 o = INTVAL (offset);
5237
5238 if (basereg == -1)
5239 basereg = r;
5240 else if (r != basereg)
5241 bad = true;
5242 usemask |= 1 << r;
5243
5244 sort[i].bad = bad;
5245 sort[i].rewrite = false;
5246 sort[i].offset = o;
5247 sort[i].reg = reg;
5248 sort[i].mem = mem;
5249 }
5250
5251 /* If we are doing a series of register loads, we can't safely reorder
5252 them if any of the regs used in addr expressions are also being set. */
5253 if (load_p && (regmask & usemask))
5254 return false;
5255
5256 /* Sort the array by increasing mem offset order, then check that
5257 offsets are valid and register order matches mem order. At the
5258 end of this loop, m is the number of loads/stores we will try to
5259 combine; the rest are leftovers. */
5260 qsort (sort, n, sizeof (struct ldstwm_operand), compare_ldstwm_operands);
5261
5262 baseoffset = sort[0].offset;
5263 needscratch = baseoffset != 0;
5264 if (needscratch && !scratch)
5265 return false;
5266
5267 lastreg = regmask = regset = 0;
5268 lastoffset = baseoffset;
5269 for (m = 0; m < n && !sort[m].bad; m++)
5270 {
5271 int thisreg = REGNO (sort[m].reg);
5272 if (sort[m].offset != lastoffset
5273 || (m > 0 && lastreg >= thisreg)
5274 || !nios2_ldstwm_regset_p (thisreg, ®set))
5275 break;
5276 lastoffset += 4;
5277 lastreg = thisreg;
5278 regmask |= (1 << thisreg);
5279 }
5280
5281 /* For loads, make sure we are not overwriting the scratch reg.
5282 The peephole2 pattern isn't supposed to match unless the register is
5283 unused all the way through, so this isn't supposed to happen anyway. */
5284 if (load_p
5285 && needscratch
5286 && ((1 << REGNO (scratch)) & regmask) != 0)
5287 return false;
5288 newbasereg = needscratch ? (int) REGNO (scratch) : basereg;
5289
5290 /* We may be able to combine only the first m of the n total loads/stores
5291 into a single instruction. If m < 2, there's no point in emitting
5292 a ldwm/stwm at all, but we might be able to do further optimizations
5293 if we have a scratch. We will count the instruction lengths of the
5294 old and new patterns and store the savings in nbytes. */
5295 if (m < 2)
5296 {
5297 if (!needscratch)
5298 return false;
5299 m = 0;
5300 nbytes = 0;
5301 }
5302 else
5303 nbytes = -4; /* Size of ldwm/stwm. */
5304 if (needscratch)
5305 {
5306 int bo = baseoffset > 0 ? baseoffset : -baseoffset;
5307 if (CDX_REG_P (newbasereg)
5308 && CDX_REG_P (basereg)
5309 && bo <= 128 && bo > 0 && (bo & (bo - 1)) == 0)
5310 nbytes -= 2; /* Size of addi.n/subi.n. */
5311 else
5312 nbytes -= 4; /* Size of non-CDX addi. */
5313 }
5314
5315 /* Count the size of the input load/store instructions being replaced. */
5316 for (i = 0; i < m; i++)
5317 if (can_use_cdx_ldstw (REGNO (sort[i].reg), basereg, sort[i].offset))
5318 nbytes += 2;
5319 else
5320 nbytes += 4;
5321
5322 /* We may also be able to save a bit if we can rewrite non-CDX
5323 load/stores that can't be combined into the ldwm/stwm into CDX
5324 load/stores using the scratch reg. For example, this might happen
5325 if baseoffset is large, by bringing in the offsets in the load/store
5326 instructions within the range that fits in the CDX instruction. */
5327 if (needscratch && CDX_REG_P (newbasereg))
5328 for (i = m; i < n && !sort[i].bad; i++)
5329 if (!can_use_cdx_ldstw (REGNO (sort[i].reg), basereg, sort[i].offset)
5330 && can_use_cdx_ldstw (REGNO (sort[i].reg), newbasereg,
5331 sort[i].offset - baseoffset))
5332 {
5333 sort[i].rewrite = true;
5334 nbytes += 2;
5335 }
5336
5337 /* Are we good to go? */
5338 if (nbytes <= 0)
5339 return false;
5340
5341 /* Emit the scratch load. */
5342 if (needscratch)
5343 emit_insn (gen_rtx_SET (scratch, XEXP (sort[0].mem, 0)));
5344
5345 /* Emit the ldwm/stwm insn. */
5346 if (m > 0)
5347 {
5348 rtvec p = rtvec_alloc (m);
5349 for (i = 0; i < m; i++)
5350 {
5351 int offset = sort[i].offset;
5352 rtx mem, reg = sort[i].reg;
5353 rtx base_reg = gen_rtx_REG (Pmode, newbasereg);
5354 if (needscratch)
5355 offset -= baseoffset;
5356 mem = gen_rtx_MEM (SImode, plus_constant (Pmode, base_reg, offset));
5357 if (load_p)
5358 RTVEC_ELT (p, i) = gen_rtx_SET (reg, mem);
5359 else
5360 RTVEC_ELT (p, i) = gen_rtx_SET (mem, reg);
5361 }
5362 emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
5363 }
5364
5365 /* Emit any leftover load/stores as individual instructions, doing
5366 the previously-noted rewrites to use the scratch reg. */
5367 for (i = m; i < n; i++)
5368 {
5369 rtx reg = sort[i].reg;
5370 rtx mem = sort[i].mem;
5371 if (sort[i].rewrite)
5372 {
5373 int offset = sort[i].offset - baseoffset;
5374 mem = gen_rtx_MEM (SImode, plus_constant (Pmode, scratch, offset));
5375 }
5376 if (load_p)
5377 emit_move_insn (reg, mem);
5378 else
5379 emit_move_insn (mem, reg);
5380 }
5381 return true;
5382 }
5383
5384 /* Implement TARGET_MACHINE_DEPENDENT_REORG:
5385 We use this hook when emitting CDX code to enforce the 4-byte
5386 alignment requirement for labels that are used as the targets of
5387 jmpi instructions. CDX code can otherwise contain a mix of 16-bit
5388 and 32-bit instructions aligned on any 16-bit boundary, but functions
5389 and jmpi labels have to be 32-bit aligned because of the way the address
5390 is encoded in the instruction. */
5391
5392 static unsigned char *label_align;
5393 static int min_labelno, max_labelno;
5394
5395 static void
nios2_reorg(void)5396 nios2_reorg (void)
5397 {
5398 bool changed = true;
5399 rtx_insn *insn;
5400
5401 if (!TARGET_HAS_CDX)
5402 return;
5403
5404 /* Initialize the data structures. */
5405 if (label_align)
5406 free (label_align);
5407 max_labelno = max_label_num ();
5408 min_labelno = get_first_label_num ();
5409 label_align = XCNEWVEC (unsigned char, max_labelno - min_labelno + 1);
5410
5411 /* Iterate on inserting alignment and adjusting branch lengths until
5412 no more changes. */
5413 while (changed)
5414 {
5415 changed = false;
5416 shorten_branches (get_insns ());
5417
5418 for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
5419 if (JUMP_P (insn) && insn_variable_length_p (insn))
5420 {
5421 rtx label = JUMP_LABEL (insn);
5422 /* We use the current fact that all cases of 'jmpi'
5423 doing the actual branch in the machine description
5424 has a computed length of 6 or 8. Length 4 and below
5425 are all PC-relative 'br' branches without the jump-align
5426 problem. */
5427 if (label && LABEL_P (label) && get_attr_length (insn) > 4)
5428 {
5429 int index = CODE_LABEL_NUMBER (label) - min_labelno;
5430 if (label_align[index] != 2)
5431 {
5432 label_align[index] = 2;
5433 changed = true;
5434 }
5435 }
5436 }
5437 }
5438 }
5439
5440 /* Implement LABEL_ALIGN, using the information gathered in nios2_reorg. */
5441 int
nios2_label_align(rtx label)5442 nios2_label_align (rtx label)
5443 {
5444 int n = CODE_LABEL_NUMBER (label);
5445
5446 if (label_align && n >= min_labelno && n <= max_labelno)
5447 return MAX (label_align[n - min_labelno], align_labels.levels[0].log);
5448 return align_labels.levels[0].log;
5449 }
5450
5451 /* Implement ADJUST_REG_ALLOC_ORDER. We use the default ordering
5452 for R1 and non-CDX R2 code; for CDX we tweak thing to prefer
5453 the registers that can be used as operands to instructions that
5454 have 3-bit register fields. */
5455 void
nios2_adjust_reg_alloc_order(void)5456 nios2_adjust_reg_alloc_order (void)
5457 {
5458 const int cdx_reg_alloc_order[] =
5459 {
5460 /* Call-clobbered GPRs within CDX 3-bit encoded range. */
5461 2, 3, 4, 5, 6, 7,
5462 /* Call-saved GPRs within CDX 3-bit encoded range. */
5463 16, 17,
5464 /* Other call-clobbered GPRs. */
5465 8, 9, 10, 11, 12, 13, 14, 15,
5466 /* Other call-saved GPRs. RA placed first since it is always saved. */
5467 31, 18, 19, 20, 21, 22, 23, 28,
5468 /* Fixed GPRs, not used by the register allocator. */
5469 0, 1, 24, 25, 26, 27, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39
5470 };
5471
5472 if (TARGET_HAS_CDX)
5473 memcpy (reg_alloc_order, cdx_reg_alloc_order,
5474 sizeof (int) * FIRST_PSEUDO_REGISTER);
5475 }
5476
5477
5478 /* Initialize the GCC target structure. */
5479 #undef TARGET_ASM_FUNCTION_PROLOGUE
5480 #define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
5481
5482 #undef TARGET_IN_SMALL_DATA_P
5483 #define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
5484
5485 #undef TARGET_SECTION_TYPE_FLAGS
5486 #define TARGET_SECTION_TYPE_FLAGS nios2_section_type_flags
5487
5488 #undef TARGET_INIT_BUILTINS
5489 #define TARGET_INIT_BUILTINS nios2_init_builtins
5490 #undef TARGET_EXPAND_BUILTIN
5491 #define TARGET_EXPAND_BUILTIN nios2_expand_builtin
5492 #undef TARGET_BUILTIN_DECL
5493 #define TARGET_BUILTIN_DECL nios2_builtin_decl
5494
5495 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5496 #define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
5497
5498 #undef TARGET_CAN_ELIMINATE
5499 #define TARGET_CAN_ELIMINATE nios2_can_eliminate
5500
5501 #undef TARGET_FUNCTION_ARG
5502 #define TARGET_FUNCTION_ARG nios2_function_arg
5503
5504 #undef TARGET_FUNCTION_ARG_ADVANCE
5505 #define TARGET_FUNCTION_ARG_ADVANCE nios2_function_arg_advance
5506
5507 #undef TARGET_FUNCTION_ARG_PADDING
5508 #define TARGET_FUNCTION_ARG_PADDING nios2_function_arg_padding
5509
5510 #undef TARGET_ARG_PARTIAL_BYTES
5511 #define TARGET_ARG_PARTIAL_BYTES nios2_arg_partial_bytes
5512
5513 #undef TARGET_TRAMPOLINE_INIT
5514 #define TARGET_TRAMPOLINE_INIT nios2_trampoline_init
5515
5516 #undef TARGET_FUNCTION_VALUE
5517 #define TARGET_FUNCTION_VALUE nios2_function_value
5518
5519 #undef TARGET_LIBCALL_VALUE
5520 #define TARGET_LIBCALL_VALUE nios2_libcall_value
5521
5522 #undef TARGET_FUNCTION_VALUE_REGNO_P
5523 #define TARGET_FUNCTION_VALUE_REGNO_P nios2_function_value_regno_p
5524
5525 #undef TARGET_RETURN_IN_MEMORY
5526 #define TARGET_RETURN_IN_MEMORY nios2_return_in_memory
5527
5528 #undef TARGET_PROMOTE_PROTOTYPES
5529 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
5530
5531 #undef TARGET_SETUP_INCOMING_VARARGS
5532 #define TARGET_SETUP_INCOMING_VARARGS nios2_setup_incoming_varargs
5533
5534 #undef TARGET_MUST_PASS_IN_STACK
5535 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
5536
5537 #undef TARGET_LEGITIMATE_CONSTANT_P
5538 #define TARGET_LEGITIMATE_CONSTANT_P nios2_legitimate_constant_p
5539
5540 #undef TARGET_LEGITIMIZE_ADDRESS
5541 #define TARGET_LEGITIMIZE_ADDRESS nios2_legitimize_address
5542
5543 #undef TARGET_DELEGITIMIZE_ADDRESS
5544 #define TARGET_DELEGITIMIZE_ADDRESS nios2_delegitimize_address
5545
5546 #undef TARGET_LEGITIMATE_ADDRESS_P
5547 #define TARGET_LEGITIMATE_ADDRESS_P nios2_legitimate_address_p
5548
5549 #undef TARGET_PREFERRED_RELOAD_CLASS
5550 #define TARGET_PREFERRED_RELOAD_CLASS nios2_preferred_reload_class
5551
5552 #undef TARGET_RTX_COSTS
5553 #define TARGET_RTX_COSTS nios2_rtx_costs
5554
5555 #undef TARGET_ADDRESS_COST
5556 #define TARGET_ADDRESS_COST nios2_address_cost
5557
5558 #undef TARGET_HAVE_TLS
5559 #define TARGET_HAVE_TLS TARGET_LINUX_ABI
5560
5561 #undef TARGET_CANNOT_FORCE_CONST_MEM
5562 #define TARGET_CANNOT_FORCE_CONST_MEM nios2_cannot_force_const_mem
5563
5564 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
5565 #define TARGET_ASM_OUTPUT_DWARF_DTPREL nios2_output_dwarf_dtprel
5566
5567 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
5568 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P nios2_print_operand_punct_valid_p
5569
5570 #undef TARGET_PRINT_OPERAND
5571 #define TARGET_PRINT_OPERAND nios2_print_operand
5572
5573 #undef TARGET_PRINT_OPERAND_ADDRESS
5574 #define TARGET_PRINT_OPERAND_ADDRESS nios2_print_operand_address
5575
5576 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
5577 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA nios2_output_addr_const_extra
5578
5579 #undef TARGET_ASM_FILE_END
5580 #define TARGET_ASM_FILE_END nios2_asm_file_end
5581
5582 #undef TARGET_OPTION_OVERRIDE
5583 #define TARGET_OPTION_OVERRIDE nios2_option_override
5584
5585 #undef TARGET_OPTION_SAVE
5586 #define TARGET_OPTION_SAVE nios2_option_save
5587
5588 #undef TARGET_OPTION_RESTORE
5589 #define TARGET_OPTION_RESTORE nios2_option_restore
5590
5591 #undef TARGET_CAN_INLINE_P
5592 #define TARGET_CAN_INLINE_P nios2_can_inline_p
5593
5594 #undef TARGET_SET_CURRENT_FUNCTION
5595 #define TARGET_SET_CURRENT_FUNCTION nios2_set_current_function
5596
5597 #undef TARGET_OPTION_VALID_ATTRIBUTE_P
5598 #define TARGET_OPTION_VALID_ATTRIBUTE_P nios2_valid_target_attribute_p
5599
5600 #undef TARGET_OPTION_PRAGMA_PARSE
5601 #define TARGET_OPTION_PRAGMA_PARSE nios2_pragma_target_parse
5602
5603 #undef TARGET_MERGE_DECL_ATTRIBUTES
5604 #define TARGET_MERGE_DECL_ATTRIBUTES nios2_merge_decl_attributes
5605
5606 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5607 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
5608 hook_bool_const_tree_hwi_hwi_const_tree_true
5609
5610 #undef TARGET_ASM_OUTPUT_MI_THUNK
5611 #define TARGET_ASM_OUTPUT_MI_THUNK nios2_asm_output_mi_thunk
5612
5613 #undef TARGET_MACHINE_DEPENDENT_REORG
5614 #define TARGET_MACHINE_DEPENDENT_REORG nios2_reorg
5615
5616 #undef TARGET_CONSTANT_ALIGNMENT
5617 #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
5618
5619 #undef TARGET_HAVE_SPECULATION_SAFE_VALUE
5620 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
5621
5622 struct gcc_target targetm = TARGET_INITIALIZER;
5623
5624 #include "gt-nios2.h"
5625