]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/nios2/nios2.c
Update copyright years in gcc/
[thirdparty/gcc.git] / gcc / config / nios2 / nios2.c
1 /* Target machine subroutines for Altera Nios II.
2 Copyright (C) 2012-2014 Free Software Foundation, Inc.
3 Contributed by Jonah Graham (jgraham@altera.com),
4 Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@altera.com).
5 Contributed by Mentor Graphics, Inc.
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published
11 by the Free Software Foundation; either version 3, or (at your
12 option) any later version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "rtl.h"
28 #include "tree.h"
29 #include "regs.h"
30 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "output.h"
34 #include "insn-attr.h"
35 #include "flags.h"
36 #include "recog.h"
37 #include "expr.h"
38 #include "optabs.h"
39 #include "function.h"
40 #include "ggc.h"
41 #include "basic-block.h"
42 #include "diagnostic-core.h"
43 #include "toplev.h"
44 #include "target.h"
45 #include "target-def.h"
46 #include "tm_p.h"
47 #include "langhooks.h"
48 #include "df.h"
49 #include "debug.h"
50 #include "real.h"
51 #include "reload.h"
52 #include "stor-layout.h"
53 #include "varasm.h"
54 #include "calls.h"
55
56 /* Forward function declarations. */
57 static bool prologue_saved_reg_p (unsigned);
58 static void nios2_load_pic_register (void);
59 static void nios2_register_custom_code (unsigned int, enum nios2_ccs_code, int);
60 static const char *nios2_unspec_reloc_name (int);
61 static void nios2_register_builtin_fndecl (unsigned, tree);
62
63 /* Threshold for data being put into the small data/bss area, instead
64 of the normal data area (references to the small data/bss area take
65 1 instruction, and use the global pointer, references to the normal
66 data area takes 2 instructions). */
67 unsigned HOST_WIDE_INT nios2_section_threshold = NIOS2_DEFAULT_GVALUE;
68
69 struct GTY (()) machine_function
70 {
71 /* Current frame information, to be filled in by nios2_compute_frame_layout
72 with register save masks, and offsets for the current function. */
73
74 /* Mask of registers to save. */
75 unsigned int save_mask;
76 /* Number of bytes that the entire frame takes up. */
77 int total_size;
78 /* Number of bytes that variables take up. */
79 int var_size;
80 /* Number of bytes that outgoing arguments take up. */
81 int args_size;
82 /* Number of bytes needed to store registers in frame. */
83 int save_reg_size;
84 /* Offset from new stack pointer to store registers. */
85 int save_regs_offset;
86 /* != 0 if frame layout already calculated. */
87 int initialized;
88 };
89
90 /* State to track the assignment of custom codes to FPU/custom builtins. */
91 static enum nios2_ccs_code custom_code_status[256];
92 static int custom_code_index[256];
93 /* Set to true if any conflicts (re-use of a code between 0-255) are found. */
94 static bool custom_code_conflict = false;
95
96 \f
97 /* Definition of builtin function types for nios2. */
98
99 #define N2_FTYPES \
100 N2_FTYPE(1, (SF)) \
101 N2_FTYPE(1, (VOID)) \
102 N2_FTYPE(2, (DF, DF)) \
103 N2_FTYPE(3, (DF, DF, DF)) \
104 N2_FTYPE(2, (DF, SF)) \
105 N2_FTYPE(2, (DF, SI)) \
106 N2_FTYPE(2, (DF, UI)) \
107 N2_FTYPE(2, (SF, DF)) \
108 N2_FTYPE(2, (SF, SF)) \
109 N2_FTYPE(3, (SF, SF, SF)) \
110 N2_FTYPE(2, (SF, SI)) \
111 N2_FTYPE(2, (SF, UI)) \
112 N2_FTYPE(2, (SI, CVPTR)) \
113 N2_FTYPE(2, (SI, DF)) \
114 N2_FTYPE(3, (SI, DF, DF)) \
115 N2_FTYPE(2, (SI, SF)) \
116 N2_FTYPE(3, (SI, SF, SF)) \
117 N2_FTYPE(2, (SI, SI)) \
118 N2_FTYPE(2, (UI, CVPTR)) \
119 N2_FTYPE(2, (UI, DF)) \
120 N2_FTYPE(2, (UI, SF)) \
121 N2_FTYPE(2, (VOID, DF)) \
122 N2_FTYPE(2, (VOID, SF)) \
123 N2_FTYPE(3, (VOID, SI, SI)) \
124 N2_FTYPE(3, (VOID, VPTR, SI))
125
126 #define N2_FTYPE_OP1(R) N2_FTYPE_ ## R ## _VOID
127 #define N2_FTYPE_OP2(R, A1) N2_FTYPE_ ## R ## _ ## A1
128 #define N2_FTYPE_OP3(R, A1, A2) N2_FTYPE_ ## R ## _ ## A1 ## _ ## A2
129
130 /* Expand ftcode enumeration. */
131 enum nios2_ftcode {
132 #define N2_FTYPE(N,ARGS) N2_FTYPE_OP ## N ARGS,
133 N2_FTYPES
134 #undef N2_FTYPE
135 N2_FTYPE_MAX
136 };
137
138 /* Return the tree function type, based on the ftcode. */
139 static tree
140 nios2_ftype (enum nios2_ftcode ftcode)
141 {
142 static tree types[(int) N2_FTYPE_MAX];
143
144 tree N2_TYPE_SF = float_type_node;
145 tree N2_TYPE_DF = double_type_node;
146 tree N2_TYPE_SI = integer_type_node;
147 tree N2_TYPE_UI = unsigned_type_node;
148 tree N2_TYPE_VOID = void_type_node;
149
150 static const_tree N2_TYPE_CVPTR, N2_TYPE_VPTR;
151 if (!N2_TYPE_CVPTR)
152 {
153 /* const volatile void *. */
154 N2_TYPE_CVPTR
155 = build_pointer_type (build_qualified_type (void_type_node,
156 (TYPE_QUAL_CONST
157 | TYPE_QUAL_VOLATILE)));
158 /* volatile void *. */
159 N2_TYPE_VPTR
160 = build_pointer_type (build_qualified_type (void_type_node,
161 TYPE_QUAL_VOLATILE));
162 }
163 if (types[(int) ftcode] == NULL_TREE)
164 switch (ftcode)
165 {
166 #define N2_FTYPE_ARGS1(R) N2_TYPE_ ## R
167 #define N2_FTYPE_ARGS2(R,A1) N2_TYPE_ ## R, N2_TYPE_ ## A1
168 #define N2_FTYPE_ARGS3(R,A1,A2) N2_TYPE_ ## R, N2_TYPE_ ## A1, N2_TYPE_ ## A2
169 #define N2_FTYPE(N,ARGS) \
170 case N2_FTYPE_OP ## N ARGS: \
171 types[(int) ftcode] \
172 = build_function_type_list (N2_FTYPE_ARGS ## N ARGS, NULL_TREE); \
173 break;
174 N2_FTYPES
175 #undef N2_FTYPE
176 default: gcc_unreachable ();
177 }
178 return types[(int) ftcode];
179 }
180
181 \f
182 /* Definition of FPU instruction descriptions. */
183
184 struct nios2_fpu_insn_info
185 {
186 const char *name;
187 int num_operands, *optvar;
188 int opt, no_opt;
189 #define N2F_DF 0x1
190 #define N2F_DFREQ 0x2
191 #define N2F_UNSAFE 0x4
192 #define N2F_FINITE 0x8
193 unsigned int flags;
194 enum insn_code icode;
195 enum nios2_ftcode ftcode;
196 };
197
198 /* Base macro for defining FPU instructions. */
199 #define N2FPU_INSN_DEF_BASE(insn, nop, flags, icode, args) \
200 { #insn, nop, &nios2_custom_ ## insn, OPT_mcustom_##insn##_, \
201 OPT_mno_custom_##insn, flags, CODE_FOR_ ## icode, \
202 N2_FTYPE_OP ## nop args }
203
204 /* Arithmetic and math functions; 2 or 3 operand FP operations. */
205 #define N2FPU_OP2(mode) (mode, mode)
206 #define N2FPU_OP3(mode) (mode, mode, mode)
207 #define N2FPU_INSN_DEF(code, icode, nop, flags, m, M) \
208 N2FPU_INSN_DEF_BASE (f ## code ## m, nop, flags, \
209 icode ## m ## f ## nop, N2FPU_OP ## nop (M ## F))
210 #define N2FPU_INSN_SF(code, nop, flags) \
211 N2FPU_INSN_DEF (code, code, nop, flags, s, S)
212 #define N2FPU_INSN_DF(code, nop, flags) \
213 N2FPU_INSN_DEF (code, code, nop, flags | N2F_DF, d, D)
214
215 /* Compare instructions, 3 operand FP operation with a SI result. */
216 #define N2FPU_CMP_DEF(code, flags, m, M) \
217 N2FPU_INSN_DEF_BASE (fcmp ## code ## m, 3, flags, \
218 nios2_s ## code ## m ## f, (SI, M ## F, M ## F))
219 #define N2FPU_CMP_SF(code) N2FPU_CMP_DEF (code, 0, s, S)
220 #define N2FPU_CMP_DF(code) N2FPU_CMP_DEF (code, N2F_DF, d, D)
221
222 /* The order of definition needs to be maintained consistent with
223 enum n2fpu_code in nios2-opts.h. */
224 struct nios2_fpu_insn_info nios2_fpu_insn[] =
225 {
226 /* Single precision instructions. */
227 N2FPU_INSN_SF (add, 3, 0),
228 N2FPU_INSN_SF (sub, 3, 0),
229 N2FPU_INSN_SF (mul, 3, 0),
230 N2FPU_INSN_SF (div, 3, 0),
231 /* Due to textual difference between min/max and smin/smax. */
232 N2FPU_INSN_DEF (min, smin, 3, N2F_FINITE, s, S),
233 N2FPU_INSN_DEF (max, smax, 3, N2F_FINITE, s, S),
234 N2FPU_INSN_SF (neg, 2, 0),
235 N2FPU_INSN_SF (abs, 2, 0),
236 N2FPU_INSN_SF (sqrt, 2, 0),
237 N2FPU_INSN_SF (sin, 2, N2F_UNSAFE),
238 N2FPU_INSN_SF (cos, 2, N2F_UNSAFE),
239 N2FPU_INSN_SF (tan, 2, N2F_UNSAFE),
240 N2FPU_INSN_SF (atan, 2, N2F_UNSAFE),
241 N2FPU_INSN_SF (exp, 2, N2F_UNSAFE),
242 N2FPU_INSN_SF (log, 2, N2F_UNSAFE),
243 /* Single precision compares. */
244 N2FPU_CMP_SF (eq), N2FPU_CMP_SF (ne),
245 N2FPU_CMP_SF (lt), N2FPU_CMP_SF (le),
246 N2FPU_CMP_SF (gt), N2FPU_CMP_SF (ge),
247
248 /* Double precision instructions. */
249 N2FPU_INSN_DF (add, 3, 0),
250 N2FPU_INSN_DF (sub, 3, 0),
251 N2FPU_INSN_DF (mul, 3, 0),
252 N2FPU_INSN_DF (div, 3, 0),
253 /* Due to textual difference between min/max and smin/smax. */
254 N2FPU_INSN_DEF (min, smin, 3, N2F_FINITE, d, D),
255 N2FPU_INSN_DEF (max, smax, 3, N2F_FINITE, d, D),
256 N2FPU_INSN_DF (neg, 2, 0),
257 N2FPU_INSN_DF (abs, 2, 0),
258 N2FPU_INSN_DF (sqrt, 2, 0),
259 N2FPU_INSN_DF (sin, 2, N2F_UNSAFE),
260 N2FPU_INSN_DF (cos, 2, N2F_UNSAFE),
261 N2FPU_INSN_DF (tan, 2, N2F_UNSAFE),
262 N2FPU_INSN_DF (atan, 2, N2F_UNSAFE),
263 N2FPU_INSN_DF (exp, 2, N2F_UNSAFE),
264 N2FPU_INSN_DF (log, 2, N2F_UNSAFE),
265 /* Double precision compares. */
266 N2FPU_CMP_DF (eq), N2FPU_CMP_DF (ne),
267 N2FPU_CMP_DF (lt), N2FPU_CMP_DF (le),
268 N2FPU_CMP_DF (gt), N2FPU_CMP_DF (ge),
269
270 /* Conversion instructions. */
271 N2FPU_INSN_DEF_BASE (floatis, 2, 0, floatsisf2, (SF, SI)),
272 N2FPU_INSN_DEF_BASE (floatus, 2, 0, floatunssisf2, (SF, UI)),
273 N2FPU_INSN_DEF_BASE (floatid, 2, 0, floatsidf2, (DF, SI)),
274 N2FPU_INSN_DEF_BASE (floatud, 2, 0, floatunssidf2, (DF, UI)),
275 N2FPU_INSN_DEF_BASE (fixsi, 2, 0, fix_truncsfsi2, (SI, SF)),
276 N2FPU_INSN_DEF_BASE (fixsu, 2, 0, fixuns_truncsfsi2, (UI, SF)),
277 N2FPU_INSN_DEF_BASE (fixdi, 2, 0, fix_truncdfsi2, (SI, DF)),
278 N2FPU_INSN_DEF_BASE (fixdu, 2, 0, fixuns_truncdfsi2, (UI, DF)),
279 N2FPU_INSN_DEF_BASE (fextsd, 2, 0, extendsfdf2, (DF, SF)),
280 N2FPU_INSN_DEF_BASE (ftruncds, 2, 0, truncdfsf2, (SF, DF)),
281
282 /* X, Y access instructions. */
283 N2FPU_INSN_DEF_BASE (fwrx, 2, N2F_DFREQ, nios2_fwrx, (VOID, DF)),
284 N2FPU_INSN_DEF_BASE (fwry, 2, N2F_DFREQ, nios2_fwry, (VOID, SF)),
285 N2FPU_INSN_DEF_BASE (frdxlo, 1, N2F_DFREQ, nios2_frdxlo, (SF)),
286 N2FPU_INSN_DEF_BASE (frdxhi, 1, N2F_DFREQ, nios2_frdxhi, (SF)),
287 N2FPU_INSN_DEF_BASE (frdy, 1, N2F_DFREQ, nios2_frdy, (SF))
288 };
289
290 /* Some macros for ease of access. */
291 #define N2FPU(code) nios2_fpu_insn[(int) code]
292 #define N2FPU_ENABLED_P(code) (N2FPU_N(code) >= 0)
293 #define N2FPU_N(code) (*N2FPU(code).optvar)
294 #define N2FPU_NAME(code) (N2FPU(code).name)
295 #define N2FPU_ICODE(code) (N2FPU(code).icode)
296 #define N2FPU_FTCODE(code) (N2FPU(code).ftcode)
297 #define N2FPU_FINITE_P(code) (N2FPU(code).flags & N2F_FINITE)
298 #define N2FPU_UNSAFE_P(code) (N2FPU(code).flags & N2F_UNSAFE)
299 #define N2FPU_DOUBLE_P(code) (N2FPU(code).flags & N2F_DF)
300 #define N2FPU_DOUBLE_REQUIRED_P(code) (N2FPU(code).flags & N2F_DFREQ)
301
302 /* Same as above, but for cases where using only the op part is shorter. */
303 #define N2FPU_OP(op) N2FPU(n2fpu_ ## op)
304 #define N2FPU_OP_NAME(op) N2FPU_NAME(n2fpu_ ## op)
305 #define N2FPU_OP_ENABLED_P(op) N2FPU_ENABLED_P(n2fpu_ ## op)
306
307 /* Export the FPU insn enabled predicate to nios2.md. */
308 bool
309 nios2_fpu_insn_enabled (enum n2fpu_code code)
310 {
311 return N2FPU_ENABLED_P (code);
312 }
313
314 /* Return true if COND comparison for mode MODE is enabled under current
315 settings. */
316
317 static bool
318 nios2_fpu_compare_enabled (enum rtx_code cond, enum machine_mode mode)
319 {
320 if (mode == SFmode)
321 switch (cond)
322 {
323 case EQ: return N2FPU_OP_ENABLED_P (fcmpeqs);
324 case NE: return N2FPU_OP_ENABLED_P (fcmpnes);
325 case GT: return N2FPU_OP_ENABLED_P (fcmpgts);
326 case GE: return N2FPU_OP_ENABLED_P (fcmpges);
327 case LT: return N2FPU_OP_ENABLED_P (fcmplts);
328 case LE: return N2FPU_OP_ENABLED_P (fcmples);
329 default: break;
330 }
331 else if (mode == DFmode)
332 switch (cond)
333 {
334 case EQ: return N2FPU_OP_ENABLED_P (fcmpeqd);
335 case NE: return N2FPU_OP_ENABLED_P (fcmpned);
336 case GT: return N2FPU_OP_ENABLED_P (fcmpgtd);
337 case GE: return N2FPU_OP_ENABLED_P (fcmpged);
338 case LT: return N2FPU_OP_ENABLED_P (fcmpltd);
339 case LE: return N2FPU_OP_ENABLED_P (fcmpled);
340 default: break;
341 }
342 return false;
343 }
344
345 /* Stack layout and calling conventions. */
346
347 #define NIOS2_STACK_ALIGN(LOC) \
348 (((LOC) + ((PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) - 1)) \
349 & ~((PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) - 1))
350
351 /* Return the bytes needed to compute the frame pointer from the current
352 stack pointer. */
353 static int
354 nios2_compute_frame_layout (void)
355 {
356 unsigned int regno;
357 unsigned int save_mask = 0;
358 int total_size;
359 int var_size;
360 int out_args_size;
361 int save_reg_size;
362
363 if (cfun->machine->initialized)
364 return cfun->machine->total_size;
365
366 var_size = NIOS2_STACK_ALIGN (get_frame_size ());
367 out_args_size = NIOS2_STACK_ALIGN (crtl->outgoing_args_size);
368 total_size = var_size + out_args_size;
369
370 /* Calculate space needed for gp registers. */
371 save_reg_size = 0;
372 for (regno = 0; regno <= LAST_GP_REG; regno++)
373 if (prologue_saved_reg_p (regno))
374 {
375 save_mask |= 1 << regno;
376 save_reg_size += 4;
377 }
378
379 /* If we call eh_return, we need to save the EH data registers. */
380 if (crtl->calls_eh_return)
381 {
382 unsigned i;
383 unsigned r;
384
385 for (i = 0; (r = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++)
386 if (!(save_mask & (1 << r)))
387 {
388 save_mask |= 1 << r;
389 save_reg_size += 4;
390 }
391 }
392
393 save_reg_size = NIOS2_STACK_ALIGN (save_reg_size);
394 total_size += save_reg_size;
395 total_size += NIOS2_STACK_ALIGN (crtl->args.pretend_args_size);
396
397 /* Save other computed information. */
398 cfun->machine->save_mask = save_mask;
399 cfun->machine->total_size = total_size;
400 cfun->machine->var_size = var_size;
401 cfun->machine->args_size = out_args_size;
402 cfun->machine->save_reg_size = save_reg_size;
403 cfun->machine->initialized = reload_completed;
404 cfun->machine->save_regs_offset = out_args_size + var_size;
405
406 return total_size;
407 }
408
409 /* Generate save/restore of register REGNO at SP + OFFSET. Used by the
410 prologue/epilogue expand routines. */
411 static void
412 save_reg (int regno, unsigned offset)
413 {
414 rtx reg = gen_rtx_REG (SImode, regno);
415 rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
416 gen_int_mode (offset, Pmode));
417 rtx insn = emit_move_insn (gen_frame_mem (Pmode, addr), reg);
418 RTX_FRAME_RELATED_P (insn) = 1;
419 }
420
421 static void
422 restore_reg (int regno, unsigned offset)
423 {
424 rtx reg = gen_rtx_REG (SImode, regno);
425 rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
426 gen_int_mode (offset, Pmode));
427 rtx insn = emit_move_insn (reg, gen_frame_mem (Pmode, addr));
428 /* Tag epilogue unwind note. */
429 add_reg_note (insn, REG_CFA_RESTORE, reg);
430 RTX_FRAME_RELATED_P (insn) = 1;
431 }
432
433 /* Emit conditional trap for checking stack limit. */
434 static void
435 nios2_emit_stack_limit_check (void)
436 {
437 if (REG_P (stack_limit_rtx))
438 emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode, stack_pointer_rtx,
439 stack_limit_rtx),
440 stack_pointer_rtx, stack_limit_rtx, GEN_INT (3)));
441 else
442 sorry ("only register based stack limit is supported");
443 }
444
445 /* Temp regno used inside prologue/epilogue. */
446 #define TEMP_REG_NUM 8
447
448 void
449 nios2_expand_prologue (void)
450 {
451 unsigned int regno;
452 int total_frame_size, save_offset;
453 int sp_offset; /* offset from base_reg to final stack value. */
454 int fp_offset; /* offset from base_reg to final fp value. */
455 rtx insn;
456
457 total_frame_size = nios2_compute_frame_layout ();
458
459 if (flag_stack_usage_info)
460 current_function_static_stack_size = total_frame_size;
461
462 /* Decrement the stack pointer. */
463 if (!SMALL_INT (total_frame_size))
464 {
465 /* We need an intermediary point, this will point at the spill block. */
466 insn = emit_insn
467 (gen_add2_insn (stack_pointer_rtx,
468 gen_int_mode (cfun->machine->save_regs_offset
469 - total_frame_size, Pmode)));
470 RTX_FRAME_RELATED_P (insn) = 1;
471
472 fp_offset = 0;
473 sp_offset = -cfun->machine->save_regs_offset;
474 }
475 else if (total_frame_size)
476 {
477 insn = emit_insn (gen_add2_insn (stack_pointer_rtx,
478 gen_int_mode (-total_frame_size,
479 Pmode)));
480 RTX_FRAME_RELATED_P (insn) = 1;
481 fp_offset = cfun->machine->save_regs_offset;
482 sp_offset = 0;
483 }
484 else
485 fp_offset = sp_offset = 0;
486
487 if (crtl->limit_stack)
488 nios2_emit_stack_limit_check ();
489
490 save_offset = fp_offset + cfun->machine->save_reg_size;
491
492 for (regno = LAST_GP_REG; regno > 0; regno--)
493 if (cfun->machine->save_mask & (1 << regno))
494 {
495 save_offset -= 4;
496 save_reg (regno, save_offset);
497 }
498
499 if (frame_pointer_needed)
500 {
501 insn = emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
502 stack_pointer_rtx,
503 gen_int_mode (fp_offset, Pmode)));
504 RTX_FRAME_RELATED_P (insn) = 1;
505 }
506
507 if (sp_offset)
508 {
509 rtx sp_adjust
510 = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
511 plus_constant (Pmode, stack_pointer_rtx, sp_offset));
512 if (SMALL_INT (sp_offset))
513 insn = emit_insn (sp_adjust);
514 else
515 {
516 rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
517 emit_move_insn (tmp, gen_int_mode (sp_offset, Pmode));
518 insn = emit_insn (gen_add2_insn (stack_pointer_rtx, tmp));
519 /* Attach the sp_adjust as a note indicating what happened. */
520 add_reg_note (insn, REG_FRAME_RELATED_EXPR, sp_adjust);
521 }
522 RTX_FRAME_RELATED_P (insn) = 1;
523
524 if (crtl->limit_stack)
525 nios2_emit_stack_limit_check ();
526 }
527
528 /* Load the PIC register if needed. */
529 if (crtl->uses_pic_offset_table)
530 nios2_load_pic_register ();
531
532 /* If we are profiling, make sure no instructions are scheduled before
533 the call to mcount. */
534 if (crtl->profile)
535 emit_insn (gen_blockage ());
536 }
537
538 void
539 nios2_expand_epilogue (bool sibcall_p)
540 {
541 rtx insn, cfa_adj;
542 int total_frame_size;
543 int sp_adjust, save_offset;
544 unsigned int regno;
545
546 if (!sibcall_p && nios2_can_use_return_insn ())
547 {
548 emit_jump_insn (gen_return ());
549 return;
550 }
551
552 emit_insn (gen_blockage ());
553
554 total_frame_size = nios2_compute_frame_layout ();
555 if (frame_pointer_needed)
556 {
557 /* Recover the stack pointer. */
558 insn = emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
559 cfa_adj = plus_constant (Pmode, stack_pointer_rtx,
560 (total_frame_size
561 - cfun->machine->save_regs_offset));
562 add_reg_note (insn, REG_CFA_DEF_CFA, cfa_adj);
563 RTX_FRAME_RELATED_P (insn) = 1;
564
565 save_offset = 0;
566 sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
567 }
568 else if (!SMALL_INT (total_frame_size))
569 {
570 rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
571 emit_move_insn (tmp, gen_int_mode (cfun->machine->save_regs_offset,
572 Pmode));
573 insn = emit_insn (gen_add2_insn (stack_pointer_rtx, tmp));
574 cfa_adj = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
575 plus_constant (Pmode, stack_pointer_rtx,
576 cfun->machine->save_regs_offset));
577 add_reg_note (insn, REG_CFA_ADJUST_CFA, cfa_adj);
578 RTX_FRAME_RELATED_P (insn) = 1;
579 save_offset = 0;
580 sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
581 }
582 else
583 {
584 save_offset = cfun->machine->save_regs_offset;
585 sp_adjust = total_frame_size;
586 }
587
588 save_offset += cfun->machine->save_reg_size;
589
590 for (regno = LAST_GP_REG; regno > 0; regno--)
591 if (cfun->machine->save_mask & (1 << regno))
592 {
593 save_offset -= 4;
594 restore_reg (regno, save_offset);
595 }
596
597 if (sp_adjust)
598 {
599 insn = emit_insn (gen_add2_insn (stack_pointer_rtx,
600 gen_int_mode (sp_adjust, Pmode)));
601 cfa_adj = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
602 plus_constant (Pmode, stack_pointer_rtx,
603 sp_adjust));
604 add_reg_note (insn, REG_CFA_ADJUST_CFA, cfa_adj);
605 RTX_FRAME_RELATED_P (insn) = 1;
606 }
607
608 /* Add in the __builtin_eh_return stack adjustment. */
609 if (crtl->calls_eh_return)
610 emit_insn (gen_add2_insn (stack_pointer_rtx, EH_RETURN_STACKADJ_RTX));
611
612 if (!sibcall_p)
613 emit_jump_insn (gen_simple_return ());
614 }
615
616 /* Implement RETURN_ADDR_RTX. Note, we do not support moving
617 back to a previous frame. */
618 rtx
619 nios2_get_return_address (int count)
620 {
621 if (count != 0)
622 return const0_rtx;
623
624 return get_hard_reg_initial_val (Pmode, RA_REGNO);
625 }
626
627 /* Emit code to change the current function's return address to
628 ADDRESS. SCRATCH is available as a scratch register, if needed.
629 ADDRESS and SCRATCH are both word-mode GPRs. */
630 void
631 nios2_set_return_address (rtx address, rtx scratch)
632 {
633 nios2_compute_frame_layout ();
634 if (cfun->machine->save_mask & (1 << RA_REGNO))
635 {
636 unsigned offset = cfun->machine->save_reg_size - 4;
637 rtx base;
638
639 if (frame_pointer_needed)
640 base = hard_frame_pointer_rtx;
641 else
642 {
643 base = stack_pointer_rtx;
644 offset += cfun->machine->save_regs_offset;
645
646 if (!SMALL_INT (offset))
647 {
648 emit_move_insn (scratch, gen_int_mode (offset, Pmode));
649 emit_insn (gen_add2_insn (scratch, base));
650 base = scratch;
651 offset = 0;
652 }
653 }
654 if (offset)
655 base = plus_constant (Pmode, base, offset);
656 emit_move_insn (gen_rtx_MEM (Pmode, base), address);
657 }
658 else
659 emit_move_insn (gen_rtx_REG (Pmode, RA_REGNO), address);
660 }
661
662 /* Implement FUNCTION_PROFILER macro. */
663 void
664 nios2_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
665 {
666 fprintf (file, "\tmov\tr8, ra\n");
667 if (flag_pic)
668 {
669 fprintf (file, "\tnextpc\tr2\n");
670 fprintf (file, "\t1: movhi\tr3, %%hiadj(_GLOBAL_OFFSET_TABLE_ - 1b)\n");
671 fprintf (file, "\taddi\tr3, r3, %%lo(_GLOBAL_OFFSET_TABLE_ - 1b)\n");
672 fprintf (file, "\tadd\tr2, r2, r3\n");
673 fprintf (file, "\tldw\tr2, %%call(_mcount)(r2)\n");
674 fprintf (file, "\tcallr\tr2\n");
675 }
676 else
677 fprintf (file, "\tcall\t_mcount\n");
678 fprintf (file, "\tmov\tra, r8\n");
679 }
680
681 /* Dump stack layout. */
682 static void
683 nios2_dump_frame_layout (FILE *file)
684 {
685 fprintf (file, "\t%s Current Frame Info\n", ASM_COMMENT_START);
686 fprintf (file, "\t%s total_size = %d\n", ASM_COMMENT_START,
687 cfun->machine->total_size);
688 fprintf (file, "\t%s var_size = %d\n", ASM_COMMENT_START,
689 cfun->machine->var_size);
690 fprintf (file, "\t%s args_size = %d\n", ASM_COMMENT_START,
691 cfun->machine->args_size);
692 fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START,
693 cfun->machine->save_reg_size);
694 fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START,
695 cfun->machine->initialized);
696 fprintf (file, "\t%s save_regs_offset = %d\n", ASM_COMMENT_START,
697 cfun->machine->save_regs_offset);
698 fprintf (file, "\t%s is_leaf = %d\n", ASM_COMMENT_START,
699 crtl->is_leaf);
700 fprintf (file, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START,
701 frame_pointer_needed);
702 fprintf (file, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START,
703 crtl->args.pretend_args_size);
704 }
705
706 /* Return true if REGNO should be saved in the prologue. */
707 static bool
708 prologue_saved_reg_p (unsigned regno)
709 {
710 gcc_assert (GP_REG_P (regno));
711
712 if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
713 return true;
714
715 if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
716 return true;
717
718 if (regno == PIC_OFFSET_TABLE_REGNUM && crtl->uses_pic_offset_table)
719 return true;
720
721 if (regno == RA_REGNO && df_regs_ever_live_p (RA_REGNO))
722 return true;
723
724 return false;
725 }
726
727 /* Implement TARGET_CAN_ELIMINATE. */
728 static bool
729 nios2_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
730 {
731 if (to == STACK_POINTER_REGNUM)
732 return !frame_pointer_needed;
733 return true;
734 }
735
736 /* Implement INITIAL_ELIMINATION_OFFSET macro. */
737 int
738 nios2_initial_elimination_offset (int from, int to)
739 {
740 int offset;
741
742 nios2_compute_frame_layout ();
743
744 /* Set OFFSET to the offset from the stack pointer. */
745 switch (from)
746 {
747 case FRAME_POINTER_REGNUM:
748 offset = cfun->machine->args_size;
749 break;
750
751 case ARG_POINTER_REGNUM:
752 offset = cfun->machine->total_size;
753 offset -= crtl->args.pretend_args_size;
754 break;
755
756 default:
757 gcc_unreachable ();
758 }
759
760 /* If we are asked for the frame pointer offset, then adjust OFFSET
761 by the offset from the frame pointer to the stack pointer. */
762 if (to == HARD_FRAME_POINTER_REGNUM)
763 offset -= cfun->machine->save_regs_offset;
764
765 return offset;
766 }
767
768 /* Return nonzero if this function is known to have a null epilogue.
769 This allows the optimizer to omit jumps to jumps if no stack
770 was created. */
771 int
772 nios2_can_use_return_insn (void)
773 {
774 if (!reload_completed || crtl->profile)
775 return 0;
776
777 return nios2_compute_frame_layout () == 0;
778 }
779
780 \f
781 /* Check and signal some warnings/errors on FPU insn options. */
782 static void
783 nios2_custom_check_insns (void)
784 {
785 unsigned int i, j;
786 bool errors = false;
787
788 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
789 if (N2FPU_ENABLED_P (i) && N2FPU_DOUBLE_P (i))
790 {
791 for (j = 0; j < ARRAY_SIZE (nios2_fpu_insn); j++)
792 if (N2FPU_DOUBLE_REQUIRED_P (j) && ! N2FPU_ENABLED_P (j))
793 {
794 error ("switch %<-mcustom-%s%> is required for double "
795 "precision floating point", N2FPU_NAME (j));
796 errors = true;
797 }
798 break;
799 }
800
801 /* Warn if the user has certain exotic operations that won't get used
802 without -funsafe-math-optimizations. See expand_builtin () in
803 builtins.c. */
804 if (!flag_unsafe_math_optimizations)
805 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
806 if (N2FPU_ENABLED_P (i) && N2FPU_UNSAFE_P (i))
807 warning (0, "switch %<-mcustom-%s%> has no effect unless "
808 "-funsafe-math-optimizations is specified", N2FPU_NAME (i));
809
810 /* Warn if the user is trying to use -mcustom-fmins et. al, that won't
811 get used without -ffinite-math-only. See fold_builtin_fmin_fmax ()
812 in builtins.c. */
813 if (!flag_finite_math_only)
814 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
815 if (N2FPU_ENABLED_P (i) && N2FPU_FINITE_P (i))
816 warning (0, "switch %<-mcustom-%s%> has no effect unless "
817 "-ffinite-math-only is specified", N2FPU_NAME (i));
818
819 if (errors || custom_code_conflict)
820 fatal_error ("conflicting use of -mcustom switches, target attributes, "
821 "and/or __builtin_custom_ functions");
822 }
823
824 static void
825 nios2_set_fpu_custom_code (enum n2fpu_code code, int n, bool override_p)
826 {
827 if (override_p || N2FPU_N (code) == -1)
828 N2FPU_N (code) = n;
829 nios2_register_custom_code (n, CCS_FPU, (int) code);
830 }
831
832 /* Type to represent a standard FPU config. */
833 struct nios2_fpu_config
834 {
835 const char *name;
836 bool set_sp_constants;
837 int code[n2fpu_code_num];
838 };
839
840 #define NIOS2_FPU_CONFIG_NUM 3
841 static struct nios2_fpu_config custom_fpu_config[NIOS2_FPU_CONFIG_NUM];
842
843 static void
844 nios2_init_fpu_configs (void)
845 {
846 struct nios2_fpu_config* cfg;
847 int i = 0;
848 #define NEXT_FPU_CONFIG \
849 do { \
850 cfg = &custom_fpu_config[i++]; \
851 memset (cfg, -1, sizeof (struct nios2_fpu_config));\
852 } while (0)
853
854 NEXT_FPU_CONFIG;
855 cfg->name = "60-1";
856 cfg->set_sp_constants = true;
857 cfg->code[n2fpu_fmuls] = 252;
858 cfg->code[n2fpu_fadds] = 253;
859 cfg->code[n2fpu_fsubs] = 254;
860
861 NEXT_FPU_CONFIG;
862 cfg->name = "60-2";
863 cfg->set_sp_constants = true;
864 cfg->code[n2fpu_fmuls] = 252;
865 cfg->code[n2fpu_fadds] = 253;
866 cfg->code[n2fpu_fsubs] = 254;
867 cfg->code[n2fpu_fdivs] = 255;
868
869 NEXT_FPU_CONFIG;
870 cfg->name = "72-3";
871 cfg->set_sp_constants = true;
872 cfg->code[n2fpu_floatus] = 243;
873 cfg->code[n2fpu_fixsi] = 244;
874 cfg->code[n2fpu_floatis] = 245;
875 cfg->code[n2fpu_fcmpgts] = 246;
876 cfg->code[n2fpu_fcmples] = 249;
877 cfg->code[n2fpu_fcmpeqs] = 250;
878 cfg->code[n2fpu_fcmpnes] = 251;
879 cfg->code[n2fpu_fmuls] = 252;
880 cfg->code[n2fpu_fadds] = 253;
881 cfg->code[n2fpu_fsubs] = 254;
882 cfg->code[n2fpu_fdivs] = 255;
883
884 #undef NEXT_FPU_CONFIG
885 gcc_assert (i == NIOS2_FPU_CONFIG_NUM);
886 }
887
888 static struct nios2_fpu_config *
889 nios2_match_custom_fpu_cfg (const char *cfgname, const char *endp)
890 {
891 int i;
892 for (i = 0; i < NIOS2_FPU_CONFIG_NUM; i++)
893 {
894 bool match = !(endp != NULL
895 ? strncmp (custom_fpu_config[i].name, cfgname,
896 endp - cfgname)
897 : strcmp (custom_fpu_config[i].name, cfgname));
898 if (match)
899 return &custom_fpu_config[i];
900 }
901 return NULL;
902 }
903
904 /* Use CFGNAME to lookup FPU config, ENDP if not NULL marks end of string.
905 OVERRIDE is true if loaded config codes should overwrite current state. */
906 static void
907 nios2_handle_custom_fpu_cfg (const char *cfgname, const char *endp,
908 bool override)
909 {
910 struct nios2_fpu_config *cfg = nios2_match_custom_fpu_cfg (cfgname, endp);
911 if (cfg)
912 {
913 unsigned int i;
914 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
915 if (cfg->code[i] >= 0)
916 nios2_set_fpu_custom_code ((enum n2fpu_code) i, cfg->code[i],
917 override);
918 if (cfg->set_sp_constants)
919 flag_single_precision_constant = 1;
920 }
921 else
922 warning (0, "ignoring unrecognized switch %<-mcustom-fpu-cfg%> "
923 "value %<%s%>", cfg);
924
925 /* Guard against errors in the standard configurations. */
926 nios2_custom_check_insns ();
927 }
928
929 /* Check individual FPU insn options, and register custom code. */
930 static void
931 nios2_handle_custom_fpu_insn_option (int fpu_insn_index)
932 {
933 int param = N2FPU_N (fpu_insn_index);
934
935 if (0 <= param && param <= 255)
936 nios2_register_custom_code (param, CCS_FPU, fpu_insn_index);
937
938 /* Valid values are 0-255, but also allow -1 so that the
939 -mno-custom-<opt> switches work. */
940 else if (param != -1)
941 error ("switch %<-mcustom-%s%> value %d must be between 0 and 255",
942 N2FPU_NAME (fpu_insn_index), param);
943 }
944
945 /* Allocate a chunk of memory for per-function machine-dependent data. */
946 static struct machine_function *
947 nios2_init_machine_status (void)
948 {
949 return ggc_alloc_cleared_machine_function ();
950 }
951
952 /* Implement TARGET_OPTION_OVERRIDE. */
953 static void
954 nios2_option_override (void)
955 {
956 unsigned int i;
957
958 #ifdef SUBTARGET_OVERRIDE_OPTIONS
959 SUBTARGET_OVERRIDE_OPTIONS;
960 #endif
961
962 /* Check for unsupported options. */
963 if (flag_pic && !TARGET_LINUX_ABI)
964 sorry ("position-independent code requires the Linux ABI");
965
966 /* Function to allocate machine-dependent function status. */
967 init_machine_status = &nios2_init_machine_status;
968
969 nios2_section_threshold
970 = (global_options_set.x_g_switch_value
971 ? g_switch_value : NIOS2_DEFAULT_GVALUE);
972
973 /* Default to -mgpopt unless -fpic or -fPIC. */
974 if (TARGET_GPOPT == -1 && flag_pic)
975 TARGET_GPOPT = 0;
976
977 /* If we don't have mul, we don't have mulx either! */
978 if (!TARGET_HAS_MUL && TARGET_HAS_MULX)
979 target_flags &= ~MASK_HAS_MULX;
980
981 /* Initialize default FPU configurations. */
982 nios2_init_fpu_configs ();
983
984 /* Set up default handling for floating point custom instructions.
985
986 Putting things in this order means that the -mcustom-fpu-cfg=
987 switch will always be overridden by individual -mcustom-fadds=
988 switches, regardless of the order in which they were specified
989 on the command line.
990
991 This behavior of prioritization of individual -mcustom-<insn>=
992 options before the -mcustom-fpu-cfg= switch is maintained for
993 compatibility. */
994 if (nios2_custom_fpu_cfg_string && *nios2_custom_fpu_cfg_string)
995 nios2_handle_custom_fpu_cfg (nios2_custom_fpu_cfg_string, NULL, false);
996
997 /* Handle options for individual FPU insns. */
998 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
999 nios2_handle_custom_fpu_insn_option (i);
1000
1001 nios2_custom_check_insns ();
1002
1003 /* Save the initial options in case the user does function specific
1004 options. */
1005 target_option_default_node = target_option_current_node
1006 = build_target_option_node (&global_options);
1007 }
1008
1009 \f
1010 /* Return true if CST is a constant within range of movi/movui/movhi. */
1011 static bool
1012 nios2_simple_const_p (const_rtx cst)
1013 {
1014 HOST_WIDE_INT val = INTVAL (cst);
1015 return SMALL_INT (val) || SMALL_INT_UNSIGNED (val) || UPPER16_INT (val);
1016 }
1017
1018 /* Compute a (partial) cost for rtx X. Return true if the complete
1019 cost has been computed, and false if subexpressions should be
1020 scanned. In either case, *TOTAL contains the cost result. */
1021 static bool
1022 nios2_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
1023 int opno ATTRIBUTE_UNUSED,
1024 int *total, bool speed ATTRIBUTE_UNUSED)
1025 {
1026 switch (code)
1027 {
1028 case CONST_INT:
1029 if (INTVAL (x) == 0)
1030 {
1031 *total = COSTS_N_INSNS (0);
1032 return true;
1033 }
1034 else if (nios2_simple_const_p (x))
1035 {
1036 *total = COSTS_N_INSNS (2);
1037 return true;
1038 }
1039 else
1040 {
1041 *total = COSTS_N_INSNS (4);
1042 return true;
1043 }
1044
1045 case LABEL_REF:
1046 case SYMBOL_REF:
1047 case CONST:
1048 case CONST_DOUBLE:
1049 {
1050 *total = COSTS_N_INSNS (4);
1051 return true;
1052 }
1053
1054 case AND:
1055 {
1056 /* Recognize 'nor' insn pattern. */
1057 if (GET_CODE (XEXP (x, 0)) == NOT
1058 && GET_CODE (XEXP (x, 1)) == NOT)
1059 {
1060 *total = COSTS_N_INSNS (1);
1061 return true;
1062 }
1063 return false;
1064 }
1065
1066 case MULT:
1067 {
1068 *total = COSTS_N_INSNS (1);
1069 return false;
1070 }
1071 case SIGN_EXTEND:
1072 {
1073 *total = COSTS_N_INSNS (3);
1074 return false;
1075 }
1076 case ZERO_EXTEND:
1077 {
1078 *total = COSTS_N_INSNS (1);
1079 return false;
1080 }
1081
1082 default:
1083 return false;
1084 }
1085 }
1086
1087 /* Implement TARGET_PREFERRED_RELOAD_CLASS. */
1088 static reg_class_t
1089 nios2_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t regclass)
1090 {
1091 return regclass == NO_REGS ? GENERAL_REGS : regclass;
1092 }
1093
1094 /* Emit a call to __tls_get_addr. TI is the argument to this function.
1095 RET is an RTX for the return value location. The entire insn sequence
1096 is returned. */
1097 static GTY(()) rtx nios2_tls_symbol;
1098
1099 static rtx
1100 nios2_call_tls_get_addr (rtx ti)
1101 {
1102 rtx arg = gen_rtx_REG (Pmode, FIRST_ARG_REGNO);
1103 rtx ret = gen_rtx_REG (Pmode, FIRST_RETVAL_REGNO);
1104 rtx fn, insn;
1105
1106 if (!nios2_tls_symbol)
1107 nios2_tls_symbol = init_one_libfunc ("__tls_get_addr");
1108
1109 emit_move_insn (arg, ti);
1110 fn = gen_rtx_MEM (QImode, nios2_tls_symbol);
1111 insn = emit_call_insn (gen_call_value (ret, fn, const0_rtx));
1112 RTL_CONST_CALL_P (insn) = 1;
1113 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), ret);
1114 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), arg);
1115
1116 return ret;
1117 }
1118
1119 static rtx
1120 nios2_unspec_address (rtx loc, rtx base_reg, int unspec)
1121 {
1122 rtx unspec_offset =
1123 gen_rtx_CONST (Pmode, gen_rtx_UNSPEC (Pmode, gen_rtvec (1, loc),
1124 unspec));
1125 return gen_rtx_PLUS (Pmode, base_reg, unspec_offset);
1126 }
1127
1128 static rtx
1129 nios2_got_address (rtx loc, int unspec)
1130 {
1131 crtl->uses_pic_offset_table = 1;
1132 return nios2_unspec_address (loc, pic_offset_table_rtx, unspec);
1133 }
1134
1135 /* Generate the code to access LOC, a thread local SYMBOL_REF. The
1136 return value will be a valid address and move_operand (either a REG
1137 or a LO_SUM). */
1138 static rtx
1139 nios2_legitimize_tls_address (rtx loc)
1140 {
1141 rtx tmp, mem, tp;
1142 enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
1143
1144 switch (model)
1145 {
1146 case TLS_MODEL_GLOBAL_DYNAMIC:
1147 tmp = gen_reg_rtx (Pmode);
1148 emit_move_insn (tmp, nios2_got_address (loc, UNSPEC_ADD_TLS_GD));
1149 return nios2_call_tls_get_addr (tmp);
1150
1151 case TLS_MODEL_LOCAL_DYNAMIC:
1152 tmp = gen_reg_rtx (Pmode);
1153 emit_move_insn (tmp, nios2_got_address (loc, UNSPEC_ADD_TLS_LDM));
1154 return nios2_unspec_address (loc, nios2_call_tls_get_addr (tmp),
1155 UNSPEC_ADD_TLS_LDO);
1156
1157 case TLS_MODEL_INITIAL_EXEC:
1158 tmp = gen_reg_rtx (Pmode);
1159 mem = gen_const_mem (Pmode, nios2_got_address (loc, UNSPEC_LOAD_TLS_IE));
1160 emit_move_insn (tmp, mem);
1161 tp = gen_rtx_REG (Pmode, TP_REGNO);
1162 return gen_rtx_PLUS (Pmode, tp, tmp);
1163
1164 case TLS_MODEL_LOCAL_EXEC:
1165 tp = gen_rtx_REG (Pmode, TP_REGNO);
1166 return nios2_unspec_address (loc, tp, UNSPEC_ADD_TLS_LE);
1167
1168 default:
1169 gcc_unreachable ();
1170 }
1171 }
1172
1173 /* Divide Support
1174
1175 If -O3 is used, we want to output a table lookup for
1176 divides between small numbers (both num and den >= 0
1177 and < 0x10). The overhead of this method in the worst
1178 case is 40 bytes in the text section (10 insns) and
1179 256 bytes in the data section. Additional divides do
1180 not incur additional penalties in the data section.
1181
1182 Code speed is improved for small divides by about 5x
1183 when using this method in the worse case (~9 cycles
1184 vs ~45). And in the worst case divides not within the
1185 table are penalized by about 10% (~5 cycles vs ~45).
1186 However in the typical case the penalty is not as bad
1187 because doing the long divide in only 45 cycles is
1188 quite optimistic.
1189
1190 ??? would be nice to have some benchmarks other
1191 than Dhrystone to back this up.
1192
1193 This bit of expansion is to create this instruction
1194 sequence as rtl.
1195 or $8, $4, $5
1196 slli $9, $4, 4
1197 cmpgeui $3, $8, 16
1198 beq $3, $0, .L3
1199 or $10, $9, $5
1200 add $12, $11, divide_table
1201 ldbu $2, 0($12)
1202 br .L1
1203 .L3:
1204 call slow_div
1205 .L1:
1206 # continue here with result in $2
1207
1208 ??? Ideally I would like the libcall block to contain all
1209 of this code, but I don't know how to do that. What it
1210 means is that if the divide can be eliminated, it may not
1211 completely disappear.
1212
1213 ??? The __divsi3_table label should ideally be moved out
1214 of this block and into a global. If it is placed into the
1215 sdata section we can save even more cycles by doing things
1216 gp relative. */
1217 void
1218 nios2_emit_expensive_div (rtx *operands, enum machine_mode mode)
1219 {
1220 rtx or_result, shift_left_result;
1221 rtx lookup_value;
1222 rtx lab1, lab3;
1223 rtx insns;
1224 rtx libfunc;
1225 rtx final_result;
1226 rtx tmp;
1227 rtx table;
1228
1229 /* It may look a little generic, but only SImode is supported for now. */
1230 gcc_assert (mode == SImode);
1231 libfunc = optab_libfunc (sdiv_optab, SImode);
1232
1233 lab1 = gen_label_rtx ();
1234 lab3 = gen_label_rtx ();
1235
1236 or_result = expand_simple_binop (SImode, IOR,
1237 operands[1], operands[2],
1238 0, 0, OPTAB_LIB_WIDEN);
1239
1240 emit_cmp_and_jump_insns (or_result, GEN_INT (15), GTU, 0,
1241 GET_MODE (or_result), 0, lab3);
1242 JUMP_LABEL (get_last_insn ()) = lab3;
1243
1244 shift_left_result = expand_simple_binop (SImode, ASHIFT,
1245 operands[1], GEN_INT (4),
1246 0, 0, OPTAB_LIB_WIDEN);
1247
1248 lookup_value = expand_simple_binop (SImode, IOR,
1249 shift_left_result, operands[2],
1250 0, 0, OPTAB_LIB_WIDEN);
1251 table = gen_rtx_PLUS (SImode, lookup_value,
1252 gen_rtx_SYMBOL_REF (SImode, "__divsi3_table"));
1253 convert_move (operands[0], gen_rtx_MEM (QImode, table), 1);
1254
1255 tmp = emit_jump_insn (gen_jump (lab1));
1256 JUMP_LABEL (tmp) = lab1;
1257 emit_barrier ();
1258
1259 emit_label (lab3);
1260 LABEL_NUSES (lab3) = 1;
1261
1262 start_sequence ();
1263 final_result = emit_library_call_value (libfunc, NULL_RTX,
1264 LCT_CONST, SImode, 2,
1265 operands[1], SImode,
1266 operands[2], SImode);
1267
1268 insns = get_insns ();
1269 end_sequence ();
1270 emit_libcall_block (insns, operands[0], final_result,
1271 gen_rtx_DIV (SImode, operands[1], operands[2]));
1272
1273 emit_label (lab1);
1274 LABEL_NUSES (lab1) = 1;
1275 }
1276
1277 \f
1278 /* Branches and compares. */
1279
1280 /* Return in *ALT_CODE and *ALT_OP, an alternate equivalent constant
1281 comparison, e.g. >= 1 into > 0. */
1282 static void
1283 nios2_alternate_compare_const (enum rtx_code code, rtx op,
1284 enum rtx_code *alt_code, rtx *alt_op,
1285 enum machine_mode mode)
1286 {
1287 HOST_WIDE_INT opval = INTVAL (op);
1288 enum rtx_code scode = signed_condition (code);
1289 bool dec_p = (scode == LT || scode == GE);
1290
1291 if (code == EQ || code == NE)
1292 {
1293 *alt_code = code;
1294 *alt_op = op;
1295 return;
1296 }
1297
1298 *alt_op = (dec_p
1299 ? gen_int_mode (opval - 1, mode)
1300 : gen_int_mode (opval + 1, mode));
1301
1302 /* The required conversion between [>,>=] and [<,<=] is captured
1303 by a reverse + swap of condition codes. */
1304 *alt_code = reverse_condition (swap_condition (code));
1305
1306 {
1307 /* Test if the incremented/decremented value crosses the over/underflow
1308 boundary. Supposedly, such boundary cases should already be transformed
1309 into always-true/false or EQ conditions, so use an assertion here. */
1310 unsigned HOST_WIDE_INT alt_opval = INTVAL (*alt_op);
1311 if (code == scode)
1312 alt_opval ^= (1 << (GET_MODE_BITSIZE (mode) - 1));
1313 alt_opval &= GET_MODE_MASK (mode);
1314 gcc_assert (dec_p ? alt_opval != GET_MODE_MASK (mode) : alt_opval != 0);
1315 }
1316 }
1317
1318 /* Return true if the constant comparison is supported by nios2. */
1319 static bool
1320 nios2_valid_compare_const_p (enum rtx_code code, rtx op)
1321 {
1322 switch (code)
1323 {
1324 case EQ: case NE: case GE: case LT:
1325 return SMALL_INT (INTVAL (op));
1326 case GEU: case LTU:
1327 return SMALL_INT_UNSIGNED (INTVAL (op));
1328 default:
1329 return false;
1330 }
1331 }
1332
1333 /* Checks if the FPU comparison in *CMP, *OP1, and *OP2 can be supported in
1334 the current configuration. Perform modifications if MODIFY_P is true.
1335 Returns true if FPU compare can be done. */
1336
1337 bool
1338 nios2_validate_fpu_compare (enum machine_mode mode, rtx *cmp, rtx *op1, rtx *op2,
1339 bool modify_p)
1340 {
1341 bool rev_p = false;
1342 enum rtx_code code = GET_CODE (*cmp);
1343
1344 if (!nios2_fpu_compare_enabled (code, mode))
1345 {
1346 code = swap_condition (code);
1347 if (nios2_fpu_compare_enabled (code, mode))
1348 rev_p = true;
1349 else
1350 return false;
1351 }
1352
1353 if (modify_p)
1354 {
1355 if (rev_p)
1356 {
1357 rtx tmp = *op1;
1358 *op1 = *op2;
1359 *op2 = tmp;
1360 }
1361 *op1 = force_reg (mode, *op1);
1362 *op2 = force_reg (mode, *op2);
1363 *cmp = gen_rtx_fmt_ee (code, mode, *op1, *op2);
1364 }
1365 return true;
1366 }
1367
1368 /* Checks and modifies the comparison in *CMP, *OP1, and *OP2 into valid
1369 nios2 supported form. Returns true if success. */
1370 bool
1371 nios2_validate_compare (enum machine_mode mode, rtx *cmp, rtx *op1, rtx *op2)
1372 {
1373 enum rtx_code code = GET_CODE (*cmp);
1374 enum rtx_code alt_code;
1375 rtx alt_op2;
1376
1377 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
1378 return nios2_validate_fpu_compare (mode, cmp, op1, op2, true);
1379
1380 if (!reg_or_0_operand (*op2, mode))
1381 {
1382 /* Create alternate constant compare. */
1383 nios2_alternate_compare_const (code, *op2, &alt_code, &alt_op2, mode);
1384
1385 /* If alterate op2 is zero(0), we can use it directly, possibly
1386 swapping the compare code. */
1387 if (alt_op2 == const0_rtx)
1388 {
1389 code = alt_code;
1390 *op2 = alt_op2;
1391 goto check_rebuild_cmp;
1392 }
1393
1394 /* Check if either constant compare can be used. */
1395 if (nios2_valid_compare_const_p (code, *op2))
1396 return true;
1397 else if (nios2_valid_compare_const_p (alt_code, alt_op2))
1398 {
1399 code = alt_code;
1400 *op2 = alt_op2;
1401 goto rebuild_cmp;
1402 }
1403
1404 /* We have to force op2 into a register now. Try to pick one
1405 with a lower cost. */
1406 if (! nios2_simple_const_p (*op2)
1407 && nios2_simple_const_p (alt_op2))
1408 {
1409 code = alt_code;
1410 *op2 = alt_op2;
1411 }
1412 *op2 = force_reg (SImode, *op2);
1413 }
1414 check_rebuild_cmp:
1415 if (code == GT || code == GTU || code == LE || code == LEU)
1416 {
1417 rtx t = *op1; *op1 = *op2; *op2 = t;
1418 code = swap_condition (code);
1419 }
1420 rebuild_cmp:
1421 *cmp = gen_rtx_fmt_ee (code, mode, *op1, *op2);
1422 return true;
1423 }
1424
1425
1426 /* Addressing Modes. */
1427
1428 /* Implement TARGET_LEGITIMATE_CONSTANT_P. */
1429 static bool
1430 nios2_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1431 {
1432 rtx base, offset;
1433 split_const (x, &base, &offset);
1434 return GET_CODE (base) != SYMBOL_REF || !SYMBOL_REF_TLS_MODEL (base);
1435 }
1436
1437 /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
1438 static bool
1439 nios2_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1440 {
1441 return nios2_legitimate_constant_p (mode, x) == false;
1442 }
1443
1444 /* Return true if register REGNO is a valid base register.
1445 STRICT_P is true if REG_OK_STRICT is in effect. */
1446
1447 bool
1448 nios2_regno_ok_for_base_p (int regno, bool strict_p)
1449 {
1450 if (!HARD_REGISTER_NUM_P (regno))
1451 {
1452 if (!strict_p)
1453 return true;
1454
1455 if (!reg_renumber)
1456 return false;
1457
1458 regno = reg_renumber[regno];
1459 }
1460
1461 /* The fake registers will be eliminated to either the stack or
1462 hard frame pointer, both of which are usually valid base registers.
1463 Reload deals with the cases where the eliminated form isn't valid. */
1464 return (GP_REG_P (regno)
1465 || regno == FRAME_POINTER_REGNUM
1466 || regno == ARG_POINTER_REGNUM);
1467 }
1468
1469 /* Return true if the address expression formed by BASE + OFFSET is
1470 valid. */
1471 static bool
1472 nios2_valid_addr_expr_p (rtx base, rtx offset, bool strict_p)
1473 {
1474 if (!strict_p && GET_CODE (base) == SUBREG)
1475 base = SUBREG_REG (base);
1476 return (REG_P (base)
1477 && nios2_regno_ok_for_base_p (REGNO (base), strict_p)
1478 && (offset == NULL_RTX
1479 || const_arith_operand (offset, Pmode)
1480 || nios2_unspec_reloc_p (offset)));
1481 }
1482
1483 /* Implement TARGET_LEGITIMATE_ADDRESS_P. */
1484 static bool
1485 nios2_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
1486 rtx operand, bool strict_p)
1487 {
1488 switch (GET_CODE (operand))
1489 {
1490 /* Direct. */
1491 case SYMBOL_REF:
1492 if (SYMBOL_REF_TLS_MODEL (operand))
1493 return false;
1494
1495 if (nios2_symbol_ref_in_small_data_p (operand))
1496 return true;
1497
1498 /* Else, fall through. */
1499 case LABEL_REF:
1500 case CONST_INT:
1501 case CONST:
1502 case CONST_DOUBLE:
1503 return false;
1504
1505 /* Register indirect. */
1506 case REG:
1507 return nios2_regno_ok_for_base_p (REGNO (operand), strict_p);
1508
1509 /* Register indirect with displacement. */
1510 case PLUS:
1511 {
1512 rtx op0 = XEXP (operand, 0);
1513 rtx op1 = XEXP (operand, 1);
1514
1515 return (nios2_valid_addr_expr_p (op0, op1, strict_p)
1516 || nios2_valid_addr_expr_p (op1, op0, strict_p));
1517 }
1518
1519 default:
1520 break;
1521 }
1522 return false;
1523 }
1524
1525 /* Return true if SECTION is a small section name. */
1526 static bool
1527 nios2_small_section_name_p (const char *section)
1528 {
1529 return (strcmp (section, ".sbss") == 0
1530 || strncmp (section, ".sbss.", 6) == 0
1531 || strcmp (section, ".sdata") == 0
1532 || strncmp (section, ".sdata.", 7) == 0);
1533 }
1534
1535 /* Return true if EXP should be placed in the small data section. */
1536 static bool
1537 nios2_in_small_data_p (const_tree exp)
1538 {
1539 /* We want to merge strings, so we never consider them small data. */
1540 if (TREE_CODE (exp) == STRING_CST)
1541 return false;
1542
1543 if (TREE_CODE (exp) == VAR_DECL)
1544 {
1545 if (DECL_SECTION_NAME (exp))
1546 {
1547 const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
1548 if (nios2_section_threshold > 0
1549 && nios2_small_section_name_p (section))
1550 return true;
1551 }
1552 else
1553 {
1554 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
1555
1556 /* If this is an incomplete type with size 0, then we can't put it
1557 in sdata because it might be too big when completed. */
1558 if (size > 0
1559 && (unsigned HOST_WIDE_INT) size <= nios2_section_threshold)
1560 return true;
1561 }
1562 }
1563
1564 return false;
1565 }
1566
1567 /* Return true if symbol is in small data section. */
1568
1569 bool
1570 nios2_symbol_ref_in_small_data_p (rtx sym)
1571 {
1572 gcc_assert (GET_CODE (sym) == SYMBOL_REF);
1573 return
1574 (TARGET_GPOPT
1575 /* GP-relative access cannot be used for externally defined symbols,
1576 because the compilation unit that defines the symbol may place it
1577 in a section that cannot be reached from GP. */
1578 && !SYMBOL_REF_EXTERNAL_P (sym)
1579 /* True if a symbol is both small and not weak. */
1580 && SYMBOL_REF_SMALL_P (sym)
1581 && !(SYMBOL_REF_DECL (sym) && DECL_WEAK (SYMBOL_REF_DECL (sym)))
1582 /* TLS variables are not accessed through the GP. */
1583 && SYMBOL_REF_TLS_MODEL (sym) == 0);
1584
1585 }
1586
1587 /* Implement TARGET_SECTION_TYPE_FLAGS. */
1588
1589 static unsigned int
1590 nios2_section_type_flags (tree decl, const char *name, int reloc)
1591 {
1592 unsigned int flags;
1593
1594 flags = default_section_type_flags (decl, name, reloc);
1595
1596 if (nios2_small_section_name_p (name))
1597 flags |= SECTION_SMALL;
1598
1599 return flags;
1600 }
1601
1602
1603 /* Position independent code related. */
1604
1605 /* Emit code to load the PIC register. */
1606 static void
1607 nios2_load_pic_register (void)
1608 {
1609 rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
1610
1611 emit_insn (gen_load_got_register (pic_offset_table_rtx, tmp));
1612 emit_insn (gen_add3_insn (pic_offset_table_rtx, pic_offset_table_rtx, tmp));
1613 }
1614
1615 /* Generate a PIC address as a MEM rtx. */
1616 static rtx
1617 nios2_load_pic_address (rtx sym, int unspec)
1618 {
1619 rtx gotaddr = nios2_got_address (sym, unspec);
1620 return gen_const_mem (Pmode, gotaddr);
1621 }
1622
1623 /* Nonzero if the constant value X is a legitimate general operand
1624 when generating PIC code. It is given that flag_pic is on and
1625 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
1626 bool
1627 nios2_legitimate_pic_operand_p (rtx x)
1628 {
1629 return ! (GET_CODE (x) == SYMBOL_REF
1630 || GET_CODE (x) == LABEL_REF || GET_CODE (x) == CONST);
1631 }
1632
1633 /* Return TRUE if X is a thread-local symbol. */
1634 static bool
1635 nios2_tls_symbol_p (rtx x)
1636 {
1637 return (targetm.have_tls && GET_CODE (x) == SYMBOL_REF
1638 && SYMBOL_REF_TLS_MODEL (x) != 0);
1639 }
1640
1641 /* Legitimize addresses that are CONSTANT_P expressions. */
1642 static rtx
1643 nios2_legitimize_constant_address (rtx addr)
1644 {
1645 rtx base, offset;
1646 split_const (addr, &base, &offset);
1647
1648 if (nios2_tls_symbol_p (base))
1649 base = nios2_legitimize_tls_address (base);
1650 else if (flag_pic)
1651 base = nios2_load_pic_address (base, UNSPEC_PIC_SYM);
1652 else
1653 return addr;
1654
1655 if (offset != const0_rtx)
1656 {
1657 gcc_assert (can_create_pseudo_p ());
1658 return gen_rtx_PLUS (Pmode, force_reg (Pmode, base),
1659 (CONST_INT_P (offset)
1660 ? (SMALL_INT (INTVAL (offset))
1661 ? offset : force_reg (Pmode, offset))
1662 : offset));
1663 }
1664 return base;
1665 }
1666
1667 /* Implement TARGET_LEGITIMIZE_ADDRESS. */
1668 static rtx
1669 nios2_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
1670 enum machine_mode mode ATTRIBUTE_UNUSED)
1671 {
1672 if (CONSTANT_P (x))
1673 return nios2_legitimize_constant_address (x);
1674
1675 /* For the TLS LE (Local Exec) model, the compiler may try to
1676 combine constant offsets with unspec relocs, creating address RTXs
1677 looking like this:
1678 (plus:SI (reg:SI 23 r23)
1679 (const:SI
1680 (plus:SI
1681 (unspec:SI [(symbol_ref:SI ("var"))] UNSPEC_ADD_TLS_LE)
1682 (const_int 48 [0x30]))))
1683
1684 This usually happens when 'var' is a thread-local struct variable,
1685 and access of a field in var causes the addend.
1686
1687 We typically want this combining, so transform the above into this
1688 form, which is allowed:
1689 (plus:SI (reg:SI 23 r23)
1690 (const:SI
1691 (unspec:SI
1692 [(const:SI
1693 (plus:SI (symbol_ref:SI ("var"))
1694 (const_int 48 [0x30])))] UNSPEC_ADD_TLS_LE)))
1695
1696 Which will be output as '%tls_le(var+48)(r23)' in assembly. */
1697 if (GET_CODE (x) == PLUS
1698 && GET_CODE (XEXP (x, 0)) == REG
1699 && GET_CODE (XEXP (x, 1)) == CONST)
1700 {
1701 rtx unspec, offset, reg = XEXP (x, 0);
1702 split_const (XEXP (x, 1), &unspec, &offset);
1703 if (GET_CODE (unspec) == UNSPEC
1704 && nios2_unspec_reloc_name (XINT (unspec, 1)) != NULL
1705 && offset != const0_rtx)
1706 {
1707 unspec = copy_rtx (unspec);
1708 XVECEXP (unspec, 0, 0)
1709 = plus_constant (Pmode, XVECEXP (unspec, 0, 0), INTVAL (offset));
1710 x = gen_rtx_PLUS (Pmode, reg, gen_rtx_CONST (Pmode, unspec));
1711 }
1712 }
1713
1714 return x;
1715 }
1716
1717 /* Main expander function for RTL moves. */
1718 int
1719 nios2_emit_move_sequence (rtx *operands, enum machine_mode mode)
1720 {
1721 rtx to = operands[0];
1722 rtx from = operands[1];
1723
1724 if (!register_operand (to, mode) && !reg_or_0_operand (from, mode))
1725 {
1726 gcc_assert (can_create_pseudo_p ());
1727 from = copy_to_mode_reg (mode, from);
1728 }
1729
1730 if (GET_CODE (from) == SYMBOL_REF || GET_CODE (from) == LABEL_REF
1731 || GET_CODE (from) == CONST)
1732 from = nios2_legitimize_constant_address (from);
1733
1734 operands[0] = to;
1735 operands[1] = from;
1736 return 0;
1737 }
1738
1739 /* The function with address *ADDR is being called. If the address
1740 needs to be loaded from the GOT, emit the instruction to do so and
1741 update *ADDR to point to the rtx for the loaded value. */
1742 void
1743 nios2_adjust_call_address (rtx *call_op)
1744 {
1745 rtx addr;
1746 gcc_assert (MEM_P (*call_op));
1747 addr = XEXP (*call_op, 0);
1748 if (flag_pic && CONSTANT_P (addr))
1749 {
1750 rtx reg = gen_reg_rtx (Pmode);
1751 emit_move_insn (reg, nios2_load_pic_address (addr, UNSPEC_PIC_CALL_SYM));
1752 XEXP (*call_op, 0) = reg;
1753 }
1754 }
1755
1756 \f
1757 /* Output assembly language related definitions. */
1758
1759 /* Print the operand OP to file stream FILE modified by LETTER.
1760 LETTER can be one of:
1761
1762 i: print "i" if OP is an immediate, except 0
1763 o: print "io" if OP is volatile
1764 z: for const0_rtx print $0 instead of 0
1765 H: for %hiadj
1766 L: for %lo
1767 U: for upper half of 32 bit value
1768 D: for the upper 32-bits of a 64-bit double value
1769 R: prints reverse condition.
1770 */
1771 static void
1772 nios2_print_operand (FILE *file, rtx op, int letter)
1773 {
1774
1775 switch (letter)
1776 {
1777 case 'i':
1778 if (CONSTANT_P (op) && op != const0_rtx)
1779 fprintf (file, "i");
1780 return;
1781
1782 case 'o':
1783 if (GET_CODE (op) == MEM
1784 && ((MEM_VOLATILE_P (op) && TARGET_BYPASS_CACHE_VOLATILE)
1785 || TARGET_BYPASS_CACHE))
1786 fprintf (file, "io");
1787 return;
1788
1789 default:
1790 break;
1791 }
1792
1793 if (comparison_operator (op, VOIDmode))
1794 {
1795 enum rtx_code cond = GET_CODE (op);
1796 if (letter == 0)
1797 {
1798 fprintf (file, "%s", GET_RTX_NAME (cond));
1799 return;
1800 }
1801 if (letter == 'R')
1802 {
1803 fprintf (file, "%s", GET_RTX_NAME (reverse_condition (cond)));
1804 return;
1805 }
1806 }
1807
1808 switch (GET_CODE (op))
1809 {
1810 case REG:
1811 if (letter == 0 || letter == 'z')
1812 {
1813 fprintf (file, "%s", reg_names[REGNO (op)]);
1814 return;
1815 }
1816 else if (letter == 'D')
1817 {
1818 fprintf (file, "%s", reg_names[REGNO (op)+1]);
1819 return;
1820 }
1821 break;
1822
1823 case CONST_INT:
1824 if (INTVAL (op) == 0 && letter == 'z')
1825 {
1826 fprintf (file, "zero");
1827 return;
1828 }
1829
1830 if (letter == 'U')
1831 {
1832 HOST_WIDE_INT val = INTVAL (op);
1833 val = (val >> 16) & 0xFFFF;
1834 output_addr_const (file, gen_int_mode (val, SImode));
1835 return;
1836 }
1837 /* Else, fall through. */
1838
1839 case CONST:
1840 case LABEL_REF:
1841 case SYMBOL_REF:
1842 case CONST_DOUBLE:
1843 if (letter == 0 || letter == 'z')
1844 {
1845 output_addr_const (file, op);
1846 return;
1847 }
1848 else if (letter == 'H')
1849 {
1850 fprintf (file, "%%hiadj(");
1851 output_addr_const (file, op);
1852 fprintf (file, ")");
1853 return;
1854 }
1855 else if (letter == 'L')
1856 {
1857 fprintf (file, "%%lo(");
1858 output_addr_const (file, op);
1859 fprintf (file, ")");
1860 return;
1861 }
1862 break;
1863
1864 case SUBREG:
1865 case MEM:
1866 if (letter == 0)
1867 {
1868 output_address (op);
1869 return;
1870 }
1871 break;
1872
1873 case CODE_LABEL:
1874 if (letter == 0)
1875 {
1876 output_addr_const (file, op);
1877 return;
1878 }
1879 break;
1880
1881 default:
1882 break;
1883 }
1884
1885 output_operand_lossage ("Unsupported operand for code '%c'", letter);
1886 gcc_unreachable ();
1887 }
1888
1889 /* Return true if this is a GP-relative accessible reference. */
1890 static bool
1891 gprel_constant_p (rtx op)
1892 {
1893 if (GET_CODE (op) == SYMBOL_REF
1894 && nios2_symbol_ref_in_small_data_p (op))
1895 return true;
1896 else if (GET_CODE (op) == CONST
1897 && GET_CODE (XEXP (op, 0)) == PLUS)
1898 return gprel_constant_p (XEXP (XEXP (op, 0), 0));
1899
1900 return false;
1901 }
1902
1903 /* Return the name string for a supported unspec reloc offset. */
1904 static const char *
1905 nios2_unspec_reloc_name (int unspec)
1906 {
1907 switch (unspec)
1908 {
1909 case UNSPEC_PIC_SYM:
1910 return "got";
1911 case UNSPEC_PIC_CALL_SYM:
1912 return "call";
1913 case UNSPEC_LOAD_TLS_IE:
1914 return "tls_ie";
1915 case UNSPEC_ADD_TLS_LE:
1916 return "tls_le";
1917 case UNSPEC_ADD_TLS_GD:
1918 return "tls_gd";
1919 case UNSPEC_ADD_TLS_LDM:
1920 return "tls_ldm";
1921 case UNSPEC_ADD_TLS_LDO:
1922 return "tls_ldo";
1923 default:
1924 return NULL;
1925 }
1926 }
1927
1928 /* Return true for conforming unspec relocations. Also used in
1929 constraints.md and predicates.md. */
1930 bool
1931 nios2_unspec_reloc_p (rtx op)
1932 {
1933 return (GET_CODE (op) == CONST
1934 && GET_CODE (XEXP (op, 0)) == UNSPEC
1935 && nios2_unspec_reloc_name (XINT (XEXP (op, 0), 1)) != NULL);
1936 }
1937
1938 /* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */
1939 static bool
1940 nios2_output_addr_const_extra (FILE *file, rtx op)
1941 {
1942 const char *name;
1943 gcc_assert (GET_CODE (op) == UNSPEC);
1944
1945 /* Support for printing out const unspec relocations. */
1946 name = nios2_unspec_reloc_name (XINT (op, 1));
1947 if (name)
1948 {
1949 fprintf (file, "%%%s(", name);
1950 output_addr_const (file, XVECEXP (op, 0, 0));
1951 fprintf (file, ")");
1952 return true;
1953 }
1954 return false;
1955 }
1956
1957 /* Implement TARGET_PRINT_OPERAND_ADDRESS. */
1958 static void
1959 nios2_print_operand_address (FILE *file, rtx op)
1960 {
1961 switch (GET_CODE (op))
1962 {
1963 case CONST:
1964 case CONST_INT:
1965 case LABEL_REF:
1966 case CONST_DOUBLE:
1967 case SYMBOL_REF:
1968 if (gprel_constant_p (op))
1969 {
1970 fprintf (file, "%%gprel(");
1971 output_addr_const (file, op);
1972 fprintf (file, ")(%s)", reg_names[GP_REGNO]);
1973 return;
1974 }
1975
1976 break;
1977
1978 case PLUS:
1979 {
1980 rtx op0 = XEXP (op, 0);
1981 rtx op1 = XEXP (op, 1);
1982
1983 if (REG_P (op0) && CONSTANT_P (op1))
1984 {
1985 output_addr_const (file, op1);
1986 fprintf (file, "(%s)", reg_names[REGNO (op0)]);
1987 return;
1988 }
1989 else if (REG_P (op1) && CONSTANT_P (op0))
1990 {
1991 output_addr_const (file, op0);
1992 fprintf (file, "(%s)", reg_names[REGNO (op1)]);
1993 return;
1994 }
1995 }
1996 break;
1997
1998 case REG:
1999 fprintf (file, "0(%s)", reg_names[REGNO (op)]);
2000 return;
2001
2002 case MEM:
2003 {
2004 rtx base = XEXP (op, 0);
2005 nios2_print_operand_address (file, base);
2006 return;
2007 }
2008 default:
2009 break;
2010 }
2011
2012 fprintf (stderr, "Missing way to print address\n");
2013 debug_rtx (op);
2014 gcc_unreachable ();
2015 }
2016
2017 /* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL. */
2018 static void
2019 nios2_output_dwarf_dtprel (FILE *file, int size, rtx x)
2020 {
2021 gcc_assert (size == 4);
2022 fprintf (file, "\t.4byte\t%%tls_ldo(");
2023 output_addr_const (file, x);
2024 fprintf (file, ")");
2025 }
2026
2027 /* Implement TARGET_ASM_FUNCTION_PROLOGUE. */
2028 static void
2029 nios2_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
2030 {
2031 if (flag_verbose_asm || flag_debug_asm)
2032 {
2033 nios2_compute_frame_layout ();
2034 nios2_dump_frame_layout (file);
2035 }
2036 }
2037
2038 /* Emit assembly of custom FPU instructions. */
2039 const char *
2040 nios2_fpu_insn_asm (enum n2fpu_code code)
2041 {
2042 static char buf[256];
2043 const char *op1, *op2, *op3;
2044 int ln = 256, n = 0;
2045
2046 int N = N2FPU_N (code);
2047 int num_operands = N2FPU (code).num_operands;
2048 const char *insn_name = N2FPU_NAME (code);
2049 tree ftype = nios2_ftype (N2FPU_FTCODE (code));
2050 enum machine_mode dst_mode = TYPE_MODE (TREE_TYPE (ftype));
2051 enum machine_mode src_mode = TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (ftype)));
2052
2053 /* Prepare X register for DF input operands. */
2054 if (GET_MODE_SIZE (src_mode) == 8 && num_operands == 3)
2055 n = snprintf (buf, ln, "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t",
2056 N2FPU_N (n2fpu_fwrx));
2057
2058 if (src_mode == SFmode)
2059 {
2060 if (dst_mode == VOIDmode)
2061 {
2062 /* The fwry case. */
2063 op1 = op3 = "zero";
2064 op2 = "%0";
2065 num_operands -= 1;
2066 }
2067 else
2068 {
2069 op1 = "%0"; op2 = "%1";
2070 op3 = (num_operands == 2 ? "zero" : "%2");
2071 }
2072 }
2073 else if (src_mode == DFmode)
2074 {
2075 if (dst_mode == VOIDmode)
2076 {
2077 /* The fwrx case. */
2078 op1 = "zero";
2079 op2 = "%0";
2080 op3 = "%D0";
2081 num_operands -= 1;
2082 }
2083 else
2084 {
2085 op1 = (dst_mode == DFmode ? "%D0" : "%0");
2086 op2 = (num_operands == 2 ? "%1" : "%2");
2087 op3 = (num_operands == 2 ? "%D1" : "%D2");
2088 }
2089 }
2090 else if (src_mode == VOIDmode)
2091 {
2092 /* frdxlo, frdxhi, frdy cases. */
2093 gcc_assert (dst_mode == SFmode);
2094 op1 = "%0";
2095 op2 = op3 = "zero";
2096 }
2097 else if (src_mode == SImode)
2098 {
2099 /* Conversion operators. */
2100 gcc_assert (num_operands == 2);
2101 op1 = (dst_mode == DFmode ? "%D0" : "%0");
2102 op2 = "%1";
2103 op3 = "zero";
2104 }
2105 else
2106 gcc_unreachable ();
2107
2108 /* Main instruction string. */
2109 n += snprintf (buf + n, ln - n, "custom\t%d, %s, %s, %s # %s %%0%s%s",
2110 N, op1, op2, op3, insn_name,
2111 (num_operands >= 2 ? ", %1" : ""),
2112 (num_operands == 3 ? ", %2" : ""));
2113
2114 /* Extraction of Y register for DF results. */
2115 if (dst_mode == DFmode)
2116 snprintf (buf + n, ln - n, "\n\tcustom\t%d, %%0, zero, zero # frdy %%0",
2117 N2FPU_N (n2fpu_frdy));
2118 return buf;
2119 }
2120
2121 \f
2122
2123 /* Function argument related. */
2124
2125 /* Define where to put the arguments to a function. Value is zero to
2126 push the argument on the stack, or a hard register in which to
2127 store the argument.
2128
2129 MODE is the argument's machine mode.
2130 TYPE is the data type of the argument (as a tree).
2131 This is null for libcalls where that information may
2132 not be available.
2133 CUM is a variable of type CUMULATIVE_ARGS which gives info about
2134 the preceding args and about the function being called.
2135 NAMED is nonzero if this argument is a named parameter
2136 (otherwise it is an extra parameter matching an ellipsis). */
2137
2138 static rtx
2139 nios2_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
2140 const_tree type ATTRIBUTE_UNUSED,
2141 bool named ATTRIBUTE_UNUSED)
2142 {
2143 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2144 rtx return_rtx = NULL_RTX;
2145
2146 if (cum->regs_used < NUM_ARG_REGS)
2147 return_rtx = gen_rtx_REG (mode, FIRST_ARG_REGNO + cum->regs_used);
2148
2149 return return_rtx;
2150 }
2151
2152 /* Return number of bytes, at the beginning of the argument, that must be
2153 put in registers. 0 is the argument is entirely in registers or entirely
2154 in memory. */
2155
2156 static int
2157 nios2_arg_partial_bytes (cumulative_args_t cum_v,
2158 enum machine_mode mode, tree type ATTRIBUTE_UNUSED,
2159 bool named ATTRIBUTE_UNUSED)
2160 {
2161 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2162 HOST_WIDE_INT param_size;
2163
2164 if (mode == BLKmode)
2165 {
2166 param_size = int_size_in_bytes (type);
2167 gcc_assert (param_size >= 0);
2168 }
2169 else
2170 param_size = GET_MODE_SIZE (mode);
2171
2172 /* Convert to words (round up). */
2173 param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
2174
2175 if (cum->regs_used < NUM_ARG_REGS
2176 && cum->regs_used + param_size > NUM_ARG_REGS)
2177 return (NUM_ARG_REGS - cum->regs_used) * UNITS_PER_WORD;
2178
2179 return 0;
2180 }
2181
2182 /* Update the data in CUM to advance over an argument of mode MODE
2183 and data type TYPE; TYPE is null for libcalls where that information
2184 may not be available. */
2185
2186 static void
2187 nios2_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
2188 const_tree type ATTRIBUTE_UNUSED,
2189 bool named ATTRIBUTE_UNUSED)
2190 {
2191 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2192 HOST_WIDE_INT param_size;
2193
2194 if (mode == BLKmode)
2195 {
2196 param_size = int_size_in_bytes (type);
2197 gcc_assert (param_size >= 0);
2198 }
2199 else
2200 param_size = GET_MODE_SIZE (mode);
2201
2202 /* Convert to words (round up). */
2203 param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
2204
2205 if (cum->regs_used + param_size > NUM_ARG_REGS)
2206 cum->regs_used = NUM_ARG_REGS;
2207 else
2208 cum->regs_used += param_size;
2209 }
2210
2211 enum direction
2212 nios2_function_arg_padding (enum machine_mode mode, const_tree type)
2213 {
2214 /* On little-endian targets, the first byte of every stack argument
2215 is passed in the first byte of the stack slot. */
2216 if (!BYTES_BIG_ENDIAN)
2217 return upward;
2218
2219 /* Otherwise, integral types are padded downward: the last byte of a
2220 stack argument is passed in the last byte of the stack slot. */
2221 if (type != 0
2222 ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
2223 : GET_MODE_CLASS (mode) == MODE_INT)
2224 return downward;
2225
2226 /* Arguments smaller than a stack slot are padded downward. */
2227 if (mode != BLKmode)
2228 return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY) ? upward : downward;
2229
2230 return ((int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
2231 ? upward : downward);
2232 }
2233
2234 enum direction
2235 nios2_block_reg_padding (enum machine_mode mode, tree type,
2236 int first ATTRIBUTE_UNUSED)
2237 {
2238 return nios2_function_arg_padding (mode, type);
2239 }
2240
2241 /* Emit RTL insns to initialize the variable parts of a trampoline.
2242 FNADDR is an RTX for the address of the function's pure code.
2243 CXT is an RTX for the static chain value for the function.
2244 On Nios II, we handle this by a library call. */
2245 static void
2246 nios2_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
2247 {
2248 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2249 rtx ctx_reg = force_reg (Pmode, cxt);
2250 rtx addr = force_reg (Pmode, XEXP (m_tramp, 0));
2251
2252 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__trampoline_setup"),
2253 LCT_NORMAL, VOIDmode, 3, addr, Pmode, fnaddr, Pmode,
2254 ctx_reg, Pmode);
2255 }
2256
2257 /* Implement TARGET_FUNCTION_VALUE. */
2258 static rtx
2259 nios2_function_value (const_tree ret_type, const_tree fn ATTRIBUTE_UNUSED,
2260 bool outgoing ATTRIBUTE_UNUSED)
2261 {
2262 return gen_rtx_REG (TYPE_MODE (ret_type), FIRST_RETVAL_REGNO);
2263 }
2264
2265 /* Implement TARGET_LIBCALL_VALUE. */
2266 static rtx
2267 nios2_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
2268 {
2269 return gen_rtx_REG (mode, FIRST_RETVAL_REGNO);
2270 }
2271
2272 /* Implement TARGET_FUNCTION_VALUE_REGNO_P. */
2273 static bool
2274 nios2_function_value_regno_p (const unsigned int regno)
2275 {
2276 return regno == FIRST_RETVAL_REGNO;
2277 }
2278
2279 /* Implement TARGET_RETURN_IN_MEMORY. */
2280 static bool
2281 nios2_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2282 {
2283 return (int_size_in_bytes (type) > (2 * UNITS_PER_WORD)
2284 || int_size_in_bytes (type) == -1);
2285 }
2286
2287 /* TODO: It may be possible to eliminate the copyback and implement
2288 own va_arg type. */
2289 static void
2290 nios2_setup_incoming_varargs (cumulative_args_t cum_v,
2291 enum machine_mode mode, tree type,
2292 int *pretend_size, int second_time)
2293 {
2294 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2295 CUMULATIVE_ARGS local_cum;
2296 cumulative_args_t local_cum_v = pack_cumulative_args (&local_cum);
2297 int regs_to_push;
2298 int pret_size;
2299
2300 local_cum = *cum;
2301 nios2_function_arg_advance (local_cum_v, mode, type, 1);
2302
2303 regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
2304
2305 if (!second_time && regs_to_push > 0)
2306 {
2307 rtx ptr = virtual_incoming_args_rtx;
2308 rtx mem = gen_rtx_MEM (BLKmode, ptr);
2309 emit_insn (gen_blockage ());
2310 move_block_from_reg (local_cum.regs_used + FIRST_ARG_REGNO, mem,
2311 regs_to_push);
2312 emit_insn (gen_blockage ());
2313 }
2314
2315 pret_size = regs_to_push * UNITS_PER_WORD;
2316 if (pret_size)
2317 *pretend_size = pret_size;
2318 }
2319
2320 \f
2321
2322 /* Init FPU builtins. */
2323 static void
2324 nios2_init_fpu_builtins (int start_code)
2325 {
2326 tree fndecl;
2327 char builtin_name[64] = "__builtin_custom_";
2328 unsigned int i, n = strlen ("__builtin_custom_");
2329
2330 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
2331 {
2332 snprintf (builtin_name + n, sizeof (builtin_name) - n,
2333 "%s", N2FPU_NAME (i));
2334 fndecl =
2335 add_builtin_function (builtin_name, nios2_ftype (N2FPU_FTCODE (i)),
2336 start_code + i, BUILT_IN_MD, NULL, NULL_TREE);
2337 nios2_register_builtin_fndecl (start_code + i, fndecl);
2338 }
2339 }
2340
2341 /* Helper function for expanding FPU builtins. */
2342 static rtx
2343 nios2_expand_fpu_builtin (tree exp, unsigned int code, rtx target)
2344 {
2345 struct expand_operand ops[MAX_RECOG_OPERANDS];
2346 enum insn_code icode = N2FPU_ICODE (code);
2347 int nargs, argno, opno = 0;
2348 int num_operands = N2FPU (code).num_operands;
2349 enum machine_mode dst_mode = TYPE_MODE (TREE_TYPE (exp));
2350 bool has_target_p = (dst_mode != VOIDmode);
2351
2352 if (N2FPU_N (code) < 0)
2353 fatal_error ("Cannot call %<__builtin_custom_%s%> without specifying switch"
2354 " %<-mcustom-%s%>", N2FPU_NAME (code), N2FPU_NAME (code));
2355 if (has_target_p)
2356 create_output_operand (&ops[opno++], target, dst_mode);
2357 else
2358 /* Subtract away the count of the VOID return, mainly for fwrx/fwry. */
2359 num_operands -= 1;
2360 nargs = call_expr_nargs (exp);
2361 for (argno = 0; argno < nargs; argno++)
2362 {
2363 tree arg = CALL_EXPR_ARG (exp, argno);
2364 create_input_operand (&ops[opno++], expand_normal (arg),
2365 TYPE_MODE (TREE_TYPE (arg)));
2366 }
2367 if (!maybe_expand_insn (icode, num_operands, ops))
2368 {
2369 error ("invalid argument to built-in function");
2370 return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
2371 }
2372 return has_target_p ? ops[0].value : const0_rtx;
2373 }
2374
2375 /* Nios II has custom instruction built-in functions of the forms:
2376 __builtin_custom_n
2377 __builtin_custom_nX
2378 __builtin_custom_nXX
2379 __builtin_custom_Xn
2380 __builtin_custom_XnX
2381 __builtin_custom_XnXX
2382
2383 where each X could be either 'i' (int), 'f' (float), or 'p' (void*).
2384 Therefore with 0-1 return values, and 0-2 arguments, we have a
2385 total of (3 + 1) * (1 + 3 + 9) == 52 custom builtin functions.
2386 */
2387 #define NUM_CUSTOM_BUILTINS ((3 + 1) * (1 + 3 + 9))
2388 static char custom_builtin_name[NUM_CUSTOM_BUILTINS][5];
2389
2390 static void
2391 nios2_init_custom_builtins (int start_code)
2392 {
2393 tree builtin_ftype, ret_type, fndecl;
2394 char builtin_name[32] = "__builtin_custom_";
2395 int n = strlen ("__builtin_custom_");
2396 int builtin_code = 0;
2397 int lhs, rhs1, rhs2;
2398
2399 struct { tree type; const char *c; } op[4];
2400 /* z */ op[0].c = ""; op[0].type = NULL_TREE;
2401 /* f */ op[1].c = "f"; op[1].type = float_type_node;
2402 /* i */ op[2].c = "i"; op[2].type = integer_type_node;
2403 /* p */ op[3].c = "p"; op[3].type = ptr_type_node;
2404
2405 /* We enumerate through the possible operand types to create all the
2406 __builtin_custom_XnXX function tree types. Note that these may slightly
2407 overlap with the function types created for other fixed builtins. */
2408
2409 for (lhs = 0; lhs < 4; lhs++)
2410 for (rhs1 = 0; rhs1 < 4; rhs1++)
2411 for (rhs2 = 0; rhs2 < 4; rhs2++)
2412 {
2413 if (rhs1 == 0 && rhs2 != 0)
2414 continue;
2415 ret_type = (op[lhs].type ? op[lhs].type : void_type_node);
2416 builtin_ftype
2417 = build_function_type_list (ret_type, integer_type_node,
2418 op[rhs1].type, op[rhs2].type,
2419 NULL_TREE);
2420 snprintf (builtin_name + n, 32 - n, "%sn%s%s",
2421 op[lhs].c, op[rhs1].c, op[rhs2].c);
2422 /* Save copy of parameter string into custom_builtin_name[]. */
2423 strncpy (custom_builtin_name[builtin_code], builtin_name + n, 5);
2424 fndecl =
2425 add_builtin_function (builtin_name, builtin_ftype,
2426 start_code + builtin_code,
2427 BUILT_IN_MD, NULL, NULL_TREE);
2428 nios2_register_builtin_fndecl (start_code + builtin_code, fndecl);
2429 builtin_code += 1;
2430 }
2431 }
2432
2433 /* Helper function for expanding custom builtins. */
2434 static rtx
2435 nios2_expand_custom_builtin (tree exp, unsigned int index, rtx target)
2436 {
2437 bool has_target_p = (TREE_TYPE (exp) != void_type_node);
2438 enum machine_mode tmode = VOIDmode;
2439 int nargs, argno;
2440 rtx value, insn, unspec_args[3];
2441 tree arg;
2442
2443 /* XnXX form. */
2444 if (has_target_p)
2445 {
2446 tmode = TYPE_MODE (TREE_TYPE (exp));
2447 if (!target || GET_MODE (target) != tmode
2448 || !REG_P (target))
2449 target = gen_reg_rtx (tmode);
2450 }
2451
2452 nargs = call_expr_nargs (exp);
2453 for (argno = 0; argno < nargs; argno++)
2454 {
2455 arg = CALL_EXPR_ARG (exp, argno);
2456 value = expand_normal (arg);
2457 unspec_args[argno] = value;
2458 if (argno == 0)
2459 {
2460 if (!custom_insn_opcode (value, VOIDmode))
2461 error ("custom instruction opcode must be compile time "
2462 "constant in the range 0-255 for __builtin_custom_%s",
2463 custom_builtin_name[index]);
2464 }
2465 else
2466 /* For other arguments, force into a register. */
2467 unspec_args[argno] = force_reg (TYPE_MODE (TREE_TYPE (arg)),
2468 unspec_args[argno]);
2469 }
2470 /* Fill remaining unspec operands with zero. */
2471 for (; argno < 3; argno++)
2472 unspec_args[argno] = const0_rtx;
2473
2474 insn = (has_target_p
2475 ? gen_rtx_SET (VOIDmode, target,
2476 gen_rtx_UNSPEC_VOLATILE (tmode,
2477 gen_rtvec_v (3, unspec_args),
2478 UNSPECV_CUSTOM_XNXX))
2479 : gen_rtx_UNSPEC_VOLATILE (VOIDmode, gen_rtvec_v (3, unspec_args),
2480 UNSPECV_CUSTOM_NXX));
2481 emit_insn (insn);
2482 return has_target_p ? target : const0_rtx;
2483 }
2484
2485
2486 \f
2487
2488 /* Main definition of built-in functions. Nios II has a small number of fixed
2489 builtins, plus a large number of FPU insn builtins, and builtins for
2490 generating custom instructions. */
2491
2492 struct nios2_builtin_desc
2493 {
2494 enum insn_code icode;
2495 enum nios2_ftcode ftype;
2496 const char *name;
2497 };
2498
2499 #define N2_BUILTINS \
2500 N2_BUILTIN_DEF (sync, N2_FTYPE_VOID_VOID) \
2501 N2_BUILTIN_DEF (ldbio, N2_FTYPE_SI_CVPTR) \
2502 N2_BUILTIN_DEF (ldbuio, N2_FTYPE_UI_CVPTR) \
2503 N2_BUILTIN_DEF (ldhio, N2_FTYPE_SI_CVPTR) \
2504 N2_BUILTIN_DEF (ldhuio, N2_FTYPE_UI_CVPTR) \
2505 N2_BUILTIN_DEF (ldwio, N2_FTYPE_SI_CVPTR) \
2506 N2_BUILTIN_DEF (stbio, N2_FTYPE_VOID_VPTR_SI) \
2507 N2_BUILTIN_DEF (sthio, N2_FTYPE_VOID_VPTR_SI) \
2508 N2_BUILTIN_DEF (stwio, N2_FTYPE_VOID_VPTR_SI) \
2509 N2_BUILTIN_DEF (rdctl, N2_FTYPE_SI_SI) \
2510 N2_BUILTIN_DEF (wrctl, N2_FTYPE_VOID_SI_SI)
2511
2512 enum nios2_builtin_code {
2513 #define N2_BUILTIN_DEF(name, ftype) NIOS2_BUILTIN_ ## name,
2514 N2_BUILTINS
2515 #undef N2_BUILTIN_DEF
2516 NUM_FIXED_NIOS2_BUILTINS
2517 };
2518
2519 static const struct nios2_builtin_desc nios2_builtins[] = {
2520 #define N2_BUILTIN_DEF(name, ftype) \
2521 { CODE_FOR_ ## name, ftype, "__builtin_" #name },
2522 N2_BUILTINS
2523 #undef N2_BUILTIN_DEF
2524 };
2525
2526 /* Start/ends of FPU/custom insn builtin index ranges. */
2527 static unsigned int nios2_fpu_builtin_base;
2528 static unsigned int nios2_custom_builtin_base;
2529 static unsigned int nios2_custom_builtin_end;
2530
2531 /* Implement TARGET_INIT_BUILTINS. */
2532 static void
2533 nios2_init_builtins (void)
2534 {
2535 unsigned int i;
2536
2537 /* Initialize fixed builtins. */
2538 for (i = 0; i < ARRAY_SIZE (nios2_builtins); i++)
2539 {
2540 const struct nios2_builtin_desc *d = &nios2_builtins[i];
2541 tree fndecl =
2542 add_builtin_function (d->name, nios2_ftype (d->ftype), i,
2543 BUILT_IN_MD, NULL, NULL);
2544 nios2_register_builtin_fndecl (i, fndecl);
2545 }
2546
2547 /* Initialize FPU builtins. */
2548 nios2_fpu_builtin_base = ARRAY_SIZE (nios2_builtins);
2549 nios2_init_fpu_builtins (nios2_fpu_builtin_base);
2550
2551 /* Initialize custom insn builtins. */
2552 nios2_custom_builtin_base
2553 = nios2_fpu_builtin_base + ARRAY_SIZE (nios2_fpu_insn);
2554 nios2_custom_builtin_end
2555 = nios2_custom_builtin_base + NUM_CUSTOM_BUILTINS;
2556 nios2_init_custom_builtins (nios2_custom_builtin_base);
2557 }
2558
2559 /* Array of fndecls for TARGET_BUILTIN_DECL. */
2560 #define NIOS2_NUM_BUILTINS \
2561 (ARRAY_SIZE (nios2_builtins) + ARRAY_SIZE (nios2_fpu_insn) + NUM_CUSTOM_BUILTINS)
2562 static GTY(()) tree nios2_builtin_decls[NIOS2_NUM_BUILTINS];
2563
2564 static void
2565 nios2_register_builtin_fndecl (unsigned code, tree fndecl)
2566 {
2567 nios2_builtin_decls[code] = fndecl;
2568 }
2569
2570 /* Implement TARGET_BUILTIN_DECL. */
2571 static tree
2572 nios2_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
2573 {
2574 gcc_assert (nios2_custom_builtin_end == ARRAY_SIZE (nios2_builtin_decls));
2575
2576 if (code >= nios2_custom_builtin_end)
2577 return error_mark_node;
2578
2579 if (code >= nios2_fpu_builtin_base
2580 && code < nios2_custom_builtin_base
2581 && ! N2FPU_ENABLED_P (code - nios2_fpu_builtin_base))
2582 return error_mark_node;
2583
2584 return nios2_builtin_decls[code];
2585 }
2586
2587 \f
2588 /* Low-level built-in expand routine. */
2589 static rtx
2590 nios2_expand_builtin_insn (const struct nios2_builtin_desc *d, int n,
2591 struct expand_operand *ops, bool has_target_p)
2592 {
2593 if (maybe_expand_insn (d->icode, n, ops))
2594 return has_target_p ? ops[0].value : const0_rtx;
2595 else
2596 {
2597 error ("invalid argument to built-in function %s", d->name);
2598 return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
2599 }
2600 }
2601
2602 /* Expand ldio/stio form load-store instruction builtins. */
2603 static rtx
2604 nios2_expand_ldstio_builtin (tree exp, rtx target,
2605 const struct nios2_builtin_desc *d)
2606 {
2607 bool has_target_p;
2608 rtx addr, mem, val;
2609 struct expand_operand ops[MAX_RECOG_OPERANDS];
2610 enum machine_mode mode = insn_data[d->icode].operand[0].mode;
2611
2612 addr = expand_normal (CALL_EXPR_ARG (exp, 0));
2613 mem = gen_rtx_MEM (mode, addr);
2614
2615 if (insn_data[d->icode].operand[0].allows_mem)
2616 {
2617 /* stxio. */
2618 val = expand_normal (CALL_EXPR_ARG (exp, 1));
2619 if (CONST_INT_P (val))
2620 val = force_reg (mode, gen_int_mode (INTVAL (val), mode));
2621 val = simplify_gen_subreg (mode, val, GET_MODE (val), 0);
2622 create_output_operand (&ops[0], mem, mode);
2623 create_input_operand (&ops[1], val, mode);
2624 has_target_p = false;
2625 }
2626 else
2627 {
2628 /* ldxio. */
2629 create_output_operand (&ops[0], target, mode);
2630 create_input_operand (&ops[1], mem, mode);
2631 has_target_p = true;
2632 }
2633 return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
2634 }
2635
2636 /* Expand rdctl/wrctl builtins. */
2637 static rtx
2638 nios2_expand_rdwrctl_builtin (tree exp, rtx target,
2639 const struct nios2_builtin_desc *d)
2640 {
2641 bool has_target_p = (insn_data[d->icode].operand[0].predicate
2642 == register_operand);
2643 rtx ctlcode = expand_normal (CALL_EXPR_ARG (exp, 0));
2644 struct expand_operand ops[MAX_RECOG_OPERANDS];
2645 if (!rdwrctl_operand (ctlcode, VOIDmode))
2646 {
2647 error ("Control register number must be in range 0-31 for %s",
2648 d->name);
2649 return has_target_p ? gen_reg_rtx (SImode) : const0_rtx;
2650 }
2651 if (has_target_p)
2652 {
2653 create_output_operand (&ops[0], target, SImode);
2654 create_integer_operand (&ops[1], INTVAL (ctlcode));
2655 }
2656 else
2657 {
2658 rtx val = expand_normal (CALL_EXPR_ARG (exp, 1));
2659 create_integer_operand (&ops[0], INTVAL (ctlcode));
2660 create_input_operand (&ops[1], val, SImode);
2661 }
2662 return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
2663 }
2664
2665 /* Implement TARGET_EXPAND_BUILTIN. Expand an expression EXP that calls
2666 a built-in function, with result going to TARGET if that's convenient
2667 (and in mode MODE if that's convenient).
2668 SUBTARGET may be used as the target for computing one of EXP's operands.
2669 IGNORE is nonzero if the value is to be ignored. */
2670
2671 static rtx
2672 nios2_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
2673 enum machine_mode mode ATTRIBUTE_UNUSED,
2674 int ignore ATTRIBUTE_UNUSED)
2675 {
2676 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2677 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2678
2679 if (fcode < nios2_fpu_builtin_base)
2680 {
2681 const struct nios2_builtin_desc *d = &nios2_builtins[fcode];
2682
2683 switch (fcode)
2684 {
2685 case NIOS2_BUILTIN_sync:
2686 emit_insn (gen_sync ());
2687 return const0_rtx;
2688
2689 case NIOS2_BUILTIN_ldbio:
2690 case NIOS2_BUILTIN_ldbuio:
2691 case NIOS2_BUILTIN_ldhio:
2692 case NIOS2_BUILTIN_ldhuio:
2693 case NIOS2_BUILTIN_ldwio:
2694 case NIOS2_BUILTIN_stbio:
2695 case NIOS2_BUILTIN_sthio:
2696 case NIOS2_BUILTIN_stwio:
2697 return nios2_expand_ldstio_builtin (exp, target, d);
2698
2699 case NIOS2_BUILTIN_rdctl:
2700 case NIOS2_BUILTIN_wrctl:
2701 return nios2_expand_rdwrctl_builtin (exp, target, d);
2702
2703 default:
2704 gcc_unreachable ();
2705 }
2706 }
2707 else if (fcode < nios2_custom_builtin_base)
2708 /* FPU builtin range. */
2709 return nios2_expand_fpu_builtin (exp, fcode - nios2_fpu_builtin_base,
2710 target);
2711 else if (fcode < nios2_custom_builtin_end)
2712 /* Custom insn builtin range. */
2713 return nios2_expand_custom_builtin (exp, fcode - nios2_custom_builtin_base,
2714 target);
2715 else
2716 gcc_unreachable ();
2717 }
2718
2719 /* Implement TARGET_INIT_LIBFUNCS. */
2720 static void
2721 nios2_init_libfuncs (void)
2722 {
2723 /* For Linux, we have access to kernel support for atomic operations. */
2724 if (TARGET_LINUX_ABI)
2725 init_sync_libfuncs (UNITS_PER_WORD);
2726 }
2727
2728 \f
2729
2730 /* Register a custom code use, and signal error if a conflict was found. */
2731 static void
2732 nios2_register_custom_code (unsigned int N, enum nios2_ccs_code status,
2733 int index)
2734 {
2735 gcc_assert (N <= 255);
2736
2737 if (status == CCS_FPU)
2738 {
2739 if (custom_code_status[N] == CCS_FPU && index != custom_code_index[N])
2740 {
2741 custom_code_conflict = true;
2742 error ("switch %<-mcustom-%s%> conflicts with switch %<-mcustom-%s%>",
2743 N2FPU_NAME (custom_code_index[N]), N2FPU_NAME (index));
2744 }
2745 else if (custom_code_status[N] == CCS_BUILTIN_CALL)
2746 {
2747 custom_code_conflict = true;
2748 error ("call to %<__builtin_custom_%s%> conflicts with switch "
2749 "%<-mcustom-%s%>", custom_builtin_name[custom_code_index[N]],
2750 N2FPU_NAME (index));
2751 }
2752 }
2753 else if (status == CCS_BUILTIN_CALL)
2754 {
2755 if (custom_code_status[N] == CCS_FPU)
2756 {
2757 custom_code_conflict = true;
2758 error ("call to %<__builtin_custom_%s%> conflicts with switch "
2759 "%<-mcustom-%s%>", custom_builtin_name[index],
2760 N2FPU_NAME (custom_code_index[N]));
2761 }
2762 else
2763 {
2764 /* Note that code conflicts between different __builtin_custom_xnxx
2765 calls are not checked. */
2766 }
2767 }
2768 else
2769 gcc_unreachable ();
2770
2771 custom_code_status[N] = status;
2772 custom_code_index[N] = index;
2773 }
2774
2775 /* Mark a custom code as not in use. */
2776 static void
2777 nios2_deregister_custom_code (unsigned int N)
2778 {
2779 if (N <= 255)
2780 {
2781 custom_code_status[N] = CCS_UNUSED;
2782 custom_code_index[N] = 0;
2783 }
2784 }
2785
2786 /* Target attributes can affect per-function option state, so we need to
2787 save/restore the custom code tracking info using the
2788 TARGET_OPTION_SAVE/TARGET_OPTION_RESTORE hooks. */
2789
2790 static void
2791 nios2_option_save (struct cl_target_option *ptr,
2792 struct gcc_options *opts ATTRIBUTE_UNUSED)
2793 {
2794 unsigned int i;
2795 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
2796 ptr->saved_fpu_custom_code[i] = N2FPU_N (i);
2797 memcpy (ptr->saved_custom_code_status, custom_code_status,
2798 sizeof (custom_code_status));
2799 memcpy (ptr->saved_custom_code_index, custom_code_index,
2800 sizeof (custom_code_index));
2801 }
2802
2803 static void
2804 nios2_option_restore (struct gcc_options *opts ATTRIBUTE_UNUSED,
2805 struct cl_target_option *ptr)
2806 {
2807 unsigned int i;
2808 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
2809 N2FPU_N (i) = ptr->saved_fpu_custom_code[i];
2810 memcpy (custom_code_status, ptr->saved_custom_code_status,
2811 sizeof (custom_code_status));
2812 memcpy (custom_code_index, ptr->saved_custom_code_index,
2813 sizeof (custom_code_index));
2814 }
2815
2816 /* Inner function to process the attribute((target(...))), take an argument and
2817 set the current options from the argument. If we have a list, recursively
2818 go over the list. */
2819
2820 static bool
2821 nios2_valid_target_attribute_rec (tree args)
2822 {
2823 if (TREE_CODE (args) == TREE_LIST)
2824 {
2825 bool ret = true;
2826 for (; args; args = TREE_CHAIN (args))
2827 if (TREE_VALUE (args)
2828 && !nios2_valid_target_attribute_rec (TREE_VALUE (args)))
2829 ret = false;
2830 return ret;
2831 }
2832 else if (TREE_CODE (args) == STRING_CST)
2833 {
2834 char *argstr = ASTRDUP (TREE_STRING_POINTER (args));
2835 while (argstr && *argstr != '\0')
2836 {
2837 bool no_opt = false, end_p = false;
2838 char *eq = NULL, *p;
2839 while (ISSPACE (*argstr))
2840 argstr++;
2841 p = argstr;
2842 while (*p != '\0' && *p != ',')
2843 {
2844 if (!eq && *p == '=')
2845 eq = p;
2846 ++p;
2847 }
2848 if (*p == '\0')
2849 end_p = true;
2850 else
2851 *p = '\0';
2852 if (eq) *eq = '\0';
2853
2854 if (!strncmp (argstr, "no-", 3))
2855 {
2856 no_opt = true;
2857 argstr += 3;
2858 }
2859 if (!strncmp (argstr, "custom-fpu-cfg", 14))
2860 {
2861 char *end_eq = p;
2862 if (no_opt)
2863 {
2864 error ("custom-fpu-cfg option does not support %<no-%>");
2865 return false;
2866 }
2867 if (!eq)
2868 {
2869 error ("custom-fpu-cfg option requires configuration"
2870 " argument");
2871 return false;
2872 }
2873 /* Increment and skip whitespace. */
2874 while (ISSPACE (*(++eq))) ;
2875 /* Decrement and skip to before any trailing whitespace. */
2876 while (ISSPACE (*(--end_eq))) ;
2877
2878 nios2_handle_custom_fpu_cfg (eq, end_eq + 1, true);
2879 }
2880 else if (!strncmp (argstr, "custom-", 7))
2881 {
2882 int code = -1;
2883 unsigned int i;
2884 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
2885 if (!strncmp (argstr + 7, N2FPU_NAME (i),
2886 strlen (N2FPU_NAME (i))))
2887 {
2888 /* Found insn. */
2889 code = i;
2890 break;
2891 }
2892 if (code >= 0)
2893 {
2894 if (no_opt)
2895 {
2896 if (eq)
2897 {
2898 error ("%<no-custom-%s%> does not accept arguments",
2899 N2FPU_NAME (code));
2900 return false;
2901 }
2902 /* Disable option by setting to -1. */
2903 nios2_deregister_custom_code (N2FPU_N (code));
2904 N2FPU_N (code) = -1;
2905 }
2906 else
2907 {
2908 char *t;
2909 if (eq)
2910 while (ISSPACE (*(++eq))) ;
2911 if (!eq || eq == p)
2912 {
2913 error ("%<custom-%s=%> requires argument",
2914 N2FPU_NAME (code));
2915 return false;
2916 }
2917 for (t = eq; t != p; ++t)
2918 {
2919 if (ISSPACE (*t))
2920 continue;
2921 if (!ISDIGIT (*t))
2922 {
2923 error ("`custom-%s=' argument requires "
2924 "numeric digits", N2FPU_NAME (code));
2925 return false;
2926 }
2927 }
2928 /* Set option to argument. */
2929 N2FPU_N (code) = atoi (eq);
2930 nios2_handle_custom_fpu_insn_option (code);
2931 }
2932 }
2933 else
2934 {
2935 error ("%<custom-%s=%> is not recognised as FPU instruction",
2936 argstr + 7);
2937 return false;
2938 }
2939 }
2940 else
2941 {
2942 error ("%<%s%> is unknown", argstr);
2943 return false;
2944 }
2945
2946 if (end_p)
2947 break;
2948 else
2949 argstr = p + 1;
2950 }
2951 return true;
2952 }
2953 else
2954 gcc_unreachable ();
2955 }
2956
2957 /* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. */
2958
2959 static tree
2960 nios2_valid_target_attribute_tree (tree args)
2961 {
2962 if (!nios2_valid_target_attribute_rec (args))
2963 return NULL_TREE;
2964 nios2_custom_check_insns ();
2965 return build_target_option_node (&global_options);
2966 }
2967
2968 /* Hook to validate attribute((target("string"))). */
2969
2970 static bool
2971 nios2_valid_target_attribute_p (tree fndecl, tree ARG_UNUSED (name),
2972 tree args, int ARG_UNUSED (flags))
2973 {
2974 struct cl_target_option cur_target;
2975 bool ret = true;
2976 tree old_optimize = build_optimization_node (&global_options);
2977 tree new_target, new_optimize;
2978 tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
2979
2980 /* If the function changed the optimization levels as well as setting target
2981 options, start with the optimizations specified. */
2982 if (func_optimize && func_optimize != old_optimize)
2983 cl_optimization_restore (&global_options,
2984 TREE_OPTIMIZATION (func_optimize));
2985
2986 /* The target attributes may also change some optimization flags, so update
2987 the optimization options if necessary. */
2988 cl_target_option_save (&cur_target, &global_options);
2989 new_target = nios2_valid_target_attribute_tree (args);
2990 new_optimize = build_optimization_node (&global_options);
2991
2992 if (!new_target)
2993 ret = false;
2994
2995 else if (fndecl)
2996 {
2997 DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
2998
2999 if (old_optimize != new_optimize)
3000 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
3001 }
3002
3003 cl_target_option_restore (&global_options, &cur_target);
3004
3005 if (old_optimize != new_optimize)
3006 cl_optimization_restore (&global_options,
3007 TREE_OPTIMIZATION (old_optimize));
3008 return ret;
3009 }
3010
3011 /* Remember the last target of nios2_set_current_function. */
3012 static GTY(()) tree nios2_previous_fndecl;
3013
3014 /* Establish appropriate back-end context for processing the function
3015 FNDECL. The argument might be NULL to indicate processing at top
3016 level, outside of any function scope. */
3017 static void
3018 nios2_set_current_function (tree fndecl)
3019 {
3020 tree old_tree = (nios2_previous_fndecl
3021 ? DECL_FUNCTION_SPECIFIC_TARGET (nios2_previous_fndecl)
3022 : NULL_TREE);
3023
3024 tree new_tree = (fndecl
3025 ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl)
3026 : NULL_TREE);
3027
3028 if (fndecl && fndecl != nios2_previous_fndecl)
3029 {
3030 nios2_previous_fndecl = fndecl;
3031 if (old_tree == new_tree)
3032 ;
3033
3034 else if (new_tree)
3035 {
3036 cl_target_option_restore (&global_options,
3037 TREE_TARGET_OPTION (new_tree));
3038 target_reinit ();
3039 }
3040
3041 else if (old_tree)
3042 {
3043 struct cl_target_option *def
3044 = TREE_TARGET_OPTION (target_option_current_node);
3045
3046 cl_target_option_restore (&global_options, def);
3047 target_reinit ();
3048 }
3049 }
3050 }
3051
3052 /* Hook to validate the current #pragma GCC target and set the FPU custom
3053 code option state. If ARGS is NULL, then POP_TARGET is used to reset
3054 the options. */
3055 static bool
3056 nios2_pragma_target_parse (tree args, tree pop_target)
3057 {
3058 tree cur_tree;
3059 if (! args)
3060 {
3061 cur_tree = ((pop_target)
3062 ? pop_target
3063 : target_option_default_node);
3064 cl_target_option_restore (&global_options,
3065 TREE_TARGET_OPTION (cur_tree));
3066 }
3067 else
3068 {
3069 cur_tree = nios2_valid_target_attribute_tree (args);
3070 if (!cur_tree)
3071 return false;
3072 }
3073
3074 target_option_current_node = cur_tree;
3075 return true;
3076 }
3077
3078 /* Implement TARGET_MERGE_DECL_ATTRIBUTES.
3079 We are just using this hook to add some additional error checking to
3080 the default behavior. GCC does not provide a target hook for merging
3081 the target options, and only correctly handles merging empty vs non-empty
3082 option data; see merge_decls() in c-decl.c.
3083 So here we require either that at least one of the decls has empty
3084 target options, or that the target options/data be identical. */
3085 static tree
3086 nios2_merge_decl_attributes (tree olddecl, tree newdecl)
3087 {
3088 tree oldopts = lookup_attribute ("target", DECL_ATTRIBUTES (olddecl));
3089 tree newopts = lookup_attribute ("target", DECL_ATTRIBUTES (newdecl));
3090 if (newopts && oldopts && newopts != oldopts)
3091 {
3092 tree oldtree = DECL_FUNCTION_SPECIFIC_TARGET (olddecl);
3093 tree newtree = DECL_FUNCTION_SPECIFIC_TARGET (newdecl);
3094 if (oldtree && newtree && oldtree != newtree)
3095 {
3096 struct cl_target_option *olddata = TREE_TARGET_OPTION (oldtree);
3097 struct cl_target_option *newdata = TREE_TARGET_OPTION (newtree);
3098 if (olddata != newdata
3099 && memcmp (olddata, newdata, sizeof (struct cl_target_option)))
3100 error ("%qE redeclared with conflicting %qs attributes",
3101 DECL_NAME (newdecl), "target");
3102 }
3103 }
3104 return merge_attributes (DECL_ATTRIBUTES (olddecl),
3105 DECL_ATTRIBUTES (newdecl));
3106 }
3107
3108 \f
3109 /* Initialize the GCC target structure. */
3110 #undef TARGET_ASM_FUNCTION_PROLOGUE
3111 #define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
3112
3113 #undef TARGET_IN_SMALL_DATA_P
3114 #define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
3115
3116 #undef TARGET_SECTION_TYPE_FLAGS
3117 #define TARGET_SECTION_TYPE_FLAGS nios2_section_type_flags
3118
3119 #undef TARGET_INIT_BUILTINS
3120 #define TARGET_INIT_BUILTINS nios2_init_builtins
3121 #undef TARGET_EXPAND_BUILTIN
3122 #define TARGET_EXPAND_BUILTIN nios2_expand_builtin
3123 #undef TARGET_BUILTIN_DECL
3124 #define TARGET_BUILTIN_DECL nios2_builtin_decl
3125
3126 #undef TARGET_INIT_LIBFUNCS
3127 #define TARGET_INIT_LIBFUNCS nios2_init_libfuncs
3128
3129 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
3130 #define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
3131
3132 #undef TARGET_CAN_ELIMINATE
3133 #define TARGET_CAN_ELIMINATE nios2_can_eliminate
3134
3135 #undef TARGET_FUNCTION_ARG
3136 #define TARGET_FUNCTION_ARG nios2_function_arg
3137
3138 #undef TARGET_FUNCTION_ARG_ADVANCE
3139 #define TARGET_FUNCTION_ARG_ADVANCE nios2_function_arg_advance
3140
3141 #undef TARGET_ARG_PARTIAL_BYTES
3142 #define TARGET_ARG_PARTIAL_BYTES nios2_arg_partial_bytes
3143
3144 #undef TARGET_TRAMPOLINE_INIT
3145 #define TARGET_TRAMPOLINE_INIT nios2_trampoline_init
3146
3147 #undef TARGET_FUNCTION_VALUE
3148 #define TARGET_FUNCTION_VALUE nios2_function_value
3149
3150 #undef TARGET_LIBCALL_VALUE
3151 #define TARGET_LIBCALL_VALUE nios2_libcall_value
3152
3153 #undef TARGET_FUNCTION_VALUE_REGNO_P
3154 #define TARGET_FUNCTION_VALUE_REGNO_P nios2_function_value_regno_p
3155
3156 #undef TARGET_RETURN_IN_MEMORY
3157 #define TARGET_RETURN_IN_MEMORY nios2_return_in_memory
3158
3159 #undef TARGET_PROMOTE_PROTOTYPES
3160 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
3161
3162 #undef TARGET_SETUP_INCOMING_VARARGS
3163 #define TARGET_SETUP_INCOMING_VARARGS nios2_setup_incoming_varargs
3164
3165 #undef TARGET_MUST_PASS_IN_STACK
3166 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
3167
3168 #undef TARGET_LEGITIMATE_CONSTANT_P
3169 #define TARGET_LEGITIMATE_CONSTANT_P nios2_legitimate_constant_p
3170
3171 #undef TARGET_LEGITIMIZE_ADDRESS
3172 #define TARGET_LEGITIMIZE_ADDRESS nios2_legitimize_address
3173
3174 #undef TARGET_LEGITIMATE_ADDRESS_P
3175 #define TARGET_LEGITIMATE_ADDRESS_P nios2_legitimate_address_p
3176
3177 #undef TARGET_PREFERRED_RELOAD_CLASS
3178 #define TARGET_PREFERRED_RELOAD_CLASS nios2_preferred_reload_class
3179
3180 #undef TARGET_RTX_COSTS
3181 #define TARGET_RTX_COSTS nios2_rtx_costs
3182
3183 #undef TARGET_HAVE_TLS
3184 #define TARGET_HAVE_TLS TARGET_LINUX_ABI
3185
3186 #undef TARGET_CANNOT_FORCE_CONST_MEM
3187 #define TARGET_CANNOT_FORCE_CONST_MEM nios2_cannot_force_const_mem
3188
3189 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
3190 #define TARGET_ASM_OUTPUT_DWARF_DTPREL nios2_output_dwarf_dtprel
3191
3192 #undef TARGET_PRINT_OPERAND
3193 #define TARGET_PRINT_OPERAND nios2_print_operand
3194
3195 #undef TARGET_PRINT_OPERAND_ADDRESS
3196 #define TARGET_PRINT_OPERAND_ADDRESS nios2_print_operand_address
3197
3198 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
3199 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA nios2_output_addr_const_extra
3200
3201 #undef TARGET_OPTION_OVERRIDE
3202 #define TARGET_OPTION_OVERRIDE nios2_option_override
3203
3204 #undef TARGET_OPTION_SAVE
3205 #define TARGET_OPTION_SAVE nios2_option_save
3206
3207 #undef TARGET_OPTION_RESTORE
3208 #define TARGET_OPTION_RESTORE nios2_option_restore
3209
3210 #undef TARGET_SET_CURRENT_FUNCTION
3211 #define TARGET_SET_CURRENT_FUNCTION nios2_set_current_function
3212
3213 #undef TARGET_OPTION_VALID_ATTRIBUTE_P
3214 #define TARGET_OPTION_VALID_ATTRIBUTE_P nios2_valid_target_attribute_p
3215
3216 #undef TARGET_OPTION_PRAGMA_PARSE
3217 #define TARGET_OPTION_PRAGMA_PARSE nios2_pragma_target_parse
3218
3219 #undef TARGET_MERGE_DECL_ATTRIBUTES
3220 #define TARGET_MERGE_DECL_ATTRIBUTES nios2_merge_decl_attributes
3221
3222 struct gcc_target targetm = TARGET_INITIALIZER;
3223
3224 #include "gt-nios2.h"