2015-01-15 Sandra Loosemore <sandra@codesourcery.com>
[official-gcc.git] / gcc / config / nios2 / nios2.c
blob502314942ccd18d3b42d9371db4e2037ce0f8cd5
1 /* Target machine subroutines for Altera Nios II.
2 Copyright (C) 2012-2015 Free Software Foundation, Inc.
3 Contributed by Jonah Graham (jgraham@altera.com),
4 Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@altera.com).
5 Contributed by Mentor Graphics, Inc.
7 This file is part of GCC.
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.
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.
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/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "rtl.h"
28 #include "hash-set.h"
29 #include "machmode.h"
30 #include "vec.h"
31 #include "double-int.h"
32 #include "input.h"
33 #include "alias.h"
34 #include "symtab.h"
35 #include "wide-int.h"
36 #include "inchash.h"
37 #include "tree.h"
38 #include "fold-const.h"
39 #include "regs.h"
40 #include "hard-reg-set.h"
41 #include "insn-config.h"
42 #include "conditions.h"
43 #include "output.h"
44 #include "insn-attr.h"
45 #include "flags.h"
46 #include "recog.h"
47 #include "hashtab.h"
48 #include "function.h"
49 #include "statistics.h"
50 #include "real.h"
51 #include "fixed-value.h"
52 #include "expmed.h"
53 #include "dojump.h"
54 #include "explow.h"
55 #include "calls.h"
56 #include "emit-rtl.h"
57 #include "varasm.h"
58 #include "stmt.h"
59 #include "expr.h"
60 #include "insn-codes.h"
61 #include "optabs.h"
62 #include "ggc.h"
63 #include "predict.h"
64 #include "dominance.h"
65 #include "cfg.h"
66 #include "cfgrtl.h"
67 #include "cfganal.h"
68 #include "lcm.h"
69 #include "cfgbuild.h"
70 #include "cfgcleanup.h"
71 #include "basic-block.h"
72 #include "diagnostic-core.h"
73 #include "toplev.h"
74 #include "target.h"
75 #include "target-def.h"
76 #include "tm_p.h"
77 #include "langhooks.h"
78 #include "df.h"
79 #include "debug.h"
80 #include "reload.h"
81 #include "stor-layout.h"
82 #include "builtins.h"
84 /* Forward function declarations. */
85 static bool prologue_saved_reg_p (unsigned);
86 static void nios2_load_pic_register (void);
87 static void nios2_register_custom_code (unsigned int, enum nios2_ccs_code, int);
88 static const char *nios2_unspec_reloc_name (int);
89 static void nios2_register_builtin_fndecl (unsigned, tree);
91 /* Threshold for data being put into the small data/bss area, instead
92 of the normal data area (references to the small data/bss area take
93 1 instruction, and use the global pointer, references to the normal
94 data area takes 2 instructions). */
95 unsigned HOST_WIDE_INT nios2_section_threshold = NIOS2_DEFAULT_GVALUE;
97 struct GTY (()) machine_function
99 /* Current frame information, to be filled in by nios2_compute_frame_layout
100 with register save masks, and offsets for the current function. */
102 /* Mask of registers to save. */
103 unsigned int save_mask;
104 /* Number of bytes that the entire frame takes up. */
105 int total_size;
106 /* Number of bytes that variables take up. */
107 int var_size;
108 /* Number of bytes that outgoing arguments take up. */
109 int args_size;
110 /* Number of bytes needed to store registers in frame. */
111 int save_reg_size;
112 /* Offset from new stack pointer to store registers. */
113 int save_regs_offset;
114 /* Offset from save_regs_offset to store frame pointer register. */
115 int fp_save_offset;
116 /* != 0 if frame layout already calculated. */
117 int initialized;
120 /* State to track the assignment of custom codes to FPU/custom builtins. */
121 static enum nios2_ccs_code custom_code_status[256];
122 static int custom_code_index[256];
123 /* Set to true if any conflicts (re-use of a code between 0-255) are found. */
124 static bool custom_code_conflict = false;
127 /* Definition of builtin function types for nios2. */
129 #define N2_FTYPES \
130 N2_FTYPE(1, (SF)) \
131 N2_FTYPE(1, (VOID)) \
132 N2_FTYPE(2, (DF, DF)) \
133 N2_FTYPE(3, (DF, DF, DF)) \
134 N2_FTYPE(2, (DF, SF)) \
135 N2_FTYPE(2, (DF, SI)) \
136 N2_FTYPE(2, (DF, UI)) \
137 N2_FTYPE(2, (SF, DF)) \
138 N2_FTYPE(2, (SF, SF)) \
139 N2_FTYPE(3, (SF, SF, SF)) \
140 N2_FTYPE(2, (SF, SI)) \
141 N2_FTYPE(2, (SF, UI)) \
142 N2_FTYPE(2, (SI, CVPTR)) \
143 N2_FTYPE(2, (SI, DF)) \
144 N2_FTYPE(3, (SI, DF, DF)) \
145 N2_FTYPE(2, (SI, SF)) \
146 N2_FTYPE(3, (SI, SF, SF)) \
147 N2_FTYPE(2, (SI, SI)) \
148 N2_FTYPE(2, (UI, CVPTR)) \
149 N2_FTYPE(2, (UI, DF)) \
150 N2_FTYPE(2, (UI, SF)) \
151 N2_FTYPE(2, (VOID, DF)) \
152 N2_FTYPE(2, (VOID, SF)) \
153 N2_FTYPE(3, (VOID, SI, SI)) \
154 N2_FTYPE(3, (VOID, VPTR, SI))
156 #define N2_FTYPE_OP1(R) N2_FTYPE_ ## R ## _VOID
157 #define N2_FTYPE_OP2(R, A1) N2_FTYPE_ ## R ## _ ## A1
158 #define N2_FTYPE_OP3(R, A1, A2) N2_FTYPE_ ## R ## _ ## A1 ## _ ## A2
160 /* Expand ftcode enumeration. */
161 enum nios2_ftcode {
162 #define N2_FTYPE(N,ARGS) N2_FTYPE_OP ## N ARGS,
163 N2_FTYPES
164 #undef N2_FTYPE
165 N2_FTYPE_MAX
168 /* Return the tree function type, based on the ftcode. */
169 static tree
170 nios2_ftype (enum nios2_ftcode ftcode)
172 static tree types[(int) N2_FTYPE_MAX];
174 tree N2_TYPE_SF = float_type_node;
175 tree N2_TYPE_DF = double_type_node;
176 tree N2_TYPE_SI = integer_type_node;
177 tree N2_TYPE_UI = unsigned_type_node;
178 tree N2_TYPE_VOID = void_type_node;
180 static const_tree N2_TYPE_CVPTR, N2_TYPE_VPTR;
181 if (!N2_TYPE_CVPTR)
183 /* const volatile void *. */
184 N2_TYPE_CVPTR
185 = build_pointer_type (build_qualified_type (void_type_node,
186 (TYPE_QUAL_CONST
187 | TYPE_QUAL_VOLATILE)));
188 /* volatile void *. */
189 N2_TYPE_VPTR
190 = build_pointer_type (build_qualified_type (void_type_node,
191 TYPE_QUAL_VOLATILE));
193 if (types[(int) ftcode] == NULL_TREE)
194 switch (ftcode)
196 #define N2_FTYPE_ARGS1(R) N2_TYPE_ ## R
197 #define N2_FTYPE_ARGS2(R,A1) N2_TYPE_ ## R, N2_TYPE_ ## A1
198 #define N2_FTYPE_ARGS3(R,A1,A2) N2_TYPE_ ## R, N2_TYPE_ ## A1, N2_TYPE_ ## A2
199 #define N2_FTYPE(N,ARGS) \
200 case N2_FTYPE_OP ## N ARGS: \
201 types[(int) ftcode] \
202 = build_function_type_list (N2_FTYPE_ARGS ## N ARGS, NULL_TREE); \
203 break;
204 N2_FTYPES
205 #undef N2_FTYPE
206 default: gcc_unreachable ();
208 return types[(int) ftcode];
212 /* Definition of FPU instruction descriptions. */
214 struct nios2_fpu_insn_info
216 const char *name;
217 int num_operands, *optvar;
218 int opt, no_opt;
219 #define N2F_DF 0x1
220 #define N2F_DFREQ 0x2
221 #define N2F_UNSAFE 0x4
222 #define N2F_FINITE 0x8
223 #define N2F_NO_ERRNO 0x10
224 unsigned int flags;
225 enum insn_code icode;
226 enum nios2_ftcode ftcode;
229 /* Base macro for defining FPU instructions. */
230 #define N2FPU_INSN_DEF_BASE(insn, nop, flags, icode, args) \
231 { #insn, nop, &nios2_custom_ ## insn, OPT_mcustom_##insn##_, \
232 OPT_mno_custom_##insn, flags, CODE_FOR_ ## icode, \
233 N2_FTYPE_OP ## nop args }
235 /* Arithmetic and math functions; 2 or 3 operand FP operations. */
236 #define N2FPU_OP2(mode) (mode, mode)
237 #define N2FPU_OP3(mode) (mode, mode, mode)
238 #define N2FPU_INSN_DEF(code, icode, nop, flags, m, M) \
239 N2FPU_INSN_DEF_BASE (f ## code ## m, nop, flags, \
240 icode ## m ## f ## nop, N2FPU_OP ## nop (M ## F))
241 #define N2FPU_INSN_SF(code, nop, flags) \
242 N2FPU_INSN_DEF (code, code, nop, flags, s, S)
243 #define N2FPU_INSN_DF(code, nop, flags) \
244 N2FPU_INSN_DEF (code, code, nop, flags | N2F_DF, d, D)
246 /* Compare instructions, 3 operand FP operation with a SI result. */
247 #define N2FPU_CMP_DEF(code, flags, m, M) \
248 N2FPU_INSN_DEF_BASE (fcmp ## code ## m, 3, flags, \
249 nios2_s ## code ## m ## f, (SI, M ## F, M ## F))
250 #define N2FPU_CMP_SF(code) N2FPU_CMP_DEF (code, 0, s, S)
251 #define N2FPU_CMP_DF(code) N2FPU_CMP_DEF (code, N2F_DF, d, D)
253 /* The order of definition needs to be maintained consistent with
254 enum n2fpu_code in nios2-opts.h. */
255 struct nios2_fpu_insn_info nios2_fpu_insn[] =
257 /* Single precision instructions. */
258 N2FPU_INSN_SF (add, 3, 0),
259 N2FPU_INSN_SF (sub, 3, 0),
260 N2FPU_INSN_SF (mul, 3, 0),
261 N2FPU_INSN_SF (div, 3, 0),
262 /* Due to textual difference between min/max and smin/smax. */
263 N2FPU_INSN_DEF (min, smin, 3, N2F_FINITE, s, S),
264 N2FPU_INSN_DEF (max, smax, 3, N2F_FINITE, s, S),
265 N2FPU_INSN_SF (neg, 2, 0),
266 N2FPU_INSN_SF (abs, 2, 0),
267 N2FPU_INSN_SF (sqrt, 2, 0),
268 N2FPU_INSN_SF (sin, 2, N2F_UNSAFE),
269 N2FPU_INSN_SF (cos, 2, N2F_UNSAFE),
270 N2FPU_INSN_SF (tan, 2, N2F_UNSAFE),
271 N2FPU_INSN_SF (atan, 2, N2F_UNSAFE),
272 N2FPU_INSN_SF (exp, 2, N2F_UNSAFE),
273 N2FPU_INSN_SF (log, 2, N2F_UNSAFE),
274 /* Single precision compares. */
275 N2FPU_CMP_SF (eq), N2FPU_CMP_SF (ne),
276 N2FPU_CMP_SF (lt), N2FPU_CMP_SF (le),
277 N2FPU_CMP_SF (gt), N2FPU_CMP_SF (ge),
279 /* Double precision instructions. */
280 N2FPU_INSN_DF (add, 3, 0),
281 N2FPU_INSN_DF (sub, 3, 0),
282 N2FPU_INSN_DF (mul, 3, 0),
283 N2FPU_INSN_DF (div, 3, 0),
284 /* Due to textual difference between min/max and smin/smax. */
285 N2FPU_INSN_DEF (min, smin, 3, N2F_FINITE, d, D),
286 N2FPU_INSN_DEF (max, smax, 3, N2F_FINITE, d, D),
287 N2FPU_INSN_DF (neg, 2, 0),
288 N2FPU_INSN_DF (abs, 2, 0),
289 N2FPU_INSN_DF (sqrt, 2, 0),
290 N2FPU_INSN_DF (sin, 2, N2F_UNSAFE),
291 N2FPU_INSN_DF (cos, 2, N2F_UNSAFE),
292 N2FPU_INSN_DF (tan, 2, N2F_UNSAFE),
293 N2FPU_INSN_DF (atan, 2, N2F_UNSAFE),
294 N2FPU_INSN_DF (exp, 2, N2F_UNSAFE),
295 N2FPU_INSN_DF (log, 2, N2F_UNSAFE),
296 /* Double precision compares. */
297 N2FPU_CMP_DF (eq), N2FPU_CMP_DF (ne),
298 N2FPU_CMP_DF (lt), N2FPU_CMP_DF (le),
299 N2FPU_CMP_DF (gt), N2FPU_CMP_DF (ge),
301 /* Conversion instructions. */
302 N2FPU_INSN_DEF_BASE (floatis, 2, 0, floatsisf2, (SF, SI)),
303 N2FPU_INSN_DEF_BASE (floatus, 2, 0, floatunssisf2, (SF, UI)),
304 N2FPU_INSN_DEF_BASE (floatid, 2, 0, floatsidf2, (DF, SI)),
305 N2FPU_INSN_DEF_BASE (floatud, 2, 0, floatunssidf2, (DF, UI)),
306 N2FPU_INSN_DEF_BASE (round, 2, N2F_NO_ERRNO, lroundsfsi2, (SI, SF)),
307 N2FPU_INSN_DEF_BASE (fixsi, 2, 0, fix_truncsfsi2, (SI, SF)),
308 N2FPU_INSN_DEF_BASE (fixsu, 2, 0, fixuns_truncsfsi2, (UI, SF)),
309 N2FPU_INSN_DEF_BASE (fixdi, 2, 0, fix_truncdfsi2, (SI, DF)),
310 N2FPU_INSN_DEF_BASE (fixdu, 2, 0, fixuns_truncdfsi2, (UI, DF)),
311 N2FPU_INSN_DEF_BASE (fextsd, 2, 0, extendsfdf2, (DF, SF)),
312 N2FPU_INSN_DEF_BASE (ftruncds, 2, 0, truncdfsf2, (SF, DF)),
314 /* X, Y access instructions. */
315 N2FPU_INSN_DEF_BASE (fwrx, 2, N2F_DFREQ, nios2_fwrx, (VOID, DF)),
316 N2FPU_INSN_DEF_BASE (fwry, 2, N2F_DFREQ, nios2_fwry, (VOID, SF)),
317 N2FPU_INSN_DEF_BASE (frdxlo, 1, N2F_DFREQ, nios2_frdxlo, (SF)),
318 N2FPU_INSN_DEF_BASE (frdxhi, 1, N2F_DFREQ, nios2_frdxhi, (SF)),
319 N2FPU_INSN_DEF_BASE (frdy, 1, N2F_DFREQ, nios2_frdy, (SF))
322 /* Some macros for ease of access. */
323 #define N2FPU(code) nios2_fpu_insn[(int) code]
324 #define N2FPU_ENABLED_P(code) (N2FPU_N(code) >= 0)
325 #define N2FPU_N(code) (*N2FPU(code).optvar)
326 #define N2FPU_NAME(code) (N2FPU(code).name)
327 #define N2FPU_ICODE(code) (N2FPU(code).icode)
328 #define N2FPU_FTCODE(code) (N2FPU(code).ftcode)
329 #define N2FPU_FINITE_P(code) (N2FPU(code).flags & N2F_FINITE)
330 #define N2FPU_UNSAFE_P(code) (N2FPU(code).flags & N2F_UNSAFE)
331 #define N2FPU_NO_ERRNO_P(code) (N2FPU(code).flags & N2F_NO_ERRNO)
332 #define N2FPU_DOUBLE_P(code) (N2FPU(code).flags & N2F_DF)
333 #define N2FPU_DOUBLE_REQUIRED_P(code) (N2FPU(code).flags & N2F_DFREQ)
335 /* Same as above, but for cases where using only the op part is shorter. */
336 #define N2FPU_OP(op) N2FPU(n2fpu_ ## op)
337 #define N2FPU_OP_NAME(op) N2FPU_NAME(n2fpu_ ## op)
338 #define N2FPU_OP_ENABLED_P(op) N2FPU_ENABLED_P(n2fpu_ ## op)
340 /* Export the FPU insn enabled predicate to nios2.md. */
341 bool
342 nios2_fpu_insn_enabled (enum n2fpu_code code)
344 return N2FPU_ENABLED_P (code);
347 /* Return true if COND comparison for mode MODE is enabled under current
348 settings. */
350 static bool
351 nios2_fpu_compare_enabled (enum rtx_code cond, machine_mode mode)
353 if (mode == SFmode)
354 switch (cond)
356 case EQ: return N2FPU_OP_ENABLED_P (fcmpeqs);
357 case NE: return N2FPU_OP_ENABLED_P (fcmpnes);
358 case GT: return N2FPU_OP_ENABLED_P (fcmpgts);
359 case GE: return N2FPU_OP_ENABLED_P (fcmpges);
360 case LT: return N2FPU_OP_ENABLED_P (fcmplts);
361 case LE: return N2FPU_OP_ENABLED_P (fcmples);
362 default: break;
364 else if (mode == DFmode)
365 switch (cond)
367 case EQ: return N2FPU_OP_ENABLED_P (fcmpeqd);
368 case NE: return N2FPU_OP_ENABLED_P (fcmpned);
369 case GT: return N2FPU_OP_ENABLED_P (fcmpgtd);
370 case GE: return N2FPU_OP_ENABLED_P (fcmpged);
371 case LT: return N2FPU_OP_ENABLED_P (fcmpltd);
372 case LE: return N2FPU_OP_ENABLED_P (fcmpled);
373 default: break;
375 return false;
378 /* Stack layout and calling conventions. */
380 #define NIOS2_STACK_ALIGN(LOC) \
381 (((LOC) + ((PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) - 1)) \
382 & ~((PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) - 1))
384 /* Return the bytes needed to compute the frame pointer from the current
385 stack pointer. */
386 static int
387 nios2_compute_frame_layout (void)
389 unsigned int regno;
390 unsigned int save_mask = 0;
391 int total_size;
392 int var_size;
393 int out_args_size;
394 int save_reg_size;
396 if (cfun->machine->initialized)
397 return cfun->machine->total_size;
399 var_size = NIOS2_STACK_ALIGN (get_frame_size ());
400 out_args_size = NIOS2_STACK_ALIGN (crtl->outgoing_args_size);
401 total_size = var_size + out_args_size;
403 /* Calculate space needed for gp registers. */
404 save_reg_size = 0;
405 for (regno = 0; regno <= LAST_GP_REG; regno++)
406 if (prologue_saved_reg_p (regno))
408 save_mask |= 1 << regno;
409 save_reg_size += 4;
412 /* If we call eh_return, we need to save the EH data registers. */
413 if (crtl->calls_eh_return)
415 unsigned i;
416 unsigned r;
418 for (i = 0; (r = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++)
419 if (!(save_mask & (1 << r)))
421 save_mask |= 1 << r;
422 save_reg_size += 4;
426 cfun->machine->fp_save_offset = 0;
427 if (save_mask & (1 << HARD_FRAME_POINTER_REGNUM))
429 int fp_save_offset = 0;
430 for (regno = 0; regno < HARD_FRAME_POINTER_REGNUM; regno++)
431 if (save_mask & (1 << regno))
432 fp_save_offset += 4;
434 cfun->machine->fp_save_offset = fp_save_offset;
437 save_reg_size = NIOS2_STACK_ALIGN (save_reg_size);
438 total_size += save_reg_size;
439 total_size += NIOS2_STACK_ALIGN (crtl->args.pretend_args_size);
441 /* Save other computed information. */
442 cfun->machine->save_mask = save_mask;
443 cfun->machine->total_size = total_size;
444 cfun->machine->var_size = var_size;
445 cfun->machine->args_size = out_args_size;
446 cfun->machine->save_reg_size = save_reg_size;
447 cfun->machine->initialized = reload_completed;
448 cfun->machine->save_regs_offset = out_args_size + var_size;
450 return total_size;
453 /* Generate save/restore of register REGNO at SP + OFFSET. Used by the
454 prologue/epilogue expand routines. */
455 static void
456 save_reg (int regno, unsigned offset)
458 rtx reg = gen_rtx_REG (SImode, regno);
459 rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
460 gen_int_mode (offset, Pmode));
461 rtx insn = emit_move_insn (gen_frame_mem (Pmode, addr), reg);
462 RTX_FRAME_RELATED_P (insn) = 1;
465 static void
466 restore_reg (int regno, unsigned offset)
468 rtx reg = gen_rtx_REG (SImode, regno);
469 rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
470 gen_int_mode (offset, Pmode));
471 rtx insn = emit_move_insn (reg, gen_frame_mem (Pmode, addr));
472 /* Tag epilogue unwind note. */
473 add_reg_note (insn, REG_CFA_RESTORE, reg);
474 RTX_FRAME_RELATED_P (insn) = 1;
477 /* Emit conditional trap for checking stack limit. */
478 static void
479 nios2_emit_stack_limit_check (void)
481 if (REG_P (stack_limit_rtx))
482 emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode, stack_pointer_rtx,
483 stack_limit_rtx),
484 stack_pointer_rtx, stack_limit_rtx, GEN_INT (3)));
485 else
486 sorry ("only register based stack limit is supported");
489 /* Temp regno used inside prologue/epilogue. */
490 #define TEMP_REG_NUM 8
492 void
493 nios2_expand_prologue (void)
495 unsigned int regno;
496 int total_frame_size, save_offset;
497 int sp_offset; /* offset from base_reg to final stack value. */
498 int save_regs_base; /* offset from base_reg to register save area. */
499 rtx insn;
501 total_frame_size = nios2_compute_frame_layout ();
503 if (flag_stack_usage_info)
504 current_function_static_stack_size = total_frame_size;
506 /* Decrement the stack pointer. */
507 if (!SMALL_INT (total_frame_size))
509 /* We need an intermediary point, this will point at the spill block. */
510 insn = emit_insn
511 (gen_add2_insn (stack_pointer_rtx,
512 gen_int_mode (cfun->machine->save_regs_offset
513 - total_frame_size, Pmode)));
514 RTX_FRAME_RELATED_P (insn) = 1;
515 save_regs_base = 0;
516 sp_offset = -cfun->machine->save_regs_offset;
518 else if (total_frame_size)
520 insn = emit_insn (gen_add2_insn (stack_pointer_rtx,
521 gen_int_mode (-total_frame_size,
522 Pmode)));
523 RTX_FRAME_RELATED_P (insn) = 1;
524 save_regs_base = cfun->machine->save_regs_offset;
525 sp_offset = 0;
527 else
528 save_regs_base = sp_offset = 0;
530 if (crtl->limit_stack)
531 nios2_emit_stack_limit_check ();
533 save_offset = save_regs_base + cfun->machine->save_reg_size;
535 for (regno = LAST_GP_REG; regno > 0; regno--)
536 if (cfun->machine->save_mask & (1 << regno))
538 save_offset -= 4;
539 save_reg (regno, save_offset);
542 if (frame_pointer_needed)
544 int fp_save_offset = save_regs_base + cfun->machine->fp_save_offset;
545 insn = emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
546 stack_pointer_rtx,
547 gen_int_mode (fp_save_offset, Pmode)));
548 RTX_FRAME_RELATED_P (insn) = 1;
551 if (sp_offset)
553 rtx sp_adjust
554 = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
555 plus_constant (Pmode, stack_pointer_rtx, sp_offset));
556 if (SMALL_INT (sp_offset))
557 insn = emit_insn (sp_adjust);
558 else
560 rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
561 emit_move_insn (tmp, gen_int_mode (sp_offset, Pmode));
562 insn = emit_insn (gen_add2_insn (stack_pointer_rtx, tmp));
563 /* Attach the sp_adjust as a note indicating what happened. */
564 add_reg_note (insn, REG_FRAME_RELATED_EXPR, sp_adjust);
566 RTX_FRAME_RELATED_P (insn) = 1;
568 if (crtl->limit_stack)
569 nios2_emit_stack_limit_check ();
572 /* Load the PIC register if needed. */
573 if (crtl->uses_pic_offset_table)
574 nios2_load_pic_register ();
576 /* If we are profiling, make sure no instructions are scheduled before
577 the call to mcount. */
578 if (crtl->profile)
579 emit_insn (gen_blockage ());
582 void
583 nios2_expand_epilogue (bool sibcall_p)
585 rtx insn, cfa_adj;
586 int total_frame_size;
587 int sp_adjust, save_offset;
588 unsigned int regno;
590 if (!sibcall_p && nios2_can_use_return_insn ())
592 emit_jump_insn (gen_return ());
593 return;
596 emit_insn (gen_blockage ());
598 total_frame_size = nios2_compute_frame_layout ();
599 if (frame_pointer_needed)
601 /* Recover the stack pointer. */
602 insn = emit_insn (gen_add3_insn
603 (stack_pointer_rtx, hard_frame_pointer_rtx,
604 gen_int_mode (-cfun->machine->fp_save_offset, Pmode)));
605 cfa_adj = plus_constant (Pmode, stack_pointer_rtx,
606 (total_frame_size
607 - cfun->machine->save_regs_offset));
608 add_reg_note (insn, REG_CFA_DEF_CFA, cfa_adj);
609 RTX_FRAME_RELATED_P (insn) = 1;
611 save_offset = 0;
612 sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
614 else if (!SMALL_INT (total_frame_size))
616 rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
617 emit_move_insn (tmp, gen_int_mode (cfun->machine->save_regs_offset,
618 Pmode));
619 insn = emit_insn (gen_add2_insn (stack_pointer_rtx, tmp));
620 cfa_adj = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
621 plus_constant (Pmode, stack_pointer_rtx,
622 cfun->machine->save_regs_offset));
623 add_reg_note (insn, REG_CFA_ADJUST_CFA, cfa_adj);
624 RTX_FRAME_RELATED_P (insn) = 1;
625 save_offset = 0;
626 sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
628 else
630 save_offset = cfun->machine->save_regs_offset;
631 sp_adjust = total_frame_size;
634 save_offset += cfun->machine->save_reg_size;
636 for (regno = LAST_GP_REG; regno > 0; regno--)
637 if (cfun->machine->save_mask & (1 << regno))
639 save_offset -= 4;
640 restore_reg (regno, save_offset);
643 if (sp_adjust)
645 insn = emit_insn (gen_add2_insn (stack_pointer_rtx,
646 gen_int_mode (sp_adjust, Pmode)));
647 cfa_adj = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
648 plus_constant (Pmode, stack_pointer_rtx,
649 sp_adjust));
650 add_reg_note (insn, REG_CFA_ADJUST_CFA, cfa_adj);
651 RTX_FRAME_RELATED_P (insn) = 1;
654 /* Add in the __builtin_eh_return stack adjustment. */
655 if (crtl->calls_eh_return)
656 emit_insn (gen_add2_insn (stack_pointer_rtx, EH_RETURN_STACKADJ_RTX));
658 if (!sibcall_p)
659 emit_jump_insn (gen_simple_return ());
662 /* Implement RETURN_ADDR_RTX. Note, we do not support moving
663 back to a previous frame. */
665 nios2_get_return_address (int count)
667 if (count != 0)
668 return const0_rtx;
670 return get_hard_reg_initial_val (Pmode, RA_REGNO);
673 /* Emit code to change the current function's return address to
674 ADDRESS. SCRATCH is available as a scratch register, if needed.
675 ADDRESS and SCRATCH are both word-mode GPRs. */
676 void
677 nios2_set_return_address (rtx address, rtx scratch)
679 nios2_compute_frame_layout ();
680 if (cfun->machine->save_mask & (1 << RA_REGNO))
682 unsigned offset = cfun->machine->save_reg_size - 4;
683 rtx base;
685 if (frame_pointer_needed)
686 base = hard_frame_pointer_rtx;
687 else
689 base = stack_pointer_rtx;
690 offset += cfun->machine->save_regs_offset;
692 if (!SMALL_INT (offset))
694 emit_move_insn (scratch, gen_int_mode (offset, Pmode));
695 emit_insn (gen_add2_insn (scratch, base));
696 base = scratch;
697 offset = 0;
700 if (offset)
701 base = plus_constant (Pmode, base, offset);
702 emit_move_insn (gen_rtx_MEM (Pmode, base), address);
704 else
705 emit_move_insn (gen_rtx_REG (Pmode, RA_REGNO), address);
708 /* Implement FUNCTION_PROFILER macro. */
709 void
710 nios2_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
712 fprintf (file, "\tmov\tr8, ra\n");
713 if (flag_pic == 1)
715 fprintf (file, "\tnextpc\tr2\n");
716 fprintf (file, "\t1: movhi\tr3, %%hiadj(_gp_got - 1b)\n");
717 fprintf (file, "\taddi\tr3, r3, %%lo(_gp_got - 1b)\n");
718 fprintf (file, "\tadd\tr2, r2, r3\n");
719 fprintf (file, "\tldw\tr2, %%call(_mcount)(r2)\n");
720 fprintf (file, "\tcallr\tr2\n");
722 else if (flag_pic == 2)
724 fprintf (file, "\tnextpc\tr2\n");
725 fprintf (file, "\t1: movhi\tr3, %%hiadj(_gp_got - 1b)\n");
726 fprintf (file, "\taddi\tr3, r3, %%lo(_gp_got - 1b)\n");
727 fprintf (file, "\tadd\tr2, r2, r3\n");
728 fprintf (file, "\tmovhi\tr3, %%call_hiadj(_mcount)\n");
729 fprintf (file, "\taddi\tr3, r3, %%call_lo(_mcount)\n");
730 fprintf (file, "\tadd\tr3, r2, r3\n");
731 fprintf (file, "\tldw\tr2, 0(r3)\n");
732 fprintf (file, "\tcallr\tr2\n");
734 else
735 fprintf (file, "\tcall\t_mcount\n");
736 fprintf (file, "\tmov\tra, r8\n");
739 /* Dump stack layout. */
740 static void
741 nios2_dump_frame_layout (FILE *file)
743 fprintf (file, "\t%s Current Frame Info\n", ASM_COMMENT_START);
744 fprintf (file, "\t%s total_size = %d\n", ASM_COMMENT_START,
745 cfun->machine->total_size);
746 fprintf (file, "\t%s var_size = %d\n", ASM_COMMENT_START,
747 cfun->machine->var_size);
748 fprintf (file, "\t%s args_size = %d\n", ASM_COMMENT_START,
749 cfun->machine->args_size);
750 fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START,
751 cfun->machine->save_reg_size);
752 fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START,
753 cfun->machine->initialized);
754 fprintf (file, "\t%s save_regs_offset = %d\n", ASM_COMMENT_START,
755 cfun->machine->save_regs_offset);
756 fprintf (file, "\t%s is_leaf = %d\n", ASM_COMMENT_START,
757 crtl->is_leaf);
758 fprintf (file, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START,
759 frame_pointer_needed);
760 fprintf (file, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START,
761 crtl->args.pretend_args_size);
764 /* Return true if REGNO should be saved in the prologue. */
765 static bool
766 prologue_saved_reg_p (unsigned regno)
768 gcc_assert (GP_REG_P (regno));
770 if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
771 return true;
773 if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
774 return true;
776 if (regno == PIC_OFFSET_TABLE_REGNUM && crtl->uses_pic_offset_table)
777 return true;
779 if (regno == RA_REGNO && df_regs_ever_live_p (RA_REGNO))
780 return true;
782 return false;
785 /* Implement TARGET_CAN_ELIMINATE. */
786 static bool
787 nios2_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
789 if (to == STACK_POINTER_REGNUM)
790 return !frame_pointer_needed;
791 return true;
794 /* Implement INITIAL_ELIMINATION_OFFSET macro. */
796 nios2_initial_elimination_offset (int from, int to)
798 int offset;
800 nios2_compute_frame_layout ();
802 /* Set OFFSET to the offset from the stack pointer. */
803 switch (from)
805 case FRAME_POINTER_REGNUM:
806 offset = cfun->machine->args_size;
807 break;
809 case ARG_POINTER_REGNUM:
810 offset = cfun->machine->total_size;
811 offset -= crtl->args.pretend_args_size;
812 break;
814 default:
815 gcc_unreachable ();
818 /* If we are asked for the frame pointer offset, then adjust OFFSET
819 by the offset from the frame pointer to the stack pointer. */
820 if (to == HARD_FRAME_POINTER_REGNUM)
821 offset -= (cfun->machine->save_regs_offset
822 + cfun->machine->fp_save_offset);
824 return offset;
827 /* Return nonzero if this function is known to have a null epilogue.
828 This allows the optimizer to omit jumps to jumps if no stack
829 was created. */
831 nios2_can_use_return_insn (void)
833 if (!reload_completed || crtl->profile)
834 return 0;
836 return nios2_compute_frame_layout () == 0;
840 /* Check and signal some warnings/errors on FPU insn options. */
841 static void
842 nios2_custom_check_insns (void)
844 unsigned int i, j;
845 bool errors = false;
847 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
848 if (N2FPU_ENABLED_P (i) && N2FPU_DOUBLE_P (i))
850 for (j = 0; j < ARRAY_SIZE (nios2_fpu_insn); j++)
851 if (N2FPU_DOUBLE_REQUIRED_P (j) && ! N2FPU_ENABLED_P (j))
853 error ("switch %<-mcustom-%s%> is required for double "
854 "precision floating point", N2FPU_NAME (j));
855 errors = true;
857 break;
860 /* Warn if the user has certain exotic operations that won't get used
861 without -funsafe-math-optimizations. See expand_builtin () in
862 builtins.c. */
863 if (!flag_unsafe_math_optimizations)
864 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
865 if (N2FPU_ENABLED_P (i) && N2FPU_UNSAFE_P (i))
866 warning (0, "switch %<-mcustom-%s%> has no effect unless "
867 "-funsafe-math-optimizations is specified", N2FPU_NAME (i));
869 /* Warn if the user is trying to use -mcustom-fmins et. al, that won't
870 get used without -ffinite-math-only. See fold_builtin_fmin_fmax ()
871 in builtins.c. */
872 if (!flag_finite_math_only)
873 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
874 if (N2FPU_ENABLED_P (i) && N2FPU_FINITE_P (i))
875 warning (0, "switch %<-mcustom-%s%> has no effect unless "
876 "-ffinite-math-only is specified", N2FPU_NAME (i));
878 /* Warn if the user is trying to use a custom rounding instruction
879 that won't get used without -fno-math-errno. See
880 expand_builtin_int_roundingfn_2 () in builtins.c. */
881 if (flag_errno_math)
882 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
883 if (N2FPU_ENABLED_P (i) && N2FPU_NO_ERRNO_P (i))
884 warning (0, "switch %<-mcustom-%s%> has no effect unless "
885 "-fno-math-errno is specified", N2FPU_NAME (i));
887 if (errors || custom_code_conflict)
888 fatal_error ("conflicting use of -mcustom switches, target attributes, "
889 "and/or __builtin_custom_ functions");
892 static void
893 nios2_set_fpu_custom_code (enum n2fpu_code code, int n, bool override_p)
895 if (override_p || N2FPU_N (code) == -1)
896 N2FPU_N (code) = n;
897 nios2_register_custom_code (n, CCS_FPU, (int) code);
900 /* Type to represent a standard FPU config. */
901 struct nios2_fpu_config
903 const char *name;
904 bool set_sp_constants;
905 int code[n2fpu_code_num];
908 #define NIOS2_FPU_CONFIG_NUM 3
909 static struct nios2_fpu_config custom_fpu_config[NIOS2_FPU_CONFIG_NUM];
911 static void
912 nios2_init_fpu_configs (void)
914 struct nios2_fpu_config* cfg;
915 int i = 0;
916 #define NEXT_FPU_CONFIG \
917 do { \
918 cfg = &custom_fpu_config[i++]; \
919 memset (cfg, -1, sizeof (struct nios2_fpu_config));\
920 } while (0)
922 NEXT_FPU_CONFIG;
923 cfg->name = "60-1";
924 cfg->set_sp_constants = true;
925 cfg->code[n2fpu_fmuls] = 252;
926 cfg->code[n2fpu_fadds] = 253;
927 cfg->code[n2fpu_fsubs] = 254;
929 NEXT_FPU_CONFIG;
930 cfg->name = "60-2";
931 cfg->set_sp_constants = true;
932 cfg->code[n2fpu_fmuls] = 252;
933 cfg->code[n2fpu_fadds] = 253;
934 cfg->code[n2fpu_fsubs] = 254;
935 cfg->code[n2fpu_fdivs] = 255;
937 NEXT_FPU_CONFIG;
938 cfg->name = "72-3";
939 cfg->set_sp_constants = true;
940 cfg->code[n2fpu_floatus] = 243;
941 cfg->code[n2fpu_fixsi] = 244;
942 cfg->code[n2fpu_floatis] = 245;
943 cfg->code[n2fpu_fcmpgts] = 246;
944 cfg->code[n2fpu_fcmples] = 249;
945 cfg->code[n2fpu_fcmpeqs] = 250;
946 cfg->code[n2fpu_fcmpnes] = 251;
947 cfg->code[n2fpu_fmuls] = 252;
948 cfg->code[n2fpu_fadds] = 253;
949 cfg->code[n2fpu_fsubs] = 254;
950 cfg->code[n2fpu_fdivs] = 255;
952 #undef NEXT_FPU_CONFIG
953 gcc_assert (i == NIOS2_FPU_CONFIG_NUM);
956 static struct nios2_fpu_config *
957 nios2_match_custom_fpu_cfg (const char *cfgname, const char *endp)
959 int i;
960 for (i = 0; i < NIOS2_FPU_CONFIG_NUM; i++)
962 bool match = !(endp != NULL
963 ? strncmp (custom_fpu_config[i].name, cfgname,
964 endp - cfgname)
965 : strcmp (custom_fpu_config[i].name, cfgname));
966 if (match)
967 return &custom_fpu_config[i];
969 return NULL;
972 /* Use CFGNAME to lookup FPU config, ENDP if not NULL marks end of string.
973 OVERRIDE is true if loaded config codes should overwrite current state. */
974 static void
975 nios2_handle_custom_fpu_cfg (const char *cfgname, const char *endp,
976 bool override)
978 struct nios2_fpu_config *cfg = nios2_match_custom_fpu_cfg (cfgname, endp);
979 if (cfg)
981 unsigned int i;
982 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
983 if (cfg->code[i] >= 0)
984 nios2_set_fpu_custom_code ((enum n2fpu_code) i, cfg->code[i],
985 override);
986 if (cfg->set_sp_constants)
987 flag_single_precision_constant = 1;
989 else
990 warning (0, "ignoring unrecognized switch %<-mcustom-fpu-cfg%> "
991 "value %<%s%>", cfgname);
993 /* Guard against errors in the standard configurations. */
994 nios2_custom_check_insns ();
997 /* Check individual FPU insn options, and register custom code. */
998 static void
999 nios2_handle_custom_fpu_insn_option (int fpu_insn_index)
1001 int param = N2FPU_N (fpu_insn_index);
1003 if (0 <= param && param <= 255)
1004 nios2_register_custom_code (param, CCS_FPU, fpu_insn_index);
1006 /* Valid values are 0-255, but also allow -1 so that the
1007 -mno-custom-<opt> switches work. */
1008 else if (param != -1)
1009 error ("switch %<-mcustom-%s%> value %d must be between 0 and 255",
1010 N2FPU_NAME (fpu_insn_index), param);
1013 /* Allocate a chunk of memory for per-function machine-dependent data. */
1014 static struct machine_function *
1015 nios2_init_machine_status (void)
1017 return ggc_cleared_alloc<machine_function> ();
1020 /* Implement TARGET_OPTION_OVERRIDE. */
1021 static void
1022 nios2_option_override (void)
1024 unsigned int i;
1026 #ifdef SUBTARGET_OVERRIDE_OPTIONS
1027 SUBTARGET_OVERRIDE_OPTIONS;
1028 #endif
1030 /* Check for unsupported options. */
1031 if (flag_pic && !TARGET_LINUX_ABI)
1032 sorry ("position-independent code requires the Linux ABI");
1034 /* Function to allocate machine-dependent function status. */
1035 init_machine_status = &nios2_init_machine_status;
1037 nios2_section_threshold
1038 = (global_options_set.x_g_switch_value
1039 ? g_switch_value : NIOS2_DEFAULT_GVALUE);
1041 if (nios2_gpopt_option == gpopt_unspecified)
1043 /* Default to -mgpopt unless -fpic or -fPIC. */
1044 if (flag_pic)
1045 nios2_gpopt_option = gpopt_none;
1046 else
1047 nios2_gpopt_option = gpopt_local;
1050 /* If we don't have mul, we don't have mulx either! */
1051 if (!TARGET_HAS_MUL && TARGET_HAS_MULX)
1052 target_flags &= ~MASK_HAS_MULX;
1054 /* Initialize default FPU configurations. */
1055 nios2_init_fpu_configs ();
1057 /* Set up default handling for floating point custom instructions.
1059 Putting things in this order means that the -mcustom-fpu-cfg=
1060 switch will always be overridden by individual -mcustom-fadds=
1061 switches, regardless of the order in which they were specified
1062 on the command line.
1064 This behavior of prioritization of individual -mcustom-<insn>=
1065 options before the -mcustom-fpu-cfg= switch is maintained for
1066 compatibility. */
1067 if (nios2_custom_fpu_cfg_string && *nios2_custom_fpu_cfg_string)
1068 nios2_handle_custom_fpu_cfg (nios2_custom_fpu_cfg_string, NULL, false);
1070 /* Handle options for individual FPU insns. */
1071 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
1072 nios2_handle_custom_fpu_insn_option (i);
1074 nios2_custom_check_insns ();
1076 /* Save the initial options in case the user does function specific
1077 options. */
1078 target_option_default_node = target_option_current_node
1079 = build_target_option_node (&global_options);
1083 /* Return true if CST is a constant within range of movi/movui/movhi. */
1084 static bool
1085 nios2_simple_const_p (const_rtx cst)
1087 HOST_WIDE_INT val = INTVAL (cst);
1088 return SMALL_INT (val) || SMALL_INT_UNSIGNED (val) || UPPER16_INT (val);
1091 /* Compute a (partial) cost for rtx X. Return true if the complete
1092 cost has been computed, and false if subexpressions should be
1093 scanned. In either case, *TOTAL contains the cost result. */
1094 static bool
1095 nios2_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
1096 int opno ATTRIBUTE_UNUSED,
1097 int *total, bool speed ATTRIBUTE_UNUSED)
1099 switch (code)
1101 case CONST_INT:
1102 if (INTVAL (x) == 0)
1104 *total = COSTS_N_INSNS (0);
1105 return true;
1107 else if (nios2_simple_const_p (x))
1109 *total = COSTS_N_INSNS (2);
1110 return true;
1112 else
1114 *total = COSTS_N_INSNS (4);
1115 return true;
1118 case LABEL_REF:
1119 case SYMBOL_REF:
1120 case CONST:
1121 case CONST_DOUBLE:
1123 *total = COSTS_N_INSNS (4);
1124 return true;
1127 case AND:
1129 /* Recognize 'nor' insn pattern. */
1130 if (GET_CODE (XEXP (x, 0)) == NOT
1131 && GET_CODE (XEXP (x, 1)) == NOT)
1133 *total = COSTS_N_INSNS (1);
1134 return true;
1136 return false;
1139 case MULT:
1141 *total = COSTS_N_INSNS (1);
1142 return false;
1144 case SIGN_EXTEND:
1146 *total = COSTS_N_INSNS (3);
1147 return false;
1149 case ZERO_EXTEND:
1151 *total = COSTS_N_INSNS (1);
1152 return false;
1155 default:
1156 return false;
1160 /* Implement TARGET_PREFERRED_RELOAD_CLASS. */
1161 static reg_class_t
1162 nios2_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t regclass)
1164 return regclass == NO_REGS ? GENERAL_REGS : regclass;
1167 /* Emit a call to __tls_get_addr. TI is the argument to this function.
1168 RET is an RTX for the return value location. The entire insn sequence
1169 is returned. */
1170 static GTY(()) rtx nios2_tls_symbol;
1172 static rtx
1173 nios2_call_tls_get_addr (rtx ti)
1175 rtx arg = gen_rtx_REG (Pmode, FIRST_ARG_REGNO);
1176 rtx ret = gen_rtx_REG (Pmode, FIRST_RETVAL_REGNO);
1177 rtx fn, insn;
1179 if (!nios2_tls_symbol)
1180 nios2_tls_symbol = init_one_libfunc ("__tls_get_addr");
1182 emit_move_insn (arg, ti);
1183 fn = gen_rtx_MEM (QImode, nios2_tls_symbol);
1184 insn = emit_call_insn (gen_call_value (ret, fn, const0_rtx));
1185 RTL_CONST_CALL_P (insn) = 1;
1186 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), ret);
1187 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), arg);
1189 return ret;
1192 /* Return true for large offsets requiring hiadj/lo relocation pairs. */
1193 static bool
1194 nios2_large_offset_p (int unspec)
1196 gcc_assert (nios2_unspec_reloc_name (unspec) != NULL);
1198 if (flag_pic == 2
1199 /* FIXME: TLS GOT offset relocations will eventually also get this
1200 treatment, after binutils support for those are also completed. */
1201 && (unspec == UNSPEC_PIC_SYM || unspec == UNSPEC_PIC_CALL_SYM))
1202 return true;
1204 /* 'gotoff' offsets are always hiadj/lo. */
1205 if (unspec == UNSPEC_PIC_GOTOFF_SYM)
1206 return true;
1208 return false;
1211 /* Return true for conforming unspec relocations. Also used in
1212 constraints.md and predicates.md. */
1213 bool
1214 nios2_unspec_reloc_p (rtx op)
1216 return (GET_CODE (op) == CONST
1217 && GET_CODE (XEXP (op, 0)) == UNSPEC
1218 && ! nios2_large_offset_p (XINT (XEXP (op, 0), 1)));
1221 /* Helper to generate unspec constant. */
1222 static rtx
1223 nios2_unspec_offset (rtx loc, int unspec)
1225 return gen_rtx_CONST (Pmode, gen_rtx_UNSPEC (Pmode, gen_rtvec (1, loc),
1226 unspec));
1229 /* Generate GOT pointer based address with large offset. */
1230 static rtx
1231 nios2_large_got_address (rtx offset)
1233 rtx addr = gen_reg_rtx (Pmode);
1234 emit_insn (gen_add3_insn (addr, pic_offset_table_rtx,
1235 force_reg (Pmode, offset)));
1236 return addr;
1239 /* Generate a GOT pointer based address. */
1240 static rtx
1241 nios2_got_address (rtx loc, int unspec)
1243 rtx offset = nios2_unspec_offset (loc, unspec);
1244 crtl->uses_pic_offset_table = 1;
1246 if (nios2_large_offset_p (unspec))
1247 return nios2_large_got_address (offset);
1249 return gen_rtx_PLUS (Pmode, pic_offset_table_rtx, offset);
1252 /* Generate the code to access LOC, a thread local SYMBOL_REF. The
1253 return value will be a valid address and move_operand (either a REG
1254 or a LO_SUM). */
1255 static rtx
1256 nios2_legitimize_tls_address (rtx loc)
1258 rtx tmp, mem, tp;
1259 enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
1261 switch (model)
1263 case TLS_MODEL_GLOBAL_DYNAMIC:
1264 tmp = gen_reg_rtx (Pmode);
1265 emit_move_insn (tmp, nios2_got_address (loc, UNSPEC_ADD_TLS_GD));
1266 return nios2_call_tls_get_addr (tmp);
1268 case TLS_MODEL_LOCAL_DYNAMIC:
1269 tmp = gen_reg_rtx (Pmode);
1270 emit_move_insn (tmp, nios2_got_address (loc, UNSPEC_ADD_TLS_LDM));
1271 return gen_rtx_PLUS (Pmode, nios2_call_tls_get_addr (tmp),
1272 nios2_unspec_offset (loc, UNSPEC_ADD_TLS_LDO));
1274 case TLS_MODEL_INITIAL_EXEC:
1275 tmp = gen_reg_rtx (Pmode);
1276 mem = gen_const_mem (Pmode, nios2_got_address (loc, UNSPEC_LOAD_TLS_IE));
1277 emit_move_insn (tmp, mem);
1278 tp = gen_rtx_REG (Pmode, TP_REGNO);
1279 return gen_rtx_PLUS (Pmode, tp, tmp);
1281 case TLS_MODEL_LOCAL_EXEC:
1282 tp = gen_rtx_REG (Pmode, TP_REGNO);
1283 return gen_rtx_PLUS (Pmode, tp,
1284 nios2_unspec_offset (loc, UNSPEC_ADD_TLS_LE));
1285 default:
1286 gcc_unreachable ();
1290 /* Divide Support
1292 If -O3 is used, we want to output a table lookup for
1293 divides between small numbers (both num and den >= 0
1294 and < 0x10). The overhead of this method in the worst
1295 case is 40 bytes in the text section (10 insns) and
1296 256 bytes in the data section. Additional divides do
1297 not incur additional penalties in the data section.
1299 Code speed is improved for small divides by about 5x
1300 when using this method in the worse case (~9 cycles
1301 vs ~45). And in the worst case divides not within the
1302 table are penalized by about 10% (~5 cycles vs ~45).
1303 However in the typical case the penalty is not as bad
1304 because doing the long divide in only 45 cycles is
1305 quite optimistic.
1307 ??? would be nice to have some benchmarks other
1308 than Dhrystone to back this up.
1310 This bit of expansion is to create this instruction
1311 sequence as rtl.
1312 or $8, $4, $5
1313 slli $9, $4, 4
1314 cmpgeui $3, $8, 16
1315 beq $3, $0, .L3
1316 or $10, $9, $5
1317 add $12, $11, divide_table
1318 ldbu $2, 0($12)
1319 br .L1
1320 .L3:
1321 call slow_div
1322 .L1:
1323 # continue here with result in $2
1325 ??? Ideally I would like the libcall block to contain all
1326 of this code, but I don't know how to do that. What it
1327 means is that if the divide can be eliminated, it may not
1328 completely disappear.
1330 ??? The __divsi3_table label should ideally be moved out
1331 of this block and into a global. If it is placed into the
1332 sdata section we can save even more cycles by doing things
1333 gp relative. */
1334 void
1335 nios2_emit_expensive_div (rtx *operands, machine_mode mode)
1337 rtx or_result, shift_left_result;
1338 rtx lookup_value;
1339 rtx_code_label *lab1, *lab3;
1340 rtx insns;
1341 rtx libfunc;
1342 rtx final_result;
1343 rtx tmp;
1344 rtx table;
1346 /* It may look a little generic, but only SImode is supported for now. */
1347 gcc_assert (mode == SImode);
1348 libfunc = optab_libfunc (sdiv_optab, SImode);
1350 lab1 = gen_label_rtx ();
1351 lab3 = gen_label_rtx ();
1353 or_result = expand_simple_binop (SImode, IOR,
1354 operands[1], operands[2],
1355 0, 0, OPTAB_LIB_WIDEN);
1357 emit_cmp_and_jump_insns (or_result, GEN_INT (15), GTU, 0,
1358 GET_MODE (or_result), 0, lab3);
1359 JUMP_LABEL (get_last_insn ()) = lab3;
1361 shift_left_result = expand_simple_binop (SImode, ASHIFT,
1362 operands[1], GEN_INT (4),
1363 0, 0, OPTAB_LIB_WIDEN);
1365 lookup_value = expand_simple_binop (SImode, IOR,
1366 shift_left_result, operands[2],
1367 0, 0, OPTAB_LIB_WIDEN);
1368 table = gen_rtx_PLUS (SImode, lookup_value,
1369 gen_rtx_SYMBOL_REF (SImode, "__divsi3_table"));
1370 convert_move (operands[0], gen_rtx_MEM (QImode, table), 1);
1372 tmp = emit_jump_insn (gen_jump (lab1));
1373 JUMP_LABEL (tmp) = lab1;
1374 emit_barrier ();
1376 emit_label (lab3);
1377 LABEL_NUSES (lab3) = 1;
1379 start_sequence ();
1380 final_result = emit_library_call_value (libfunc, NULL_RTX,
1381 LCT_CONST, SImode, 2,
1382 operands[1], SImode,
1383 operands[2], SImode);
1385 insns = get_insns ();
1386 end_sequence ();
1387 emit_libcall_block (insns, operands[0], final_result,
1388 gen_rtx_DIV (SImode, operands[1], operands[2]));
1390 emit_label (lab1);
1391 LABEL_NUSES (lab1) = 1;
1395 /* Branches and compares. */
1397 /* Return in *ALT_CODE and *ALT_OP, an alternate equivalent constant
1398 comparison, e.g. >= 1 into > 0. */
1399 static void
1400 nios2_alternate_compare_const (enum rtx_code code, rtx op,
1401 enum rtx_code *alt_code, rtx *alt_op,
1402 machine_mode mode)
1404 HOST_WIDE_INT opval = INTVAL (op);
1405 enum rtx_code scode = signed_condition (code);
1406 bool dec_p = (scode == LT || scode == GE);
1408 if (code == EQ || code == NE)
1410 *alt_code = code;
1411 *alt_op = op;
1412 return;
1415 *alt_op = (dec_p
1416 ? gen_int_mode (opval - 1, mode)
1417 : gen_int_mode (opval + 1, mode));
1419 /* The required conversion between [>,>=] and [<,<=] is captured
1420 by a reverse + swap of condition codes. */
1421 *alt_code = reverse_condition (swap_condition (code));
1424 /* Test if the incremented/decremented value crosses the over/underflow
1425 boundary. Supposedly, such boundary cases should already be transformed
1426 into always-true/false or EQ conditions, so use an assertion here. */
1427 unsigned HOST_WIDE_INT alt_opval = INTVAL (*alt_op);
1428 if (code == scode)
1429 alt_opval ^= (1 << (GET_MODE_BITSIZE (mode) - 1));
1430 alt_opval &= GET_MODE_MASK (mode);
1431 gcc_assert (dec_p ? alt_opval != GET_MODE_MASK (mode) : alt_opval != 0);
1435 /* Return true if the constant comparison is supported by nios2. */
1436 static bool
1437 nios2_valid_compare_const_p (enum rtx_code code, rtx op)
1439 switch (code)
1441 case EQ: case NE: case GE: case LT:
1442 return SMALL_INT (INTVAL (op));
1443 case GEU: case LTU:
1444 return SMALL_INT_UNSIGNED (INTVAL (op));
1445 default:
1446 return false;
1450 /* Checks if the FPU comparison in *CMP, *OP1, and *OP2 can be supported in
1451 the current configuration. Perform modifications if MODIFY_P is true.
1452 Returns true if FPU compare can be done. */
1454 bool
1455 nios2_validate_fpu_compare (machine_mode mode, rtx *cmp, rtx *op1, rtx *op2,
1456 bool modify_p)
1458 bool rev_p = false;
1459 enum rtx_code code = GET_CODE (*cmp);
1461 if (!nios2_fpu_compare_enabled (code, mode))
1463 code = swap_condition (code);
1464 if (nios2_fpu_compare_enabled (code, mode))
1465 rev_p = true;
1466 else
1467 return false;
1470 if (modify_p)
1472 if (rev_p)
1474 rtx tmp = *op1;
1475 *op1 = *op2;
1476 *op2 = tmp;
1478 *op1 = force_reg (mode, *op1);
1479 *op2 = force_reg (mode, *op2);
1480 *cmp = gen_rtx_fmt_ee (code, mode, *op1, *op2);
1482 return true;
1485 /* Checks and modifies the comparison in *CMP, *OP1, and *OP2 into valid
1486 nios2 supported form. Returns true if success. */
1487 bool
1488 nios2_validate_compare (machine_mode mode, rtx *cmp, rtx *op1, rtx *op2)
1490 enum rtx_code code = GET_CODE (*cmp);
1491 enum rtx_code alt_code;
1492 rtx alt_op2;
1494 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
1495 return nios2_validate_fpu_compare (mode, cmp, op1, op2, true);
1497 if (!reg_or_0_operand (*op2, mode))
1499 /* Create alternate constant compare. */
1500 nios2_alternate_compare_const (code, *op2, &alt_code, &alt_op2, mode);
1502 /* If alterate op2 is zero(0), we can use it directly, possibly
1503 swapping the compare code. */
1504 if (alt_op2 == const0_rtx)
1506 code = alt_code;
1507 *op2 = alt_op2;
1508 goto check_rebuild_cmp;
1511 /* Check if either constant compare can be used. */
1512 if (nios2_valid_compare_const_p (code, *op2))
1513 return true;
1514 else if (nios2_valid_compare_const_p (alt_code, alt_op2))
1516 code = alt_code;
1517 *op2 = alt_op2;
1518 goto rebuild_cmp;
1521 /* We have to force op2 into a register now. Try to pick one
1522 with a lower cost. */
1523 if (! nios2_simple_const_p (*op2)
1524 && nios2_simple_const_p (alt_op2))
1526 code = alt_code;
1527 *op2 = alt_op2;
1529 *op2 = force_reg (SImode, *op2);
1531 check_rebuild_cmp:
1532 if (code == GT || code == GTU || code == LE || code == LEU)
1534 rtx t = *op1; *op1 = *op2; *op2 = t;
1535 code = swap_condition (code);
1537 rebuild_cmp:
1538 *cmp = gen_rtx_fmt_ee (code, mode, *op1, *op2);
1539 return true;
1543 /* Addressing Modes. */
1545 /* Implement TARGET_LEGITIMATE_CONSTANT_P. */
1546 static bool
1547 nios2_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1549 rtx base, offset;
1550 split_const (x, &base, &offset);
1551 return GET_CODE (base) != SYMBOL_REF || !SYMBOL_REF_TLS_MODEL (base);
1554 /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
1555 static bool
1556 nios2_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1558 return nios2_legitimate_constant_p (mode, x) == false;
1561 /* Return true if register REGNO is a valid base register.
1562 STRICT_P is true if REG_OK_STRICT is in effect. */
1564 bool
1565 nios2_regno_ok_for_base_p (int regno, bool strict_p)
1567 if (!HARD_REGISTER_NUM_P (regno))
1569 if (!strict_p)
1570 return true;
1572 if (!reg_renumber)
1573 return false;
1575 regno = reg_renumber[regno];
1578 /* The fake registers will be eliminated to either the stack or
1579 hard frame pointer, both of which are usually valid base registers.
1580 Reload deals with the cases where the eliminated form isn't valid. */
1581 return (GP_REG_P (regno)
1582 || regno == FRAME_POINTER_REGNUM
1583 || regno == ARG_POINTER_REGNUM);
1586 /* Return true if the address expression formed by BASE + OFFSET is
1587 valid. */
1588 static bool
1589 nios2_valid_addr_expr_p (rtx base, rtx offset, bool strict_p)
1591 if (!strict_p && GET_CODE (base) == SUBREG)
1592 base = SUBREG_REG (base);
1593 return (REG_P (base)
1594 && nios2_regno_ok_for_base_p (REGNO (base), strict_p)
1595 && (offset == NULL_RTX
1596 || const_arith_operand (offset, Pmode)
1597 || nios2_unspec_reloc_p (offset)));
1600 /* Implement TARGET_LEGITIMATE_ADDRESS_P. */
1601 static bool
1602 nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
1603 rtx operand, bool strict_p)
1605 switch (GET_CODE (operand))
1607 /* Direct. */
1608 case SYMBOL_REF:
1609 if (SYMBOL_REF_TLS_MODEL (operand))
1610 return false;
1612 if (nios2_symbol_ref_in_small_data_p (operand))
1613 return true;
1615 /* Else, fall through. */
1616 case LABEL_REF:
1617 case CONST_INT:
1618 case CONST:
1619 case CONST_DOUBLE:
1620 return false;
1622 /* Register indirect. */
1623 case REG:
1624 return nios2_regno_ok_for_base_p (REGNO (operand), strict_p);
1626 /* Register indirect with displacement. */
1627 case PLUS:
1629 rtx op0 = XEXP (operand, 0);
1630 rtx op1 = XEXP (operand, 1);
1632 return (nios2_valid_addr_expr_p (op0, op1, strict_p)
1633 || nios2_valid_addr_expr_p (op1, op0, strict_p));
1636 default:
1637 break;
1639 return false;
1642 /* Return true if SECTION is a small section name. */
1643 static bool
1644 nios2_small_section_name_p (const char *section)
1646 return (strcmp (section, ".sbss") == 0
1647 || strncmp (section, ".sbss.", 6) == 0
1648 || strcmp (section, ".sdata") == 0
1649 || strncmp (section, ".sdata.", 7) == 0);
1652 /* Return true if EXP should be placed in the small data section. */
1653 static bool
1654 nios2_in_small_data_p (const_tree exp)
1656 /* We want to merge strings, so we never consider them small data. */
1657 if (TREE_CODE (exp) == STRING_CST)
1658 return false;
1660 if (TREE_CODE (exp) == VAR_DECL)
1662 if (DECL_SECTION_NAME (exp))
1664 const char *section = DECL_SECTION_NAME (exp);
1665 if (nios2_small_section_name_p (section))
1666 return true;
1668 else
1670 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
1672 /* If this is an incomplete type with size 0, then we can't put it
1673 in sdata because it might be too big when completed. */
1674 if (size > 0
1675 && (unsigned HOST_WIDE_INT) size <= nios2_section_threshold)
1676 return true;
1680 return false;
1683 /* Return true if symbol is in small data section. */
1685 bool
1686 nios2_symbol_ref_in_small_data_p (rtx sym)
1688 tree decl;
1690 gcc_assert (GET_CODE (sym) == SYMBOL_REF);
1691 decl = SYMBOL_REF_DECL (sym);
1693 /* TLS variables are not accessed through the GP. */
1694 if (SYMBOL_REF_TLS_MODEL (sym) != 0)
1695 return false;
1697 /* If the user has explicitly placed the symbol in a small data section
1698 via an attribute, generate gp-relative addressing even if the symbol
1699 is external, weak, or larger than we'd automatically put in the
1700 small data section. OTOH, if the symbol is located in some
1701 non-small-data section, we can't use gp-relative accesses on it
1702 unless the user has requested gpopt_data or gpopt_all. */
1704 switch (nios2_gpopt_option)
1706 case gpopt_none:
1707 /* Don't generate a gp-relative addressing mode if that's been
1708 disabled. */
1709 return false;
1711 case gpopt_local:
1712 /* Use GP-relative addressing for small data symbols that are
1713 not external or weak, plus any symbols that have explicitly
1714 been placed in a small data section. */
1715 if (decl && DECL_SECTION_NAME (decl))
1716 return nios2_small_section_name_p (DECL_SECTION_NAME (decl));
1717 return (SYMBOL_REF_SMALL_P (sym)
1718 && !SYMBOL_REF_EXTERNAL_P (sym)
1719 && !(decl && DECL_WEAK (decl)));
1721 case gpopt_global:
1722 /* Use GP-relative addressing for small data symbols, even if
1723 they are external or weak. Note that SYMBOL_REF_SMALL_P
1724 is also true of symbols that have explicitly been placed
1725 in a small data section. */
1726 return SYMBOL_REF_SMALL_P (sym);
1728 case gpopt_data:
1729 /* Use GP-relative addressing for all data symbols regardless
1730 of the object size, but not for code symbols. This option
1731 is equivalent to the user asserting that the entire data
1732 section is accessible from the GP. */
1733 return !SYMBOL_REF_FUNCTION_P (sym);
1735 case gpopt_all:
1736 /* Use GP-relative addressing for everything, including code.
1737 Effectively, the user has asserted that the entire program
1738 fits within the 64K range of the GP offset. */
1739 return true;
1741 default:
1742 /* We shouldn't get here. */
1743 return false;
1747 /* Implement TARGET_SECTION_TYPE_FLAGS. */
1749 static unsigned int
1750 nios2_section_type_flags (tree decl, const char *name, int reloc)
1752 unsigned int flags;
1754 flags = default_section_type_flags (decl, name, reloc);
1756 if (nios2_small_section_name_p (name))
1757 flags |= SECTION_SMALL;
1759 return flags;
1762 /* Return true if SYMBOL_REF X binds locally. */
1764 static bool
1765 nios2_symbol_binds_local_p (const_rtx x)
1767 return (SYMBOL_REF_DECL (x)
1768 ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
1769 : SYMBOL_REF_LOCAL_P (x));
1772 /* Position independent code related. */
1774 /* Emit code to load the PIC register. */
1775 static void
1776 nios2_load_pic_register (void)
1778 rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
1780 emit_insn (gen_load_got_register (pic_offset_table_rtx, tmp));
1781 emit_insn (gen_add3_insn (pic_offset_table_rtx, pic_offset_table_rtx, tmp));
1784 /* Generate a PIC address as a MEM rtx. */
1785 static rtx
1786 nios2_load_pic_address (rtx sym, int unspec)
1788 if (flag_pic == 2
1789 && GET_CODE (sym) == SYMBOL_REF
1790 && nios2_symbol_binds_local_p (sym))
1791 /* Under -fPIC, generate a GOTOFF address for local symbols. */
1792 return nios2_got_address (sym, UNSPEC_PIC_GOTOFF_SYM);
1794 return gen_const_mem (Pmode, nios2_got_address (sym, unspec));
1797 /* Nonzero if the constant value X is a legitimate general operand
1798 when generating PIC code. It is given that flag_pic is on and
1799 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
1800 bool
1801 nios2_legitimate_pic_operand_p (rtx x)
1803 if (GET_CODE (x) == CONST
1804 && GET_CODE (XEXP (x, 0)) == UNSPEC
1805 && nios2_large_offset_p (XINT (XEXP (x, 0), 1)))
1806 return true;
1808 return ! (GET_CODE (x) == SYMBOL_REF
1809 || GET_CODE (x) == LABEL_REF || GET_CODE (x) == CONST);
1812 /* Return TRUE if X is a thread-local symbol. */
1813 static bool
1814 nios2_tls_symbol_p (rtx x)
1816 return (targetm.have_tls && GET_CODE (x) == SYMBOL_REF
1817 && SYMBOL_REF_TLS_MODEL (x) != 0);
1820 /* Legitimize addresses that are CONSTANT_P expressions. */
1821 static rtx
1822 nios2_legitimize_constant_address (rtx addr)
1824 rtx base, offset;
1825 split_const (addr, &base, &offset);
1827 if (nios2_tls_symbol_p (base))
1828 base = nios2_legitimize_tls_address (base);
1829 else if (flag_pic)
1830 base = nios2_load_pic_address (base, UNSPEC_PIC_SYM);
1831 else
1832 return addr;
1834 if (offset != const0_rtx)
1836 gcc_assert (can_create_pseudo_p ());
1837 return gen_rtx_PLUS (Pmode, force_reg (Pmode, base),
1838 (CONST_INT_P (offset)
1839 ? (SMALL_INT (INTVAL (offset))
1840 ? offset : force_reg (Pmode, offset))
1841 : offset));
1843 return base;
1846 /* Implement TARGET_LEGITIMIZE_ADDRESS. */
1847 static rtx
1848 nios2_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
1849 machine_mode mode ATTRIBUTE_UNUSED)
1851 if (CONSTANT_P (x))
1852 return nios2_legitimize_constant_address (x);
1854 /* For the TLS LE (Local Exec) model, the compiler may try to
1855 combine constant offsets with unspec relocs, creating address RTXs
1856 looking like this:
1857 (plus:SI (reg:SI 23 r23)
1858 (const:SI
1859 (plus:SI
1860 (unspec:SI [(symbol_ref:SI ("var"))] UNSPEC_ADD_TLS_LE)
1861 (const_int 48 [0x30]))))
1863 This usually happens when 'var' is a thread-local struct variable,
1864 and access of a field in var causes the addend.
1866 We typically want this combining, so transform the above into this
1867 form, which is allowed:
1868 (plus:SI (reg:SI 23 r23)
1869 (const:SI
1870 (unspec:SI
1871 [(const:SI
1872 (plus:SI (symbol_ref:SI ("var"))
1873 (const_int 48 [0x30])))] UNSPEC_ADD_TLS_LE)))
1875 Which will be output as '%tls_le(var+48)(r23)' in assembly. */
1876 if (GET_CODE (x) == PLUS
1877 && GET_CODE (XEXP (x, 0)) == REG
1878 && GET_CODE (XEXP (x, 1)) == CONST)
1880 rtx unspec, offset, reg = XEXP (x, 0);
1881 split_const (XEXP (x, 1), &unspec, &offset);
1882 if (GET_CODE (unspec) == UNSPEC
1883 && !nios2_large_offset_p (XINT (unspec, 1))
1884 && offset != const0_rtx)
1886 unspec = copy_rtx (unspec);
1887 XVECEXP (unspec, 0, 0)
1888 = plus_constant (Pmode, XVECEXP (unspec, 0, 0), INTVAL (offset));
1889 x = gen_rtx_PLUS (Pmode, reg, gen_rtx_CONST (Pmode, unspec));
1893 return x;
1896 static rtx
1897 nios2_delegitimize_address (rtx x)
1899 x = delegitimize_mem_from_attrs (x);
1901 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC)
1903 switch (XINT (XEXP (x, 0), 1))
1905 case UNSPEC_PIC_SYM:
1906 case UNSPEC_PIC_CALL_SYM:
1907 case UNSPEC_PIC_GOTOFF_SYM:
1908 case UNSPEC_ADD_TLS_GD:
1909 case UNSPEC_ADD_TLS_LDM:
1910 case UNSPEC_LOAD_TLS_IE:
1911 case UNSPEC_ADD_TLS_LE:
1912 x = XVECEXP (XEXP (x, 0), 0, 0);
1913 gcc_assert (GET_CODE (x) == SYMBOL_REF);
1914 break;
1917 return x;
1920 /* Main expander function for RTL moves. */
1922 nios2_emit_move_sequence (rtx *operands, machine_mode mode)
1924 rtx to = operands[0];
1925 rtx from = operands[1];
1927 if (!register_operand (to, mode) && !reg_or_0_operand (from, mode))
1929 gcc_assert (can_create_pseudo_p ());
1930 from = copy_to_mode_reg (mode, from);
1933 if (GET_CODE (from) == SYMBOL_REF || GET_CODE (from) == LABEL_REF
1934 || (GET_CODE (from) == CONST
1935 && GET_CODE (XEXP (from, 0)) != UNSPEC))
1936 from = nios2_legitimize_constant_address (from);
1938 operands[0] = to;
1939 operands[1] = from;
1940 return 0;
1943 /* The function with address *ADDR is being called. If the address
1944 needs to be loaded from the GOT, emit the instruction to do so and
1945 update *ADDR to point to the rtx for the loaded value. */
1946 void
1947 nios2_adjust_call_address (rtx *call_op)
1949 rtx addr;
1950 gcc_assert (MEM_P (*call_op));
1951 addr = XEXP (*call_op, 0);
1952 if (flag_pic && CONSTANT_P (addr))
1954 rtx reg = gen_reg_rtx (Pmode);
1955 emit_move_insn (reg, nios2_load_pic_address (addr, UNSPEC_PIC_CALL_SYM));
1956 XEXP (*call_op, 0) = reg;
1961 /* Output assembly language related definitions. */
1963 /* Print the operand OP to file stream FILE modified by LETTER.
1964 LETTER can be one of:
1966 i: print "i" if OP is an immediate, except 0
1967 o: print "io" if OP is volatile
1968 z: for const0_rtx print $0 instead of 0
1969 H: for %hiadj
1970 L: for %lo
1971 U: for upper half of 32 bit value
1972 D: for the upper 32-bits of a 64-bit double value
1973 R: prints reverse condition.
1975 static void
1976 nios2_print_operand (FILE *file, rtx op, int letter)
1979 switch (letter)
1981 case 'i':
1982 if (CONSTANT_P (op) && op != const0_rtx)
1983 fprintf (file, "i");
1984 return;
1986 case 'o':
1987 if (GET_CODE (op) == MEM
1988 && ((MEM_VOLATILE_P (op) && TARGET_BYPASS_CACHE_VOLATILE)
1989 || TARGET_BYPASS_CACHE))
1990 fprintf (file, "io");
1991 return;
1993 default:
1994 break;
1997 if (comparison_operator (op, VOIDmode))
1999 enum rtx_code cond = GET_CODE (op);
2000 if (letter == 0)
2002 fprintf (file, "%s", GET_RTX_NAME (cond));
2003 return;
2005 if (letter == 'R')
2007 fprintf (file, "%s", GET_RTX_NAME (reverse_condition (cond)));
2008 return;
2012 switch (GET_CODE (op))
2014 case REG:
2015 if (letter == 0 || letter == 'z')
2017 fprintf (file, "%s", reg_names[REGNO (op)]);
2018 return;
2020 else if (letter == 'D')
2022 fprintf (file, "%s", reg_names[REGNO (op)+1]);
2023 return;
2025 break;
2027 case CONST_INT:
2028 if (INTVAL (op) == 0 && letter == 'z')
2030 fprintf (file, "zero");
2031 return;
2034 if (letter == 'U')
2036 HOST_WIDE_INT val = INTVAL (op);
2037 val = (val >> 16) & 0xFFFF;
2038 output_addr_const (file, gen_int_mode (val, SImode));
2039 return;
2041 /* Else, fall through. */
2043 case CONST:
2044 case LABEL_REF:
2045 case SYMBOL_REF:
2046 case CONST_DOUBLE:
2047 if (letter == 0 || letter == 'z')
2049 output_addr_const (file, op);
2050 return;
2052 else if (letter == 'H' || letter == 'L')
2054 fprintf (file, "%%");
2055 if (GET_CODE (op) == CONST
2056 && GET_CODE (XEXP (op, 0)) == UNSPEC)
2058 rtx unspec = XEXP (op, 0);
2059 int unspec_reloc = XINT (unspec, 1);
2060 gcc_assert (nios2_large_offset_p (unspec_reloc));
2061 fprintf (file, "%s_", nios2_unspec_reloc_name (unspec_reloc));
2062 op = XVECEXP (unspec, 0, 0);
2064 fprintf (file, letter == 'H' ? "hiadj(" : "lo(");
2065 output_addr_const (file, op);
2066 fprintf (file, ")");
2067 return;
2069 break;
2071 case SUBREG:
2072 case MEM:
2073 if (letter == 0)
2075 output_address (op);
2076 return;
2078 break;
2080 case CODE_LABEL:
2081 if (letter == 0)
2083 output_addr_const (file, op);
2084 return;
2086 break;
2088 default:
2089 break;
2092 output_operand_lossage ("Unsupported operand for code '%c'", letter);
2093 gcc_unreachable ();
2096 /* Return true if this is a GP-relative accessible reference. */
2097 static bool
2098 gprel_constant_p (rtx op)
2100 if (GET_CODE (op) == SYMBOL_REF
2101 && nios2_symbol_ref_in_small_data_p (op))
2102 return true;
2103 else if (GET_CODE (op) == CONST
2104 && GET_CODE (XEXP (op, 0)) == PLUS)
2105 return gprel_constant_p (XEXP (XEXP (op, 0), 0));
2107 return false;
2110 /* Return the name string for a supported unspec reloc offset. */
2111 static const char *
2112 nios2_unspec_reloc_name (int unspec)
2114 switch (unspec)
2116 case UNSPEC_PIC_SYM:
2117 return "got";
2118 case UNSPEC_PIC_CALL_SYM:
2119 return "call";
2120 case UNSPEC_PIC_GOTOFF_SYM:
2121 return "gotoff";
2122 case UNSPEC_LOAD_TLS_IE:
2123 return "tls_ie";
2124 case UNSPEC_ADD_TLS_LE:
2125 return "tls_le";
2126 case UNSPEC_ADD_TLS_GD:
2127 return "tls_gd";
2128 case UNSPEC_ADD_TLS_LDM:
2129 return "tls_ldm";
2130 case UNSPEC_ADD_TLS_LDO:
2131 return "tls_ldo";
2132 default:
2133 return NULL;
2137 /* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */
2138 static bool
2139 nios2_output_addr_const_extra (FILE *file, rtx op)
2141 const char *name;
2142 gcc_assert (GET_CODE (op) == UNSPEC);
2144 /* Support for printing out const unspec relocations. */
2145 name = nios2_unspec_reloc_name (XINT (op, 1));
2146 if (name)
2148 fprintf (file, "%%%s(", name);
2149 output_addr_const (file, XVECEXP (op, 0, 0));
2150 fprintf (file, ")");
2151 return true;
2153 return false;
2156 /* Implement TARGET_PRINT_OPERAND_ADDRESS. */
2157 static void
2158 nios2_print_operand_address (FILE *file, rtx op)
2160 switch (GET_CODE (op))
2162 case CONST:
2163 case CONST_INT:
2164 case LABEL_REF:
2165 case CONST_DOUBLE:
2166 case SYMBOL_REF:
2167 if (gprel_constant_p (op))
2169 fprintf (file, "%%gprel(");
2170 output_addr_const (file, op);
2171 fprintf (file, ")(%s)", reg_names[GP_REGNO]);
2172 return;
2175 break;
2177 case PLUS:
2179 rtx op0 = XEXP (op, 0);
2180 rtx op1 = XEXP (op, 1);
2182 if (REG_P (op0) && CONSTANT_P (op1))
2184 output_addr_const (file, op1);
2185 fprintf (file, "(%s)", reg_names[REGNO (op0)]);
2186 return;
2188 else if (REG_P (op1) && CONSTANT_P (op0))
2190 output_addr_const (file, op0);
2191 fprintf (file, "(%s)", reg_names[REGNO (op1)]);
2192 return;
2195 break;
2197 case REG:
2198 fprintf (file, "0(%s)", reg_names[REGNO (op)]);
2199 return;
2201 case MEM:
2203 rtx base = XEXP (op, 0);
2204 nios2_print_operand_address (file, base);
2205 return;
2207 default:
2208 break;
2211 fprintf (stderr, "Missing way to print address\n");
2212 debug_rtx (op);
2213 gcc_unreachable ();
2216 /* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL. */
2217 static void
2218 nios2_output_dwarf_dtprel (FILE *file, int size, rtx x)
2220 gcc_assert (size == 4);
2221 fprintf (file, "\t.4byte\t%%tls_ldo(");
2222 output_addr_const (file, x);
2223 fprintf (file, ")");
2226 /* Implement TARGET_ASM_FUNCTION_PROLOGUE. */
2227 static void
2228 nios2_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
2230 if (flag_verbose_asm || flag_debug_asm)
2232 nios2_compute_frame_layout ();
2233 nios2_dump_frame_layout (file);
2237 /* Emit assembly of custom FPU instructions. */
2238 const char *
2239 nios2_fpu_insn_asm (enum n2fpu_code code)
2241 static char buf[256];
2242 const char *op1, *op2, *op3;
2243 int ln = 256, n = 0;
2245 int N = N2FPU_N (code);
2246 int num_operands = N2FPU (code).num_operands;
2247 const char *insn_name = N2FPU_NAME (code);
2248 tree ftype = nios2_ftype (N2FPU_FTCODE (code));
2249 machine_mode dst_mode = TYPE_MODE (TREE_TYPE (ftype));
2250 machine_mode src_mode = TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (ftype)));
2252 /* Prepare X register for DF input operands. */
2253 if (GET_MODE_SIZE (src_mode) == 8 && num_operands == 3)
2254 n = snprintf (buf, ln, "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t",
2255 N2FPU_N (n2fpu_fwrx));
2257 if (src_mode == SFmode)
2259 if (dst_mode == VOIDmode)
2261 /* The fwry case. */
2262 op1 = op3 = "zero";
2263 op2 = "%0";
2264 num_operands -= 1;
2266 else
2268 op1 = (dst_mode == DFmode ? "%D0" : "%0");
2269 op2 = "%1";
2270 op3 = (num_operands == 2 ? "zero" : "%2");
2273 else if (src_mode == DFmode)
2275 if (dst_mode == VOIDmode)
2277 /* The fwrx case. */
2278 op1 = "zero";
2279 op2 = "%0";
2280 op3 = "%D0";
2281 num_operands -= 1;
2283 else
2285 op1 = (dst_mode == DFmode ? "%D0" : "%0");
2286 op2 = (num_operands == 2 ? "%1" : "%2");
2287 op3 = (num_operands == 2 ? "%D1" : "%D2");
2290 else if (src_mode == VOIDmode)
2292 /* frdxlo, frdxhi, frdy cases. */
2293 gcc_assert (dst_mode == SFmode);
2294 op1 = "%0";
2295 op2 = op3 = "zero";
2297 else if (src_mode == SImode)
2299 /* Conversion operators. */
2300 gcc_assert (num_operands == 2);
2301 op1 = (dst_mode == DFmode ? "%D0" : "%0");
2302 op2 = "%1";
2303 op3 = "zero";
2305 else
2306 gcc_unreachable ();
2308 /* Main instruction string. */
2309 n += snprintf (buf + n, ln - n, "custom\t%d, %s, %s, %s # %s %%0%s%s",
2310 N, op1, op2, op3, insn_name,
2311 (num_operands >= 2 ? ", %1" : ""),
2312 (num_operands == 3 ? ", %2" : ""));
2314 /* Extraction of Y register for DF results. */
2315 if (dst_mode == DFmode)
2316 snprintf (buf + n, ln - n, "\n\tcustom\t%d, %%0, zero, zero # frdy %%0",
2317 N2FPU_N (n2fpu_frdy));
2318 return buf;
2323 /* Function argument related. */
2325 /* Define where to put the arguments to a function. Value is zero to
2326 push the argument on the stack, or a hard register in which to
2327 store the argument.
2329 MODE is the argument's machine mode.
2330 TYPE is the data type of the argument (as a tree).
2331 This is null for libcalls where that information may
2332 not be available.
2333 CUM is a variable of type CUMULATIVE_ARGS which gives info about
2334 the preceding args and about the function being called.
2335 NAMED is nonzero if this argument is a named parameter
2336 (otherwise it is an extra parameter matching an ellipsis). */
2338 static rtx
2339 nios2_function_arg (cumulative_args_t cum_v, machine_mode mode,
2340 const_tree type ATTRIBUTE_UNUSED,
2341 bool named ATTRIBUTE_UNUSED)
2343 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2344 rtx return_rtx = NULL_RTX;
2346 if (cum->regs_used < NUM_ARG_REGS)
2347 return_rtx = gen_rtx_REG (mode, FIRST_ARG_REGNO + cum->regs_used);
2349 return return_rtx;
2352 /* Return number of bytes, at the beginning of the argument, that must be
2353 put in registers. 0 is the argument is entirely in registers or entirely
2354 in memory. */
2356 static int
2357 nios2_arg_partial_bytes (cumulative_args_t cum_v,
2358 machine_mode mode, tree type ATTRIBUTE_UNUSED,
2359 bool named ATTRIBUTE_UNUSED)
2361 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2362 HOST_WIDE_INT param_size;
2364 if (mode == BLKmode)
2366 param_size = int_size_in_bytes (type);
2367 gcc_assert (param_size >= 0);
2369 else
2370 param_size = GET_MODE_SIZE (mode);
2372 /* Convert to words (round up). */
2373 param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
2375 if (cum->regs_used < NUM_ARG_REGS
2376 && cum->regs_used + param_size > NUM_ARG_REGS)
2377 return (NUM_ARG_REGS - cum->regs_used) * UNITS_PER_WORD;
2379 return 0;
2382 /* Update the data in CUM to advance over an argument of mode MODE
2383 and data type TYPE; TYPE is null for libcalls where that information
2384 may not be available. */
2386 static void
2387 nios2_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
2388 const_tree type ATTRIBUTE_UNUSED,
2389 bool named ATTRIBUTE_UNUSED)
2391 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2392 HOST_WIDE_INT param_size;
2394 if (mode == BLKmode)
2396 param_size = int_size_in_bytes (type);
2397 gcc_assert (param_size >= 0);
2399 else
2400 param_size = GET_MODE_SIZE (mode);
2402 /* Convert to words (round up). */
2403 param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
2405 if (cum->regs_used + param_size > NUM_ARG_REGS)
2406 cum->regs_used = NUM_ARG_REGS;
2407 else
2408 cum->regs_used += param_size;
2411 enum direction
2412 nios2_function_arg_padding (machine_mode mode, const_tree type)
2414 /* On little-endian targets, the first byte of every stack argument
2415 is passed in the first byte of the stack slot. */
2416 if (!BYTES_BIG_ENDIAN)
2417 return upward;
2419 /* Otherwise, integral types are padded downward: the last byte of a
2420 stack argument is passed in the last byte of the stack slot. */
2421 if (type != 0
2422 ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
2423 : GET_MODE_CLASS (mode) == MODE_INT)
2424 return downward;
2426 /* Arguments smaller than a stack slot are padded downward. */
2427 if (mode != BLKmode)
2428 return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY) ? upward : downward;
2430 return ((int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
2431 ? upward : downward);
2434 enum direction
2435 nios2_block_reg_padding (machine_mode mode, tree type,
2436 int first ATTRIBUTE_UNUSED)
2438 return nios2_function_arg_padding (mode, type);
2441 /* Emit RTL insns to initialize the variable parts of a trampoline.
2442 FNADDR is an RTX for the address of the function's pure code.
2443 CXT is an RTX for the static chain value for the function.
2444 On Nios II, we handle this by a library call. */
2445 static void
2446 nios2_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
2448 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2449 rtx ctx_reg = force_reg (Pmode, cxt);
2450 rtx addr = force_reg (Pmode, XEXP (m_tramp, 0));
2452 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__trampoline_setup"),
2453 LCT_NORMAL, VOIDmode, 3, addr, Pmode, fnaddr, Pmode,
2454 ctx_reg, Pmode);
2457 /* Implement TARGET_FUNCTION_VALUE. */
2458 static rtx
2459 nios2_function_value (const_tree ret_type, const_tree fn ATTRIBUTE_UNUSED,
2460 bool outgoing ATTRIBUTE_UNUSED)
2462 return gen_rtx_REG (TYPE_MODE (ret_type), FIRST_RETVAL_REGNO);
2465 /* Implement TARGET_LIBCALL_VALUE. */
2466 static rtx
2467 nios2_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
2469 return gen_rtx_REG (mode, FIRST_RETVAL_REGNO);
2472 /* Implement TARGET_FUNCTION_VALUE_REGNO_P. */
2473 static bool
2474 nios2_function_value_regno_p (const unsigned int regno)
2476 return regno == FIRST_RETVAL_REGNO;
2479 /* Implement TARGET_RETURN_IN_MEMORY. */
2480 static bool
2481 nios2_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2483 return (int_size_in_bytes (type) > (2 * UNITS_PER_WORD)
2484 || int_size_in_bytes (type) == -1);
2487 /* TODO: It may be possible to eliminate the copyback and implement
2488 own va_arg type. */
2489 static void
2490 nios2_setup_incoming_varargs (cumulative_args_t cum_v,
2491 machine_mode mode, tree type,
2492 int *pretend_size, int second_time)
2494 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2495 CUMULATIVE_ARGS local_cum;
2496 cumulative_args_t local_cum_v = pack_cumulative_args (&local_cum);
2497 int regs_to_push;
2498 int pret_size;
2500 local_cum = *cum;
2501 nios2_function_arg_advance (local_cum_v, mode, type, 1);
2503 regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
2505 if (!second_time && regs_to_push > 0)
2507 rtx ptr = virtual_incoming_args_rtx;
2508 rtx mem = gen_rtx_MEM (BLKmode, ptr);
2509 emit_insn (gen_blockage ());
2510 move_block_from_reg (local_cum.regs_used + FIRST_ARG_REGNO, mem,
2511 regs_to_push);
2512 emit_insn (gen_blockage ());
2515 pret_size = regs_to_push * UNITS_PER_WORD;
2516 if (pret_size)
2517 *pretend_size = pret_size;
2522 /* Init FPU builtins. */
2523 static void
2524 nios2_init_fpu_builtins (int start_code)
2526 tree fndecl;
2527 char builtin_name[64] = "__builtin_custom_";
2528 unsigned int i, n = strlen ("__builtin_custom_");
2530 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
2532 snprintf (builtin_name + n, sizeof (builtin_name) - n,
2533 "%s", N2FPU_NAME (i));
2534 fndecl =
2535 add_builtin_function (builtin_name, nios2_ftype (N2FPU_FTCODE (i)),
2536 start_code + i, BUILT_IN_MD, NULL, NULL_TREE);
2537 nios2_register_builtin_fndecl (start_code + i, fndecl);
2541 /* Helper function for expanding FPU builtins. */
2542 static rtx
2543 nios2_expand_fpu_builtin (tree exp, unsigned int code, rtx target)
2545 struct expand_operand ops[MAX_RECOG_OPERANDS];
2546 enum insn_code icode = N2FPU_ICODE (code);
2547 int nargs, argno, opno = 0;
2548 int num_operands = N2FPU (code).num_operands;
2549 machine_mode dst_mode = TYPE_MODE (TREE_TYPE (exp));
2550 bool has_target_p = (dst_mode != VOIDmode);
2552 if (N2FPU_N (code) < 0)
2553 fatal_error ("Cannot call %<__builtin_custom_%s%> without specifying switch"
2554 " %<-mcustom-%s%>", N2FPU_NAME (code), N2FPU_NAME (code));
2555 if (has_target_p)
2556 create_output_operand (&ops[opno++], target, dst_mode);
2557 else
2558 /* Subtract away the count of the VOID return, mainly for fwrx/fwry. */
2559 num_operands -= 1;
2560 nargs = call_expr_nargs (exp);
2561 for (argno = 0; argno < nargs; argno++)
2563 tree arg = CALL_EXPR_ARG (exp, argno);
2564 create_input_operand (&ops[opno++], expand_normal (arg),
2565 TYPE_MODE (TREE_TYPE (arg)));
2567 if (!maybe_expand_insn (icode, num_operands, ops))
2569 error ("invalid argument to built-in function");
2570 return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
2572 return has_target_p ? ops[0].value : const0_rtx;
2575 /* Nios II has custom instruction built-in functions of the forms:
2576 __builtin_custom_n
2577 __builtin_custom_nX
2578 __builtin_custom_nXX
2579 __builtin_custom_Xn
2580 __builtin_custom_XnX
2581 __builtin_custom_XnXX
2583 where each X could be either 'i' (int), 'f' (float), or 'p' (void*).
2584 Therefore with 0-1 return values, and 0-2 arguments, we have a
2585 total of (3 + 1) * (1 + 3 + 9) == 52 custom builtin functions.
2587 #define NUM_CUSTOM_BUILTINS ((3 + 1) * (1 + 3 + 9))
2588 static char custom_builtin_name[NUM_CUSTOM_BUILTINS][5];
2590 static void
2591 nios2_init_custom_builtins (int start_code)
2593 tree builtin_ftype, ret_type, fndecl;
2594 char builtin_name[32] = "__builtin_custom_";
2595 int n = strlen ("__builtin_custom_");
2596 int builtin_code = 0;
2597 int lhs, rhs1, rhs2;
2599 struct { tree type; const char *c; } op[4];
2600 /* z */ op[0].c = ""; op[0].type = NULL_TREE;
2601 /* f */ op[1].c = "f"; op[1].type = float_type_node;
2602 /* i */ op[2].c = "i"; op[2].type = integer_type_node;
2603 /* p */ op[3].c = "p"; op[3].type = ptr_type_node;
2605 /* We enumerate through the possible operand types to create all the
2606 __builtin_custom_XnXX function tree types. Note that these may slightly
2607 overlap with the function types created for other fixed builtins. */
2609 for (lhs = 0; lhs < 4; lhs++)
2610 for (rhs1 = 0; rhs1 < 4; rhs1++)
2611 for (rhs2 = 0; rhs2 < 4; rhs2++)
2613 if (rhs1 == 0 && rhs2 != 0)
2614 continue;
2615 ret_type = (op[lhs].type ? op[lhs].type : void_type_node);
2616 builtin_ftype
2617 = build_function_type_list (ret_type, integer_type_node,
2618 op[rhs1].type, op[rhs2].type,
2619 NULL_TREE);
2620 snprintf (builtin_name + n, 32 - n, "%sn%s%s",
2621 op[lhs].c, op[rhs1].c, op[rhs2].c);
2622 /* Save copy of parameter string into custom_builtin_name[]. */
2623 strncpy (custom_builtin_name[builtin_code], builtin_name + n, 5);
2624 fndecl =
2625 add_builtin_function (builtin_name, builtin_ftype,
2626 start_code + builtin_code,
2627 BUILT_IN_MD, NULL, NULL_TREE);
2628 nios2_register_builtin_fndecl (start_code + builtin_code, fndecl);
2629 builtin_code += 1;
2633 /* Helper function for expanding custom builtins. */
2634 static rtx
2635 nios2_expand_custom_builtin (tree exp, unsigned int index, rtx target)
2637 bool has_target_p = (TREE_TYPE (exp) != void_type_node);
2638 machine_mode tmode = VOIDmode;
2639 int nargs, argno;
2640 rtx value, insn, unspec_args[3];
2641 tree arg;
2643 /* XnXX form. */
2644 if (has_target_p)
2646 tmode = TYPE_MODE (TREE_TYPE (exp));
2647 if (!target || GET_MODE (target) != tmode
2648 || !REG_P (target))
2649 target = gen_reg_rtx (tmode);
2652 nargs = call_expr_nargs (exp);
2653 for (argno = 0; argno < nargs; argno++)
2655 arg = CALL_EXPR_ARG (exp, argno);
2656 value = expand_normal (arg);
2657 unspec_args[argno] = value;
2658 if (argno == 0)
2660 if (!custom_insn_opcode (value, VOIDmode))
2661 error ("custom instruction opcode must be compile time "
2662 "constant in the range 0-255 for __builtin_custom_%s",
2663 custom_builtin_name[index]);
2665 else
2666 /* For other arguments, force into a register. */
2667 unspec_args[argno] = force_reg (TYPE_MODE (TREE_TYPE (arg)),
2668 unspec_args[argno]);
2670 /* Fill remaining unspec operands with zero. */
2671 for (; argno < 3; argno++)
2672 unspec_args[argno] = const0_rtx;
2674 insn = (has_target_p
2675 ? gen_rtx_SET (VOIDmode, target,
2676 gen_rtx_UNSPEC_VOLATILE (tmode,
2677 gen_rtvec_v (3, unspec_args),
2678 UNSPECV_CUSTOM_XNXX))
2679 : gen_rtx_UNSPEC_VOLATILE (VOIDmode, gen_rtvec_v (3, unspec_args),
2680 UNSPECV_CUSTOM_NXX));
2681 emit_insn (insn);
2682 return has_target_p ? target : const0_rtx;
2688 /* Main definition of built-in functions. Nios II has a small number of fixed
2689 builtins, plus a large number of FPU insn builtins, and builtins for
2690 generating custom instructions. */
2692 struct nios2_builtin_desc
2694 enum insn_code icode;
2695 enum nios2_ftcode ftype;
2696 const char *name;
2699 #define N2_BUILTINS \
2700 N2_BUILTIN_DEF (sync, N2_FTYPE_VOID_VOID) \
2701 N2_BUILTIN_DEF (ldbio, N2_FTYPE_SI_CVPTR) \
2702 N2_BUILTIN_DEF (ldbuio, N2_FTYPE_UI_CVPTR) \
2703 N2_BUILTIN_DEF (ldhio, N2_FTYPE_SI_CVPTR) \
2704 N2_BUILTIN_DEF (ldhuio, N2_FTYPE_UI_CVPTR) \
2705 N2_BUILTIN_DEF (ldwio, N2_FTYPE_SI_CVPTR) \
2706 N2_BUILTIN_DEF (stbio, N2_FTYPE_VOID_VPTR_SI) \
2707 N2_BUILTIN_DEF (sthio, N2_FTYPE_VOID_VPTR_SI) \
2708 N2_BUILTIN_DEF (stwio, N2_FTYPE_VOID_VPTR_SI) \
2709 N2_BUILTIN_DEF (rdctl, N2_FTYPE_SI_SI) \
2710 N2_BUILTIN_DEF (wrctl, N2_FTYPE_VOID_SI_SI)
2712 enum nios2_builtin_code {
2713 #define N2_BUILTIN_DEF(name, ftype) NIOS2_BUILTIN_ ## name,
2714 N2_BUILTINS
2715 #undef N2_BUILTIN_DEF
2716 NUM_FIXED_NIOS2_BUILTINS
2719 static const struct nios2_builtin_desc nios2_builtins[] = {
2720 #define N2_BUILTIN_DEF(name, ftype) \
2721 { CODE_FOR_ ## name, ftype, "__builtin_" #name },
2722 N2_BUILTINS
2723 #undef N2_BUILTIN_DEF
2726 /* Start/ends of FPU/custom insn builtin index ranges. */
2727 static unsigned int nios2_fpu_builtin_base;
2728 static unsigned int nios2_custom_builtin_base;
2729 static unsigned int nios2_custom_builtin_end;
2731 /* Implement TARGET_INIT_BUILTINS. */
2732 static void
2733 nios2_init_builtins (void)
2735 unsigned int i;
2737 /* Initialize fixed builtins. */
2738 for (i = 0; i < ARRAY_SIZE (nios2_builtins); i++)
2740 const struct nios2_builtin_desc *d = &nios2_builtins[i];
2741 tree fndecl =
2742 add_builtin_function (d->name, nios2_ftype (d->ftype), i,
2743 BUILT_IN_MD, NULL, NULL);
2744 nios2_register_builtin_fndecl (i, fndecl);
2747 /* Initialize FPU builtins. */
2748 nios2_fpu_builtin_base = ARRAY_SIZE (nios2_builtins);
2749 nios2_init_fpu_builtins (nios2_fpu_builtin_base);
2751 /* Initialize custom insn builtins. */
2752 nios2_custom_builtin_base
2753 = nios2_fpu_builtin_base + ARRAY_SIZE (nios2_fpu_insn);
2754 nios2_custom_builtin_end
2755 = nios2_custom_builtin_base + NUM_CUSTOM_BUILTINS;
2756 nios2_init_custom_builtins (nios2_custom_builtin_base);
2759 /* Array of fndecls for TARGET_BUILTIN_DECL. */
2760 #define NIOS2_NUM_BUILTINS \
2761 (ARRAY_SIZE (nios2_builtins) + ARRAY_SIZE (nios2_fpu_insn) + NUM_CUSTOM_BUILTINS)
2762 static GTY(()) tree nios2_builtin_decls[NIOS2_NUM_BUILTINS];
2764 static void
2765 nios2_register_builtin_fndecl (unsigned code, tree fndecl)
2767 nios2_builtin_decls[code] = fndecl;
2770 /* Implement TARGET_BUILTIN_DECL. */
2771 static tree
2772 nios2_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
2774 gcc_assert (nios2_custom_builtin_end == ARRAY_SIZE (nios2_builtin_decls));
2776 if (code >= nios2_custom_builtin_end)
2777 return error_mark_node;
2779 if (code >= nios2_fpu_builtin_base
2780 && code < nios2_custom_builtin_base
2781 && ! N2FPU_ENABLED_P (code - nios2_fpu_builtin_base))
2782 return error_mark_node;
2784 return nios2_builtin_decls[code];
2788 /* Low-level built-in expand routine. */
2789 static rtx
2790 nios2_expand_builtin_insn (const struct nios2_builtin_desc *d, int n,
2791 struct expand_operand *ops, bool has_target_p)
2793 if (maybe_expand_insn (d->icode, n, ops))
2794 return has_target_p ? ops[0].value : const0_rtx;
2795 else
2797 error ("invalid argument to built-in function %s", d->name);
2798 return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
2802 /* Expand ldio/stio form load-store instruction builtins. */
2803 static rtx
2804 nios2_expand_ldstio_builtin (tree exp, rtx target,
2805 const struct nios2_builtin_desc *d)
2807 bool has_target_p;
2808 rtx addr, mem, val;
2809 struct expand_operand ops[MAX_RECOG_OPERANDS];
2810 machine_mode mode = insn_data[d->icode].operand[0].mode;
2812 addr = expand_normal (CALL_EXPR_ARG (exp, 0));
2813 mem = gen_rtx_MEM (mode, addr);
2815 if (insn_data[d->icode].operand[0].allows_mem)
2817 /* stxio. */
2818 val = expand_normal (CALL_EXPR_ARG (exp, 1));
2819 if (CONST_INT_P (val))
2820 val = force_reg (mode, gen_int_mode (INTVAL (val), mode));
2821 val = simplify_gen_subreg (mode, val, GET_MODE (val), 0);
2822 create_output_operand (&ops[0], mem, mode);
2823 create_input_operand (&ops[1], val, mode);
2824 has_target_p = false;
2826 else
2828 /* ldxio. */
2829 create_output_operand (&ops[0], target, mode);
2830 create_input_operand (&ops[1], mem, mode);
2831 has_target_p = true;
2833 return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
2836 /* Expand rdctl/wrctl builtins. */
2837 static rtx
2838 nios2_expand_rdwrctl_builtin (tree exp, rtx target,
2839 const struct nios2_builtin_desc *d)
2841 bool has_target_p = (insn_data[d->icode].operand[0].predicate
2842 == register_operand);
2843 rtx ctlcode = expand_normal (CALL_EXPR_ARG (exp, 0));
2844 struct expand_operand ops[MAX_RECOG_OPERANDS];
2845 if (!rdwrctl_operand (ctlcode, VOIDmode))
2847 error ("Control register number must be in range 0-31 for %s",
2848 d->name);
2849 return has_target_p ? gen_reg_rtx (SImode) : const0_rtx;
2851 if (has_target_p)
2853 create_output_operand (&ops[0], target, SImode);
2854 create_integer_operand (&ops[1], INTVAL (ctlcode));
2856 else
2858 rtx val = expand_normal (CALL_EXPR_ARG (exp, 1));
2859 create_integer_operand (&ops[0], INTVAL (ctlcode));
2860 create_input_operand (&ops[1], val, SImode);
2862 return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
2865 /* Implement TARGET_EXPAND_BUILTIN. Expand an expression EXP that calls
2866 a built-in function, with result going to TARGET if that's convenient
2867 (and in mode MODE if that's convenient).
2868 SUBTARGET may be used as the target for computing one of EXP's operands.
2869 IGNORE is nonzero if the value is to be ignored. */
2871 static rtx
2872 nios2_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
2873 machine_mode mode ATTRIBUTE_UNUSED,
2874 int ignore ATTRIBUTE_UNUSED)
2876 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2877 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2879 if (fcode < nios2_fpu_builtin_base)
2881 const struct nios2_builtin_desc *d = &nios2_builtins[fcode];
2883 switch (fcode)
2885 case NIOS2_BUILTIN_sync:
2886 emit_insn (gen_sync ());
2887 return const0_rtx;
2889 case NIOS2_BUILTIN_ldbio:
2890 case NIOS2_BUILTIN_ldbuio:
2891 case NIOS2_BUILTIN_ldhio:
2892 case NIOS2_BUILTIN_ldhuio:
2893 case NIOS2_BUILTIN_ldwio:
2894 case NIOS2_BUILTIN_stbio:
2895 case NIOS2_BUILTIN_sthio:
2896 case NIOS2_BUILTIN_stwio:
2897 return nios2_expand_ldstio_builtin (exp, target, d);
2899 case NIOS2_BUILTIN_rdctl:
2900 case NIOS2_BUILTIN_wrctl:
2901 return nios2_expand_rdwrctl_builtin (exp, target, d);
2903 default:
2904 gcc_unreachable ();
2907 else if (fcode < nios2_custom_builtin_base)
2908 /* FPU builtin range. */
2909 return nios2_expand_fpu_builtin (exp, fcode - nios2_fpu_builtin_base,
2910 target);
2911 else if (fcode < nios2_custom_builtin_end)
2912 /* Custom insn builtin range. */
2913 return nios2_expand_custom_builtin (exp, fcode - nios2_custom_builtin_base,
2914 target);
2915 else
2916 gcc_unreachable ();
2919 /* Implement TARGET_INIT_LIBFUNCS. */
2920 static void
2921 nios2_init_libfuncs (void)
2923 /* For Linux, we have access to kernel support for atomic operations. */
2924 if (TARGET_LINUX_ABI)
2925 init_sync_libfuncs (UNITS_PER_WORD);
2930 /* Register a custom code use, and signal error if a conflict was found. */
2931 static void
2932 nios2_register_custom_code (unsigned int N, enum nios2_ccs_code status,
2933 int index)
2935 gcc_assert (N <= 255);
2937 if (status == CCS_FPU)
2939 if (custom_code_status[N] == CCS_FPU && index != custom_code_index[N])
2941 custom_code_conflict = true;
2942 error ("switch %<-mcustom-%s%> conflicts with switch %<-mcustom-%s%>",
2943 N2FPU_NAME (custom_code_index[N]), N2FPU_NAME (index));
2945 else if (custom_code_status[N] == CCS_BUILTIN_CALL)
2947 custom_code_conflict = true;
2948 error ("call to %<__builtin_custom_%s%> conflicts with switch "
2949 "%<-mcustom-%s%>", custom_builtin_name[custom_code_index[N]],
2950 N2FPU_NAME (index));
2953 else if (status == CCS_BUILTIN_CALL)
2955 if (custom_code_status[N] == CCS_FPU)
2957 custom_code_conflict = true;
2958 error ("call to %<__builtin_custom_%s%> conflicts with switch "
2959 "%<-mcustom-%s%>", custom_builtin_name[index],
2960 N2FPU_NAME (custom_code_index[N]));
2962 else
2964 /* Note that code conflicts between different __builtin_custom_xnxx
2965 calls are not checked. */
2968 else
2969 gcc_unreachable ();
2971 custom_code_status[N] = status;
2972 custom_code_index[N] = index;
2975 /* Mark a custom code as not in use. */
2976 static void
2977 nios2_deregister_custom_code (unsigned int N)
2979 if (N <= 255)
2981 custom_code_status[N] = CCS_UNUSED;
2982 custom_code_index[N] = 0;
2986 /* Target attributes can affect per-function option state, so we need to
2987 save/restore the custom code tracking info using the
2988 TARGET_OPTION_SAVE/TARGET_OPTION_RESTORE hooks. */
2990 static void
2991 nios2_option_save (struct cl_target_option *ptr,
2992 struct gcc_options *opts ATTRIBUTE_UNUSED)
2994 unsigned int i;
2995 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
2996 ptr->saved_fpu_custom_code[i] = N2FPU_N (i);
2997 memcpy (ptr->saved_custom_code_status, custom_code_status,
2998 sizeof (custom_code_status));
2999 memcpy (ptr->saved_custom_code_index, custom_code_index,
3000 sizeof (custom_code_index));
3003 static void
3004 nios2_option_restore (struct gcc_options *opts ATTRIBUTE_UNUSED,
3005 struct cl_target_option *ptr)
3007 unsigned int i;
3008 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
3009 N2FPU_N (i) = ptr->saved_fpu_custom_code[i];
3010 memcpy (custom_code_status, ptr->saved_custom_code_status,
3011 sizeof (custom_code_status));
3012 memcpy (custom_code_index, ptr->saved_custom_code_index,
3013 sizeof (custom_code_index));
3016 /* Inner function to process the attribute((target(...))), take an argument and
3017 set the current options from the argument. If we have a list, recursively
3018 go over the list. */
3020 static bool
3021 nios2_valid_target_attribute_rec (tree args)
3023 if (TREE_CODE (args) == TREE_LIST)
3025 bool ret = true;
3026 for (; args; args = TREE_CHAIN (args))
3027 if (TREE_VALUE (args)
3028 && !nios2_valid_target_attribute_rec (TREE_VALUE (args)))
3029 ret = false;
3030 return ret;
3032 else if (TREE_CODE (args) == STRING_CST)
3034 char *argstr = ASTRDUP (TREE_STRING_POINTER (args));
3035 while (argstr && *argstr != '\0')
3037 bool no_opt = false, end_p = false;
3038 char *eq = NULL, *p;
3039 while (ISSPACE (*argstr))
3040 argstr++;
3041 p = argstr;
3042 while (*p != '\0' && *p != ',')
3044 if (!eq && *p == '=')
3045 eq = p;
3046 ++p;
3048 if (*p == '\0')
3049 end_p = true;
3050 else
3051 *p = '\0';
3052 if (eq) *eq = '\0';
3054 if (!strncmp (argstr, "no-", 3))
3056 no_opt = true;
3057 argstr += 3;
3059 if (!strncmp (argstr, "custom-fpu-cfg", 14))
3061 char *end_eq = p;
3062 if (no_opt)
3064 error ("custom-fpu-cfg option does not support %<no-%>");
3065 return false;
3067 if (!eq)
3069 error ("custom-fpu-cfg option requires configuration"
3070 " argument");
3071 return false;
3073 /* Increment and skip whitespace. */
3074 while (ISSPACE (*(++eq))) ;
3075 /* Decrement and skip to before any trailing whitespace. */
3076 while (ISSPACE (*(--end_eq))) ;
3078 nios2_handle_custom_fpu_cfg (eq, end_eq + 1, true);
3080 else if (!strncmp (argstr, "custom-", 7))
3082 int code = -1;
3083 unsigned int i;
3084 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
3085 if (!strncmp (argstr + 7, N2FPU_NAME (i),
3086 strlen (N2FPU_NAME (i))))
3088 /* Found insn. */
3089 code = i;
3090 break;
3092 if (code >= 0)
3094 if (no_opt)
3096 if (eq)
3098 error ("%<no-custom-%s%> does not accept arguments",
3099 N2FPU_NAME (code));
3100 return false;
3102 /* Disable option by setting to -1. */
3103 nios2_deregister_custom_code (N2FPU_N (code));
3104 N2FPU_N (code) = -1;
3106 else
3108 char *t;
3109 if (eq)
3110 while (ISSPACE (*(++eq))) ;
3111 if (!eq || eq == p)
3113 error ("%<custom-%s=%> requires argument",
3114 N2FPU_NAME (code));
3115 return false;
3117 for (t = eq; t != p; ++t)
3119 if (ISSPACE (*t))
3120 continue;
3121 if (!ISDIGIT (*t))
3123 error ("`custom-%s=' argument requires "
3124 "numeric digits", N2FPU_NAME (code));
3125 return false;
3128 /* Set option to argument. */
3129 N2FPU_N (code) = atoi (eq);
3130 nios2_handle_custom_fpu_insn_option (code);
3133 else
3135 error ("%<custom-%s=%> is not recognised as FPU instruction",
3136 argstr + 7);
3137 return false;
3140 else
3142 error ("%<%s%> is unknown", argstr);
3143 return false;
3146 if (end_p)
3147 break;
3148 else
3149 argstr = p + 1;
3151 return true;
3153 else
3154 gcc_unreachable ();
3157 /* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. */
3159 static tree
3160 nios2_valid_target_attribute_tree (tree args)
3162 if (!nios2_valid_target_attribute_rec (args))
3163 return NULL_TREE;
3164 nios2_custom_check_insns ();
3165 return build_target_option_node (&global_options);
3168 /* Hook to validate attribute((target("string"))). */
3170 static bool
3171 nios2_valid_target_attribute_p (tree fndecl, tree ARG_UNUSED (name),
3172 tree args, int ARG_UNUSED (flags))
3174 struct cl_target_option cur_target;
3175 bool ret = true;
3176 tree old_optimize = build_optimization_node (&global_options);
3177 tree new_target, new_optimize;
3178 tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
3180 /* If the function changed the optimization levels as well as setting target
3181 options, start with the optimizations specified. */
3182 if (func_optimize && func_optimize != old_optimize)
3183 cl_optimization_restore (&global_options,
3184 TREE_OPTIMIZATION (func_optimize));
3186 /* The target attributes may also change some optimization flags, so update
3187 the optimization options if necessary. */
3188 cl_target_option_save (&cur_target, &global_options);
3189 new_target = nios2_valid_target_attribute_tree (args);
3190 new_optimize = build_optimization_node (&global_options);
3192 if (!new_target)
3193 ret = false;
3195 else if (fndecl)
3197 DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
3199 if (old_optimize != new_optimize)
3200 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
3203 cl_target_option_restore (&global_options, &cur_target);
3205 if (old_optimize != new_optimize)
3206 cl_optimization_restore (&global_options,
3207 TREE_OPTIMIZATION (old_optimize));
3208 return ret;
3211 /* Remember the last target of nios2_set_current_function. */
3212 static GTY(()) tree nios2_previous_fndecl;
3214 /* Establish appropriate back-end context for processing the function
3215 FNDECL. The argument might be NULL to indicate processing at top
3216 level, outside of any function scope. */
3217 static void
3218 nios2_set_current_function (tree fndecl)
3220 tree old_tree = (nios2_previous_fndecl
3221 ? DECL_FUNCTION_SPECIFIC_TARGET (nios2_previous_fndecl)
3222 : NULL_TREE);
3224 tree new_tree = (fndecl
3225 ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl)
3226 : NULL_TREE);
3228 if (fndecl && fndecl != nios2_previous_fndecl)
3230 nios2_previous_fndecl = fndecl;
3231 if (old_tree == new_tree)
3234 else if (new_tree)
3236 cl_target_option_restore (&global_options,
3237 TREE_TARGET_OPTION (new_tree));
3238 target_reinit ();
3241 else if (old_tree)
3243 struct cl_target_option *def
3244 = TREE_TARGET_OPTION (target_option_current_node);
3246 cl_target_option_restore (&global_options, def);
3247 target_reinit ();
3252 /* Hook to validate the current #pragma GCC target and set the FPU custom
3253 code option state. If ARGS is NULL, then POP_TARGET is used to reset
3254 the options. */
3255 static bool
3256 nios2_pragma_target_parse (tree args, tree pop_target)
3258 tree cur_tree;
3259 if (! args)
3261 cur_tree = ((pop_target)
3262 ? pop_target
3263 : target_option_default_node);
3264 cl_target_option_restore (&global_options,
3265 TREE_TARGET_OPTION (cur_tree));
3267 else
3269 cur_tree = nios2_valid_target_attribute_tree (args);
3270 if (!cur_tree)
3271 return false;
3274 target_option_current_node = cur_tree;
3275 return true;
3278 /* Implement TARGET_MERGE_DECL_ATTRIBUTES.
3279 We are just using this hook to add some additional error checking to
3280 the default behavior. GCC does not provide a target hook for merging
3281 the target options, and only correctly handles merging empty vs non-empty
3282 option data; see merge_decls() in c-decl.c.
3283 So here we require either that at least one of the decls has empty
3284 target options, or that the target options/data be identical. */
3285 static tree
3286 nios2_merge_decl_attributes (tree olddecl, tree newdecl)
3288 tree oldopts = lookup_attribute ("target", DECL_ATTRIBUTES (olddecl));
3289 tree newopts = lookup_attribute ("target", DECL_ATTRIBUTES (newdecl));
3290 if (newopts && oldopts && newopts != oldopts)
3292 tree oldtree = DECL_FUNCTION_SPECIFIC_TARGET (olddecl);
3293 tree newtree = DECL_FUNCTION_SPECIFIC_TARGET (newdecl);
3294 if (oldtree && newtree && oldtree != newtree)
3296 struct cl_target_option *olddata = TREE_TARGET_OPTION (oldtree);
3297 struct cl_target_option *newdata = TREE_TARGET_OPTION (newtree);
3298 if (olddata != newdata
3299 && memcmp (olddata, newdata, sizeof (struct cl_target_option)))
3300 error ("%qE redeclared with conflicting %qs attributes",
3301 DECL_NAME (newdecl), "target");
3304 return merge_attributes (DECL_ATTRIBUTES (olddecl),
3305 DECL_ATTRIBUTES (newdecl));
3309 /* Initialize the GCC target structure. */
3310 #undef TARGET_ASM_FUNCTION_PROLOGUE
3311 #define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
3313 #undef TARGET_IN_SMALL_DATA_P
3314 #define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
3316 #undef TARGET_SECTION_TYPE_FLAGS
3317 #define TARGET_SECTION_TYPE_FLAGS nios2_section_type_flags
3319 #undef TARGET_INIT_BUILTINS
3320 #define TARGET_INIT_BUILTINS nios2_init_builtins
3321 #undef TARGET_EXPAND_BUILTIN
3322 #define TARGET_EXPAND_BUILTIN nios2_expand_builtin
3323 #undef TARGET_BUILTIN_DECL
3324 #define TARGET_BUILTIN_DECL nios2_builtin_decl
3326 #undef TARGET_INIT_LIBFUNCS
3327 #define TARGET_INIT_LIBFUNCS nios2_init_libfuncs
3329 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
3330 #define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
3332 #undef TARGET_CAN_ELIMINATE
3333 #define TARGET_CAN_ELIMINATE nios2_can_eliminate
3335 #undef TARGET_FUNCTION_ARG
3336 #define TARGET_FUNCTION_ARG nios2_function_arg
3338 #undef TARGET_FUNCTION_ARG_ADVANCE
3339 #define TARGET_FUNCTION_ARG_ADVANCE nios2_function_arg_advance
3341 #undef TARGET_ARG_PARTIAL_BYTES
3342 #define TARGET_ARG_PARTIAL_BYTES nios2_arg_partial_bytes
3344 #undef TARGET_TRAMPOLINE_INIT
3345 #define TARGET_TRAMPOLINE_INIT nios2_trampoline_init
3347 #undef TARGET_FUNCTION_VALUE
3348 #define TARGET_FUNCTION_VALUE nios2_function_value
3350 #undef TARGET_LIBCALL_VALUE
3351 #define TARGET_LIBCALL_VALUE nios2_libcall_value
3353 #undef TARGET_FUNCTION_VALUE_REGNO_P
3354 #define TARGET_FUNCTION_VALUE_REGNO_P nios2_function_value_regno_p
3356 #undef TARGET_RETURN_IN_MEMORY
3357 #define TARGET_RETURN_IN_MEMORY nios2_return_in_memory
3359 #undef TARGET_PROMOTE_PROTOTYPES
3360 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
3362 #undef TARGET_SETUP_INCOMING_VARARGS
3363 #define TARGET_SETUP_INCOMING_VARARGS nios2_setup_incoming_varargs
3365 #undef TARGET_MUST_PASS_IN_STACK
3366 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
3368 #undef TARGET_LEGITIMATE_CONSTANT_P
3369 #define TARGET_LEGITIMATE_CONSTANT_P nios2_legitimate_constant_p
3371 #undef TARGET_LEGITIMIZE_ADDRESS
3372 #define TARGET_LEGITIMIZE_ADDRESS nios2_legitimize_address
3374 #undef TARGET_DELEGITIMIZE_ADDRESS
3375 #define TARGET_DELEGITIMIZE_ADDRESS nios2_delegitimize_address
3377 #undef TARGET_LEGITIMATE_ADDRESS_P
3378 #define TARGET_LEGITIMATE_ADDRESS_P nios2_legitimate_address_p
3380 #undef TARGET_PREFERRED_RELOAD_CLASS
3381 #define TARGET_PREFERRED_RELOAD_CLASS nios2_preferred_reload_class
3383 #undef TARGET_RTX_COSTS
3384 #define TARGET_RTX_COSTS nios2_rtx_costs
3386 #undef TARGET_HAVE_TLS
3387 #define TARGET_HAVE_TLS TARGET_LINUX_ABI
3389 #undef TARGET_CANNOT_FORCE_CONST_MEM
3390 #define TARGET_CANNOT_FORCE_CONST_MEM nios2_cannot_force_const_mem
3392 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
3393 #define TARGET_ASM_OUTPUT_DWARF_DTPREL nios2_output_dwarf_dtprel
3395 #undef TARGET_PRINT_OPERAND
3396 #define TARGET_PRINT_OPERAND nios2_print_operand
3398 #undef TARGET_PRINT_OPERAND_ADDRESS
3399 #define TARGET_PRINT_OPERAND_ADDRESS nios2_print_operand_address
3401 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
3402 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA nios2_output_addr_const_extra
3404 #undef TARGET_OPTION_OVERRIDE
3405 #define TARGET_OPTION_OVERRIDE nios2_option_override
3407 #undef TARGET_OPTION_SAVE
3408 #define TARGET_OPTION_SAVE nios2_option_save
3410 #undef TARGET_OPTION_RESTORE
3411 #define TARGET_OPTION_RESTORE nios2_option_restore
3413 #undef TARGET_SET_CURRENT_FUNCTION
3414 #define TARGET_SET_CURRENT_FUNCTION nios2_set_current_function
3416 #undef TARGET_OPTION_VALID_ATTRIBUTE_P
3417 #define TARGET_OPTION_VALID_ATTRIBUTE_P nios2_valid_target_attribute_p
3419 #undef TARGET_OPTION_PRAGMA_PARSE
3420 #define TARGET_OPTION_PRAGMA_PARSE nios2_pragma_target_parse
3422 #undef TARGET_MERGE_DECL_ATTRIBUTES
3423 #define TARGET_MERGE_DECL_ATTRIBUTES nios2_merge_decl_attributes
3425 struct gcc_target targetm = TARGET_INITIALIZER;
3427 #include "gt-nios2.h"