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