]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/nios2/nios2.c
nios2.md (load_got_register): Initialize GOT pointer from _gp_got instead of _GLOBAL_...
[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(_gp_got - 1b)\n");
671 fprintf (file, "\taddi\tr3, r3, %%lo(_gp_got - 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 = (dst_mode == DFmode ? "%D0" : "%0");
2070 op2 = "%1";
2071 op3 = (num_operands == 2 ? "zero" : "%2");
2072 }
2073 }
2074 else if (src_mode == DFmode)
2075 {
2076 if (dst_mode == VOIDmode)
2077 {
2078 /* The fwrx case. */
2079 op1 = "zero";
2080 op2 = "%0";
2081 op3 = "%D0";
2082 num_operands -= 1;
2083 }
2084 else
2085 {
2086 op1 = (dst_mode == DFmode ? "%D0" : "%0");
2087 op2 = (num_operands == 2 ? "%1" : "%2");
2088 op3 = (num_operands == 2 ? "%D1" : "%D2");
2089 }
2090 }
2091 else if (src_mode == VOIDmode)
2092 {
2093 /* frdxlo, frdxhi, frdy cases. */
2094 gcc_assert (dst_mode == SFmode);
2095 op1 = "%0";
2096 op2 = op3 = "zero";
2097 }
2098 else if (src_mode == SImode)
2099 {
2100 /* Conversion operators. */
2101 gcc_assert (num_operands == 2);
2102 op1 = (dst_mode == DFmode ? "%D0" : "%0");
2103 op2 = "%1";
2104 op3 = "zero";
2105 }
2106 else
2107 gcc_unreachable ();
2108
2109 /* Main instruction string. */
2110 n += snprintf (buf + n, ln - n, "custom\t%d, %s, %s, %s # %s %%0%s%s",
2111 N, op1, op2, op3, insn_name,
2112 (num_operands >= 2 ? ", %1" : ""),
2113 (num_operands == 3 ? ", %2" : ""));
2114
2115 /* Extraction of Y register for DF results. */
2116 if (dst_mode == DFmode)
2117 snprintf (buf + n, ln - n, "\n\tcustom\t%d, %%0, zero, zero # frdy %%0",
2118 N2FPU_N (n2fpu_frdy));
2119 return buf;
2120 }
2121
2122 \f
2123
2124 /* Function argument related. */
2125
2126 /* Define where to put the arguments to a function. Value is zero to
2127 push the argument on the stack, or a hard register in which to
2128 store the argument.
2129
2130 MODE is the argument's machine mode.
2131 TYPE is the data type of the argument (as a tree).
2132 This is null for libcalls where that information may
2133 not be available.
2134 CUM is a variable of type CUMULATIVE_ARGS which gives info about
2135 the preceding args and about the function being called.
2136 NAMED is nonzero if this argument is a named parameter
2137 (otherwise it is an extra parameter matching an ellipsis). */
2138
2139 static rtx
2140 nios2_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
2141 const_tree type ATTRIBUTE_UNUSED,
2142 bool named ATTRIBUTE_UNUSED)
2143 {
2144 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2145 rtx return_rtx = NULL_RTX;
2146
2147 if (cum->regs_used < NUM_ARG_REGS)
2148 return_rtx = gen_rtx_REG (mode, FIRST_ARG_REGNO + cum->regs_used);
2149
2150 return return_rtx;
2151 }
2152
2153 /* Return number of bytes, at the beginning of the argument, that must be
2154 put in registers. 0 is the argument is entirely in registers or entirely
2155 in memory. */
2156
2157 static int
2158 nios2_arg_partial_bytes (cumulative_args_t cum_v,
2159 enum machine_mode mode, tree type ATTRIBUTE_UNUSED,
2160 bool named ATTRIBUTE_UNUSED)
2161 {
2162 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2163 HOST_WIDE_INT param_size;
2164
2165 if (mode == BLKmode)
2166 {
2167 param_size = int_size_in_bytes (type);
2168 gcc_assert (param_size >= 0);
2169 }
2170 else
2171 param_size = GET_MODE_SIZE (mode);
2172
2173 /* Convert to words (round up). */
2174 param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
2175
2176 if (cum->regs_used < NUM_ARG_REGS
2177 && cum->regs_used + param_size > NUM_ARG_REGS)
2178 return (NUM_ARG_REGS - cum->regs_used) * UNITS_PER_WORD;
2179
2180 return 0;
2181 }
2182
2183 /* Update the data in CUM to advance over an argument of mode MODE
2184 and data type TYPE; TYPE is null for libcalls where that information
2185 may not be available. */
2186
2187 static void
2188 nios2_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
2189 const_tree type ATTRIBUTE_UNUSED,
2190 bool named ATTRIBUTE_UNUSED)
2191 {
2192 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2193 HOST_WIDE_INT param_size;
2194
2195 if (mode == BLKmode)
2196 {
2197 param_size = int_size_in_bytes (type);
2198 gcc_assert (param_size >= 0);
2199 }
2200 else
2201 param_size = GET_MODE_SIZE (mode);
2202
2203 /* Convert to words (round up). */
2204 param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
2205
2206 if (cum->regs_used + param_size > NUM_ARG_REGS)
2207 cum->regs_used = NUM_ARG_REGS;
2208 else
2209 cum->regs_used += param_size;
2210 }
2211
2212 enum direction
2213 nios2_function_arg_padding (enum machine_mode mode, const_tree type)
2214 {
2215 /* On little-endian targets, the first byte of every stack argument
2216 is passed in the first byte of the stack slot. */
2217 if (!BYTES_BIG_ENDIAN)
2218 return upward;
2219
2220 /* Otherwise, integral types are padded downward: the last byte of a
2221 stack argument is passed in the last byte of the stack slot. */
2222 if (type != 0
2223 ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
2224 : GET_MODE_CLASS (mode) == MODE_INT)
2225 return downward;
2226
2227 /* Arguments smaller than a stack slot are padded downward. */
2228 if (mode != BLKmode)
2229 return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY) ? upward : downward;
2230
2231 return ((int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
2232 ? upward : downward);
2233 }
2234
2235 enum direction
2236 nios2_block_reg_padding (enum machine_mode mode, tree type,
2237 int first ATTRIBUTE_UNUSED)
2238 {
2239 return nios2_function_arg_padding (mode, type);
2240 }
2241
2242 /* Emit RTL insns to initialize the variable parts of a trampoline.
2243 FNADDR is an RTX for the address of the function's pure code.
2244 CXT is an RTX for the static chain value for the function.
2245 On Nios II, we handle this by a library call. */
2246 static void
2247 nios2_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
2248 {
2249 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2250 rtx ctx_reg = force_reg (Pmode, cxt);
2251 rtx addr = force_reg (Pmode, XEXP (m_tramp, 0));
2252
2253 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__trampoline_setup"),
2254 LCT_NORMAL, VOIDmode, 3, addr, Pmode, fnaddr, Pmode,
2255 ctx_reg, Pmode);
2256 }
2257
2258 /* Implement TARGET_FUNCTION_VALUE. */
2259 static rtx
2260 nios2_function_value (const_tree ret_type, const_tree fn ATTRIBUTE_UNUSED,
2261 bool outgoing ATTRIBUTE_UNUSED)
2262 {
2263 return gen_rtx_REG (TYPE_MODE (ret_type), FIRST_RETVAL_REGNO);
2264 }
2265
2266 /* Implement TARGET_LIBCALL_VALUE. */
2267 static rtx
2268 nios2_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
2269 {
2270 return gen_rtx_REG (mode, FIRST_RETVAL_REGNO);
2271 }
2272
2273 /* Implement TARGET_FUNCTION_VALUE_REGNO_P. */
2274 static bool
2275 nios2_function_value_regno_p (const unsigned int regno)
2276 {
2277 return regno == FIRST_RETVAL_REGNO;
2278 }
2279
2280 /* Implement TARGET_RETURN_IN_MEMORY. */
2281 static bool
2282 nios2_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2283 {
2284 return (int_size_in_bytes (type) > (2 * UNITS_PER_WORD)
2285 || int_size_in_bytes (type) == -1);
2286 }
2287
2288 /* TODO: It may be possible to eliminate the copyback and implement
2289 own va_arg type. */
2290 static void
2291 nios2_setup_incoming_varargs (cumulative_args_t cum_v,
2292 enum machine_mode mode, tree type,
2293 int *pretend_size, int second_time)
2294 {
2295 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2296 CUMULATIVE_ARGS local_cum;
2297 cumulative_args_t local_cum_v = pack_cumulative_args (&local_cum);
2298 int regs_to_push;
2299 int pret_size;
2300
2301 local_cum = *cum;
2302 nios2_function_arg_advance (local_cum_v, mode, type, 1);
2303
2304 regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
2305
2306 if (!second_time && regs_to_push > 0)
2307 {
2308 rtx ptr = virtual_incoming_args_rtx;
2309 rtx mem = gen_rtx_MEM (BLKmode, ptr);
2310 emit_insn (gen_blockage ());
2311 move_block_from_reg (local_cum.regs_used + FIRST_ARG_REGNO, mem,
2312 regs_to_push);
2313 emit_insn (gen_blockage ());
2314 }
2315
2316 pret_size = regs_to_push * UNITS_PER_WORD;
2317 if (pret_size)
2318 *pretend_size = pret_size;
2319 }
2320
2321 \f
2322
2323 /* Init FPU builtins. */
2324 static void
2325 nios2_init_fpu_builtins (int start_code)
2326 {
2327 tree fndecl;
2328 char builtin_name[64] = "__builtin_custom_";
2329 unsigned int i, n = strlen ("__builtin_custom_");
2330
2331 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
2332 {
2333 snprintf (builtin_name + n, sizeof (builtin_name) - n,
2334 "%s", N2FPU_NAME (i));
2335 fndecl =
2336 add_builtin_function (builtin_name, nios2_ftype (N2FPU_FTCODE (i)),
2337 start_code + i, BUILT_IN_MD, NULL, NULL_TREE);
2338 nios2_register_builtin_fndecl (start_code + i, fndecl);
2339 }
2340 }
2341
2342 /* Helper function for expanding FPU builtins. */
2343 static rtx
2344 nios2_expand_fpu_builtin (tree exp, unsigned int code, rtx target)
2345 {
2346 struct expand_operand ops[MAX_RECOG_OPERANDS];
2347 enum insn_code icode = N2FPU_ICODE (code);
2348 int nargs, argno, opno = 0;
2349 int num_operands = N2FPU (code).num_operands;
2350 enum machine_mode dst_mode = TYPE_MODE (TREE_TYPE (exp));
2351 bool has_target_p = (dst_mode != VOIDmode);
2352
2353 if (N2FPU_N (code) < 0)
2354 fatal_error ("Cannot call %<__builtin_custom_%s%> without specifying switch"
2355 " %<-mcustom-%s%>", N2FPU_NAME (code), N2FPU_NAME (code));
2356 if (has_target_p)
2357 create_output_operand (&ops[opno++], target, dst_mode);
2358 else
2359 /* Subtract away the count of the VOID return, mainly for fwrx/fwry. */
2360 num_operands -= 1;
2361 nargs = call_expr_nargs (exp);
2362 for (argno = 0; argno < nargs; argno++)
2363 {
2364 tree arg = CALL_EXPR_ARG (exp, argno);
2365 create_input_operand (&ops[opno++], expand_normal (arg),
2366 TYPE_MODE (TREE_TYPE (arg)));
2367 }
2368 if (!maybe_expand_insn (icode, num_operands, ops))
2369 {
2370 error ("invalid argument to built-in function");
2371 return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
2372 }
2373 return has_target_p ? ops[0].value : const0_rtx;
2374 }
2375
2376 /* Nios II has custom instruction built-in functions of the forms:
2377 __builtin_custom_n
2378 __builtin_custom_nX
2379 __builtin_custom_nXX
2380 __builtin_custom_Xn
2381 __builtin_custom_XnX
2382 __builtin_custom_XnXX
2383
2384 where each X could be either 'i' (int), 'f' (float), or 'p' (void*).
2385 Therefore with 0-1 return values, and 0-2 arguments, we have a
2386 total of (3 + 1) * (1 + 3 + 9) == 52 custom builtin functions.
2387 */
2388 #define NUM_CUSTOM_BUILTINS ((3 + 1) * (1 + 3 + 9))
2389 static char custom_builtin_name[NUM_CUSTOM_BUILTINS][5];
2390
2391 static void
2392 nios2_init_custom_builtins (int start_code)
2393 {
2394 tree builtin_ftype, ret_type, fndecl;
2395 char builtin_name[32] = "__builtin_custom_";
2396 int n = strlen ("__builtin_custom_");
2397 int builtin_code = 0;
2398 int lhs, rhs1, rhs2;
2399
2400 struct { tree type; const char *c; } op[4];
2401 /* z */ op[0].c = ""; op[0].type = NULL_TREE;
2402 /* f */ op[1].c = "f"; op[1].type = float_type_node;
2403 /* i */ op[2].c = "i"; op[2].type = integer_type_node;
2404 /* p */ op[3].c = "p"; op[3].type = ptr_type_node;
2405
2406 /* We enumerate through the possible operand types to create all the
2407 __builtin_custom_XnXX function tree types. Note that these may slightly
2408 overlap with the function types created for other fixed builtins. */
2409
2410 for (lhs = 0; lhs < 4; lhs++)
2411 for (rhs1 = 0; rhs1 < 4; rhs1++)
2412 for (rhs2 = 0; rhs2 < 4; rhs2++)
2413 {
2414 if (rhs1 == 0 && rhs2 != 0)
2415 continue;
2416 ret_type = (op[lhs].type ? op[lhs].type : void_type_node);
2417 builtin_ftype
2418 = build_function_type_list (ret_type, integer_type_node,
2419 op[rhs1].type, op[rhs2].type,
2420 NULL_TREE);
2421 snprintf (builtin_name + n, 32 - n, "%sn%s%s",
2422 op[lhs].c, op[rhs1].c, op[rhs2].c);
2423 /* Save copy of parameter string into custom_builtin_name[]. */
2424 strncpy (custom_builtin_name[builtin_code], builtin_name + n, 5);
2425 fndecl =
2426 add_builtin_function (builtin_name, builtin_ftype,
2427 start_code + builtin_code,
2428 BUILT_IN_MD, NULL, NULL_TREE);
2429 nios2_register_builtin_fndecl (start_code + builtin_code, fndecl);
2430 builtin_code += 1;
2431 }
2432 }
2433
2434 /* Helper function for expanding custom builtins. */
2435 static rtx
2436 nios2_expand_custom_builtin (tree exp, unsigned int index, rtx target)
2437 {
2438 bool has_target_p = (TREE_TYPE (exp) != void_type_node);
2439 enum machine_mode tmode = VOIDmode;
2440 int nargs, argno;
2441 rtx value, insn, unspec_args[3];
2442 tree arg;
2443
2444 /* XnXX form. */
2445 if (has_target_p)
2446 {
2447 tmode = TYPE_MODE (TREE_TYPE (exp));
2448 if (!target || GET_MODE (target) != tmode
2449 || !REG_P (target))
2450 target = gen_reg_rtx (tmode);
2451 }
2452
2453 nargs = call_expr_nargs (exp);
2454 for (argno = 0; argno < nargs; argno++)
2455 {
2456 arg = CALL_EXPR_ARG (exp, argno);
2457 value = expand_normal (arg);
2458 unspec_args[argno] = value;
2459 if (argno == 0)
2460 {
2461 if (!custom_insn_opcode (value, VOIDmode))
2462 error ("custom instruction opcode must be compile time "
2463 "constant in the range 0-255 for __builtin_custom_%s",
2464 custom_builtin_name[index]);
2465 }
2466 else
2467 /* For other arguments, force into a register. */
2468 unspec_args[argno] = force_reg (TYPE_MODE (TREE_TYPE (arg)),
2469 unspec_args[argno]);
2470 }
2471 /* Fill remaining unspec operands with zero. */
2472 for (; argno < 3; argno++)
2473 unspec_args[argno] = const0_rtx;
2474
2475 insn = (has_target_p
2476 ? gen_rtx_SET (VOIDmode, target,
2477 gen_rtx_UNSPEC_VOLATILE (tmode,
2478 gen_rtvec_v (3, unspec_args),
2479 UNSPECV_CUSTOM_XNXX))
2480 : gen_rtx_UNSPEC_VOLATILE (VOIDmode, gen_rtvec_v (3, unspec_args),
2481 UNSPECV_CUSTOM_NXX));
2482 emit_insn (insn);
2483 return has_target_p ? target : const0_rtx;
2484 }
2485
2486
2487 \f
2488
2489 /* Main definition of built-in functions. Nios II has a small number of fixed
2490 builtins, plus a large number of FPU insn builtins, and builtins for
2491 generating custom instructions. */
2492
2493 struct nios2_builtin_desc
2494 {
2495 enum insn_code icode;
2496 enum nios2_ftcode ftype;
2497 const char *name;
2498 };
2499
2500 #define N2_BUILTINS \
2501 N2_BUILTIN_DEF (sync, N2_FTYPE_VOID_VOID) \
2502 N2_BUILTIN_DEF (ldbio, N2_FTYPE_SI_CVPTR) \
2503 N2_BUILTIN_DEF (ldbuio, N2_FTYPE_UI_CVPTR) \
2504 N2_BUILTIN_DEF (ldhio, N2_FTYPE_SI_CVPTR) \
2505 N2_BUILTIN_DEF (ldhuio, N2_FTYPE_UI_CVPTR) \
2506 N2_BUILTIN_DEF (ldwio, N2_FTYPE_SI_CVPTR) \
2507 N2_BUILTIN_DEF (stbio, N2_FTYPE_VOID_VPTR_SI) \
2508 N2_BUILTIN_DEF (sthio, N2_FTYPE_VOID_VPTR_SI) \
2509 N2_BUILTIN_DEF (stwio, N2_FTYPE_VOID_VPTR_SI) \
2510 N2_BUILTIN_DEF (rdctl, N2_FTYPE_SI_SI) \
2511 N2_BUILTIN_DEF (wrctl, N2_FTYPE_VOID_SI_SI)
2512
2513 enum nios2_builtin_code {
2514 #define N2_BUILTIN_DEF(name, ftype) NIOS2_BUILTIN_ ## name,
2515 N2_BUILTINS
2516 #undef N2_BUILTIN_DEF
2517 NUM_FIXED_NIOS2_BUILTINS
2518 };
2519
2520 static const struct nios2_builtin_desc nios2_builtins[] = {
2521 #define N2_BUILTIN_DEF(name, ftype) \
2522 { CODE_FOR_ ## name, ftype, "__builtin_" #name },
2523 N2_BUILTINS
2524 #undef N2_BUILTIN_DEF
2525 };
2526
2527 /* Start/ends of FPU/custom insn builtin index ranges. */
2528 static unsigned int nios2_fpu_builtin_base;
2529 static unsigned int nios2_custom_builtin_base;
2530 static unsigned int nios2_custom_builtin_end;
2531
2532 /* Implement TARGET_INIT_BUILTINS. */
2533 static void
2534 nios2_init_builtins (void)
2535 {
2536 unsigned int i;
2537
2538 /* Initialize fixed builtins. */
2539 for (i = 0; i < ARRAY_SIZE (nios2_builtins); i++)
2540 {
2541 const struct nios2_builtin_desc *d = &nios2_builtins[i];
2542 tree fndecl =
2543 add_builtin_function (d->name, nios2_ftype (d->ftype), i,
2544 BUILT_IN_MD, NULL, NULL);
2545 nios2_register_builtin_fndecl (i, fndecl);
2546 }
2547
2548 /* Initialize FPU builtins. */
2549 nios2_fpu_builtin_base = ARRAY_SIZE (nios2_builtins);
2550 nios2_init_fpu_builtins (nios2_fpu_builtin_base);
2551
2552 /* Initialize custom insn builtins. */
2553 nios2_custom_builtin_base
2554 = nios2_fpu_builtin_base + ARRAY_SIZE (nios2_fpu_insn);
2555 nios2_custom_builtin_end
2556 = nios2_custom_builtin_base + NUM_CUSTOM_BUILTINS;
2557 nios2_init_custom_builtins (nios2_custom_builtin_base);
2558 }
2559
2560 /* Array of fndecls for TARGET_BUILTIN_DECL. */
2561 #define NIOS2_NUM_BUILTINS \
2562 (ARRAY_SIZE (nios2_builtins) + ARRAY_SIZE (nios2_fpu_insn) + NUM_CUSTOM_BUILTINS)
2563 static GTY(()) tree nios2_builtin_decls[NIOS2_NUM_BUILTINS];
2564
2565 static void
2566 nios2_register_builtin_fndecl (unsigned code, tree fndecl)
2567 {
2568 nios2_builtin_decls[code] = fndecl;
2569 }
2570
2571 /* Implement TARGET_BUILTIN_DECL. */
2572 static tree
2573 nios2_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
2574 {
2575 gcc_assert (nios2_custom_builtin_end == ARRAY_SIZE (nios2_builtin_decls));
2576
2577 if (code >= nios2_custom_builtin_end)
2578 return error_mark_node;
2579
2580 if (code >= nios2_fpu_builtin_base
2581 && code < nios2_custom_builtin_base
2582 && ! N2FPU_ENABLED_P (code - nios2_fpu_builtin_base))
2583 return error_mark_node;
2584
2585 return nios2_builtin_decls[code];
2586 }
2587
2588 \f
2589 /* Low-level built-in expand routine. */
2590 static rtx
2591 nios2_expand_builtin_insn (const struct nios2_builtin_desc *d, int n,
2592 struct expand_operand *ops, bool has_target_p)
2593 {
2594 if (maybe_expand_insn (d->icode, n, ops))
2595 return has_target_p ? ops[0].value : const0_rtx;
2596 else
2597 {
2598 error ("invalid argument to built-in function %s", d->name);
2599 return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
2600 }
2601 }
2602
2603 /* Expand ldio/stio form load-store instruction builtins. */
2604 static rtx
2605 nios2_expand_ldstio_builtin (tree exp, rtx target,
2606 const struct nios2_builtin_desc *d)
2607 {
2608 bool has_target_p;
2609 rtx addr, mem, val;
2610 struct expand_operand ops[MAX_RECOG_OPERANDS];
2611 enum machine_mode mode = insn_data[d->icode].operand[0].mode;
2612
2613 addr = expand_normal (CALL_EXPR_ARG (exp, 0));
2614 mem = gen_rtx_MEM (mode, addr);
2615
2616 if (insn_data[d->icode].operand[0].allows_mem)
2617 {
2618 /* stxio. */
2619 val = expand_normal (CALL_EXPR_ARG (exp, 1));
2620 if (CONST_INT_P (val))
2621 val = force_reg (mode, gen_int_mode (INTVAL (val), mode));
2622 val = simplify_gen_subreg (mode, val, GET_MODE (val), 0);
2623 create_output_operand (&ops[0], mem, mode);
2624 create_input_operand (&ops[1], val, mode);
2625 has_target_p = false;
2626 }
2627 else
2628 {
2629 /* ldxio. */
2630 create_output_operand (&ops[0], target, mode);
2631 create_input_operand (&ops[1], mem, mode);
2632 has_target_p = true;
2633 }
2634 return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
2635 }
2636
2637 /* Expand rdctl/wrctl builtins. */
2638 static rtx
2639 nios2_expand_rdwrctl_builtin (tree exp, rtx target,
2640 const struct nios2_builtin_desc *d)
2641 {
2642 bool has_target_p = (insn_data[d->icode].operand[0].predicate
2643 == register_operand);
2644 rtx ctlcode = expand_normal (CALL_EXPR_ARG (exp, 0));
2645 struct expand_operand ops[MAX_RECOG_OPERANDS];
2646 if (!rdwrctl_operand (ctlcode, VOIDmode))
2647 {
2648 error ("Control register number must be in range 0-31 for %s",
2649 d->name);
2650 return has_target_p ? gen_reg_rtx (SImode) : const0_rtx;
2651 }
2652 if (has_target_p)
2653 {
2654 create_output_operand (&ops[0], target, SImode);
2655 create_integer_operand (&ops[1], INTVAL (ctlcode));
2656 }
2657 else
2658 {
2659 rtx val = expand_normal (CALL_EXPR_ARG (exp, 1));
2660 create_integer_operand (&ops[0], INTVAL (ctlcode));
2661 create_input_operand (&ops[1], val, SImode);
2662 }
2663 return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
2664 }
2665
2666 /* Implement TARGET_EXPAND_BUILTIN. Expand an expression EXP that calls
2667 a built-in function, with result going to TARGET if that's convenient
2668 (and in mode MODE if that's convenient).
2669 SUBTARGET may be used as the target for computing one of EXP's operands.
2670 IGNORE is nonzero if the value is to be ignored. */
2671
2672 static rtx
2673 nios2_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
2674 enum machine_mode mode ATTRIBUTE_UNUSED,
2675 int ignore ATTRIBUTE_UNUSED)
2676 {
2677 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2678 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2679
2680 if (fcode < nios2_fpu_builtin_base)
2681 {
2682 const struct nios2_builtin_desc *d = &nios2_builtins[fcode];
2683
2684 switch (fcode)
2685 {
2686 case NIOS2_BUILTIN_sync:
2687 emit_insn (gen_sync ());
2688 return const0_rtx;
2689
2690 case NIOS2_BUILTIN_ldbio:
2691 case NIOS2_BUILTIN_ldbuio:
2692 case NIOS2_BUILTIN_ldhio:
2693 case NIOS2_BUILTIN_ldhuio:
2694 case NIOS2_BUILTIN_ldwio:
2695 case NIOS2_BUILTIN_stbio:
2696 case NIOS2_BUILTIN_sthio:
2697 case NIOS2_BUILTIN_stwio:
2698 return nios2_expand_ldstio_builtin (exp, target, d);
2699
2700 case NIOS2_BUILTIN_rdctl:
2701 case NIOS2_BUILTIN_wrctl:
2702 return nios2_expand_rdwrctl_builtin (exp, target, d);
2703
2704 default:
2705 gcc_unreachable ();
2706 }
2707 }
2708 else if (fcode < nios2_custom_builtin_base)
2709 /* FPU builtin range. */
2710 return nios2_expand_fpu_builtin (exp, fcode - nios2_fpu_builtin_base,
2711 target);
2712 else if (fcode < nios2_custom_builtin_end)
2713 /* Custom insn builtin range. */
2714 return nios2_expand_custom_builtin (exp, fcode - nios2_custom_builtin_base,
2715 target);
2716 else
2717 gcc_unreachable ();
2718 }
2719
2720 /* Implement TARGET_INIT_LIBFUNCS. */
2721 static void
2722 nios2_init_libfuncs (void)
2723 {
2724 /* For Linux, we have access to kernel support for atomic operations. */
2725 if (TARGET_LINUX_ABI)
2726 init_sync_libfuncs (UNITS_PER_WORD);
2727 }
2728
2729 \f
2730
2731 /* Register a custom code use, and signal error if a conflict was found. */
2732 static void
2733 nios2_register_custom_code (unsigned int N, enum nios2_ccs_code status,
2734 int index)
2735 {
2736 gcc_assert (N <= 255);
2737
2738 if (status == CCS_FPU)
2739 {
2740 if (custom_code_status[N] == CCS_FPU && index != custom_code_index[N])
2741 {
2742 custom_code_conflict = true;
2743 error ("switch %<-mcustom-%s%> conflicts with switch %<-mcustom-%s%>",
2744 N2FPU_NAME (custom_code_index[N]), N2FPU_NAME (index));
2745 }
2746 else if (custom_code_status[N] == CCS_BUILTIN_CALL)
2747 {
2748 custom_code_conflict = true;
2749 error ("call to %<__builtin_custom_%s%> conflicts with switch "
2750 "%<-mcustom-%s%>", custom_builtin_name[custom_code_index[N]],
2751 N2FPU_NAME (index));
2752 }
2753 }
2754 else if (status == CCS_BUILTIN_CALL)
2755 {
2756 if (custom_code_status[N] == CCS_FPU)
2757 {
2758 custom_code_conflict = true;
2759 error ("call to %<__builtin_custom_%s%> conflicts with switch "
2760 "%<-mcustom-%s%>", custom_builtin_name[index],
2761 N2FPU_NAME (custom_code_index[N]));
2762 }
2763 else
2764 {
2765 /* Note that code conflicts between different __builtin_custom_xnxx
2766 calls are not checked. */
2767 }
2768 }
2769 else
2770 gcc_unreachable ();
2771
2772 custom_code_status[N] = status;
2773 custom_code_index[N] = index;
2774 }
2775
2776 /* Mark a custom code as not in use. */
2777 static void
2778 nios2_deregister_custom_code (unsigned int N)
2779 {
2780 if (N <= 255)
2781 {
2782 custom_code_status[N] = CCS_UNUSED;
2783 custom_code_index[N] = 0;
2784 }
2785 }
2786
2787 /* Target attributes can affect per-function option state, so we need to
2788 save/restore the custom code tracking info using the
2789 TARGET_OPTION_SAVE/TARGET_OPTION_RESTORE hooks. */
2790
2791 static void
2792 nios2_option_save (struct cl_target_option *ptr,
2793 struct gcc_options *opts ATTRIBUTE_UNUSED)
2794 {
2795 unsigned int i;
2796 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
2797 ptr->saved_fpu_custom_code[i] = N2FPU_N (i);
2798 memcpy (ptr->saved_custom_code_status, custom_code_status,
2799 sizeof (custom_code_status));
2800 memcpy (ptr->saved_custom_code_index, custom_code_index,
2801 sizeof (custom_code_index));
2802 }
2803
2804 static void
2805 nios2_option_restore (struct gcc_options *opts ATTRIBUTE_UNUSED,
2806 struct cl_target_option *ptr)
2807 {
2808 unsigned int i;
2809 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
2810 N2FPU_N (i) = ptr->saved_fpu_custom_code[i];
2811 memcpy (custom_code_status, ptr->saved_custom_code_status,
2812 sizeof (custom_code_status));
2813 memcpy (custom_code_index, ptr->saved_custom_code_index,
2814 sizeof (custom_code_index));
2815 }
2816
2817 /* Inner function to process the attribute((target(...))), take an argument and
2818 set the current options from the argument. If we have a list, recursively
2819 go over the list. */
2820
2821 static bool
2822 nios2_valid_target_attribute_rec (tree args)
2823 {
2824 if (TREE_CODE (args) == TREE_LIST)
2825 {
2826 bool ret = true;
2827 for (; args; args = TREE_CHAIN (args))
2828 if (TREE_VALUE (args)
2829 && !nios2_valid_target_attribute_rec (TREE_VALUE (args)))
2830 ret = false;
2831 return ret;
2832 }
2833 else if (TREE_CODE (args) == STRING_CST)
2834 {
2835 char *argstr = ASTRDUP (TREE_STRING_POINTER (args));
2836 while (argstr && *argstr != '\0')
2837 {
2838 bool no_opt = false, end_p = false;
2839 char *eq = NULL, *p;
2840 while (ISSPACE (*argstr))
2841 argstr++;
2842 p = argstr;
2843 while (*p != '\0' && *p != ',')
2844 {
2845 if (!eq && *p == '=')
2846 eq = p;
2847 ++p;
2848 }
2849 if (*p == '\0')
2850 end_p = true;
2851 else
2852 *p = '\0';
2853 if (eq) *eq = '\0';
2854
2855 if (!strncmp (argstr, "no-", 3))
2856 {
2857 no_opt = true;
2858 argstr += 3;
2859 }
2860 if (!strncmp (argstr, "custom-fpu-cfg", 14))
2861 {
2862 char *end_eq = p;
2863 if (no_opt)
2864 {
2865 error ("custom-fpu-cfg option does not support %<no-%>");
2866 return false;
2867 }
2868 if (!eq)
2869 {
2870 error ("custom-fpu-cfg option requires configuration"
2871 " argument");
2872 return false;
2873 }
2874 /* Increment and skip whitespace. */
2875 while (ISSPACE (*(++eq))) ;
2876 /* Decrement and skip to before any trailing whitespace. */
2877 while (ISSPACE (*(--end_eq))) ;
2878
2879 nios2_handle_custom_fpu_cfg (eq, end_eq + 1, true);
2880 }
2881 else if (!strncmp (argstr, "custom-", 7))
2882 {
2883 int code = -1;
2884 unsigned int i;
2885 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
2886 if (!strncmp (argstr + 7, N2FPU_NAME (i),
2887 strlen (N2FPU_NAME (i))))
2888 {
2889 /* Found insn. */
2890 code = i;
2891 break;
2892 }
2893 if (code >= 0)
2894 {
2895 if (no_opt)
2896 {
2897 if (eq)
2898 {
2899 error ("%<no-custom-%s%> does not accept arguments",
2900 N2FPU_NAME (code));
2901 return false;
2902 }
2903 /* Disable option by setting to -1. */
2904 nios2_deregister_custom_code (N2FPU_N (code));
2905 N2FPU_N (code) = -1;
2906 }
2907 else
2908 {
2909 char *t;
2910 if (eq)
2911 while (ISSPACE (*(++eq))) ;
2912 if (!eq || eq == p)
2913 {
2914 error ("%<custom-%s=%> requires argument",
2915 N2FPU_NAME (code));
2916 return false;
2917 }
2918 for (t = eq; t != p; ++t)
2919 {
2920 if (ISSPACE (*t))
2921 continue;
2922 if (!ISDIGIT (*t))
2923 {
2924 error ("`custom-%s=' argument requires "
2925 "numeric digits", N2FPU_NAME (code));
2926 return false;
2927 }
2928 }
2929 /* Set option to argument. */
2930 N2FPU_N (code) = atoi (eq);
2931 nios2_handle_custom_fpu_insn_option (code);
2932 }
2933 }
2934 else
2935 {
2936 error ("%<custom-%s=%> is not recognised as FPU instruction",
2937 argstr + 7);
2938 return false;
2939 }
2940 }
2941 else
2942 {
2943 error ("%<%s%> is unknown", argstr);
2944 return false;
2945 }
2946
2947 if (end_p)
2948 break;
2949 else
2950 argstr = p + 1;
2951 }
2952 return true;
2953 }
2954 else
2955 gcc_unreachable ();
2956 }
2957
2958 /* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. */
2959
2960 static tree
2961 nios2_valid_target_attribute_tree (tree args)
2962 {
2963 if (!nios2_valid_target_attribute_rec (args))
2964 return NULL_TREE;
2965 nios2_custom_check_insns ();
2966 return build_target_option_node (&global_options);
2967 }
2968
2969 /* Hook to validate attribute((target("string"))). */
2970
2971 static bool
2972 nios2_valid_target_attribute_p (tree fndecl, tree ARG_UNUSED (name),
2973 tree args, int ARG_UNUSED (flags))
2974 {
2975 struct cl_target_option cur_target;
2976 bool ret = true;
2977 tree old_optimize = build_optimization_node (&global_options);
2978 tree new_target, new_optimize;
2979 tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
2980
2981 /* If the function changed the optimization levels as well as setting target
2982 options, start with the optimizations specified. */
2983 if (func_optimize && func_optimize != old_optimize)
2984 cl_optimization_restore (&global_options,
2985 TREE_OPTIMIZATION (func_optimize));
2986
2987 /* The target attributes may also change some optimization flags, so update
2988 the optimization options if necessary. */
2989 cl_target_option_save (&cur_target, &global_options);
2990 new_target = nios2_valid_target_attribute_tree (args);
2991 new_optimize = build_optimization_node (&global_options);
2992
2993 if (!new_target)
2994 ret = false;
2995
2996 else if (fndecl)
2997 {
2998 DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
2999
3000 if (old_optimize != new_optimize)
3001 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
3002 }
3003
3004 cl_target_option_restore (&global_options, &cur_target);
3005
3006 if (old_optimize != new_optimize)
3007 cl_optimization_restore (&global_options,
3008 TREE_OPTIMIZATION (old_optimize));
3009 return ret;
3010 }
3011
3012 /* Remember the last target of nios2_set_current_function. */
3013 static GTY(()) tree nios2_previous_fndecl;
3014
3015 /* Establish appropriate back-end context for processing the function
3016 FNDECL. The argument might be NULL to indicate processing at top
3017 level, outside of any function scope. */
3018 static void
3019 nios2_set_current_function (tree fndecl)
3020 {
3021 tree old_tree = (nios2_previous_fndecl
3022 ? DECL_FUNCTION_SPECIFIC_TARGET (nios2_previous_fndecl)
3023 : NULL_TREE);
3024
3025 tree new_tree = (fndecl
3026 ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl)
3027 : NULL_TREE);
3028
3029 if (fndecl && fndecl != nios2_previous_fndecl)
3030 {
3031 nios2_previous_fndecl = fndecl;
3032 if (old_tree == new_tree)
3033 ;
3034
3035 else if (new_tree)
3036 {
3037 cl_target_option_restore (&global_options,
3038 TREE_TARGET_OPTION (new_tree));
3039 target_reinit ();
3040 }
3041
3042 else if (old_tree)
3043 {
3044 struct cl_target_option *def
3045 = TREE_TARGET_OPTION (target_option_current_node);
3046
3047 cl_target_option_restore (&global_options, def);
3048 target_reinit ();
3049 }
3050 }
3051 }
3052
3053 /* Hook to validate the current #pragma GCC target and set the FPU custom
3054 code option state. If ARGS is NULL, then POP_TARGET is used to reset
3055 the options. */
3056 static bool
3057 nios2_pragma_target_parse (tree args, tree pop_target)
3058 {
3059 tree cur_tree;
3060 if (! args)
3061 {
3062 cur_tree = ((pop_target)
3063 ? pop_target
3064 : target_option_default_node);
3065 cl_target_option_restore (&global_options,
3066 TREE_TARGET_OPTION (cur_tree));
3067 }
3068 else
3069 {
3070 cur_tree = nios2_valid_target_attribute_tree (args);
3071 if (!cur_tree)
3072 return false;
3073 }
3074
3075 target_option_current_node = cur_tree;
3076 return true;
3077 }
3078
3079 /* Implement TARGET_MERGE_DECL_ATTRIBUTES.
3080 We are just using this hook to add some additional error checking to
3081 the default behavior. GCC does not provide a target hook for merging
3082 the target options, and only correctly handles merging empty vs non-empty
3083 option data; see merge_decls() in c-decl.c.
3084 So here we require either that at least one of the decls has empty
3085 target options, or that the target options/data be identical. */
3086 static tree
3087 nios2_merge_decl_attributes (tree olddecl, tree newdecl)
3088 {
3089 tree oldopts = lookup_attribute ("target", DECL_ATTRIBUTES (olddecl));
3090 tree newopts = lookup_attribute ("target", DECL_ATTRIBUTES (newdecl));
3091 if (newopts && oldopts && newopts != oldopts)
3092 {
3093 tree oldtree = DECL_FUNCTION_SPECIFIC_TARGET (olddecl);
3094 tree newtree = DECL_FUNCTION_SPECIFIC_TARGET (newdecl);
3095 if (oldtree && newtree && oldtree != newtree)
3096 {
3097 struct cl_target_option *olddata = TREE_TARGET_OPTION (oldtree);
3098 struct cl_target_option *newdata = TREE_TARGET_OPTION (newtree);
3099 if (olddata != newdata
3100 && memcmp (olddata, newdata, sizeof (struct cl_target_option)))
3101 error ("%qE redeclared with conflicting %qs attributes",
3102 DECL_NAME (newdecl), "target");
3103 }
3104 }
3105 return merge_attributes (DECL_ATTRIBUTES (olddecl),
3106 DECL_ATTRIBUTES (newdecl));
3107 }
3108
3109 \f
3110 /* Initialize the GCC target structure. */
3111 #undef TARGET_ASM_FUNCTION_PROLOGUE
3112 #define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
3113
3114 #undef TARGET_IN_SMALL_DATA_P
3115 #define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
3116
3117 #undef TARGET_SECTION_TYPE_FLAGS
3118 #define TARGET_SECTION_TYPE_FLAGS nios2_section_type_flags
3119
3120 #undef TARGET_INIT_BUILTINS
3121 #define TARGET_INIT_BUILTINS nios2_init_builtins
3122 #undef TARGET_EXPAND_BUILTIN
3123 #define TARGET_EXPAND_BUILTIN nios2_expand_builtin
3124 #undef TARGET_BUILTIN_DECL
3125 #define TARGET_BUILTIN_DECL nios2_builtin_decl
3126
3127 #undef TARGET_INIT_LIBFUNCS
3128 #define TARGET_INIT_LIBFUNCS nios2_init_libfuncs
3129
3130 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
3131 #define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
3132
3133 #undef TARGET_CAN_ELIMINATE
3134 #define TARGET_CAN_ELIMINATE nios2_can_eliminate
3135
3136 #undef TARGET_FUNCTION_ARG
3137 #define TARGET_FUNCTION_ARG nios2_function_arg
3138
3139 #undef TARGET_FUNCTION_ARG_ADVANCE
3140 #define TARGET_FUNCTION_ARG_ADVANCE nios2_function_arg_advance
3141
3142 #undef TARGET_ARG_PARTIAL_BYTES
3143 #define TARGET_ARG_PARTIAL_BYTES nios2_arg_partial_bytes
3144
3145 #undef TARGET_TRAMPOLINE_INIT
3146 #define TARGET_TRAMPOLINE_INIT nios2_trampoline_init
3147
3148 #undef TARGET_FUNCTION_VALUE
3149 #define TARGET_FUNCTION_VALUE nios2_function_value
3150
3151 #undef TARGET_LIBCALL_VALUE
3152 #define TARGET_LIBCALL_VALUE nios2_libcall_value
3153
3154 #undef TARGET_FUNCTION_VALUE_REGNO_P
3155 #define TARGET_FUNCTION_VALUE_REGNO_P nios2_function_value_regno_p
3156
3157 #undef TARGET_RETURN_IN_MEMORY
3158 #define TARGET_RETURN_IN_MEMORY nios2_return_in_memory
3159
3160 #undef TARGET_PROMOTE_PROTOTYPES
3161 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
3162
3163 #undef TARGET_SETUP_INCOMING_VARARGS
3164 #define TARGET_SETUP_INCOMING_VARARGS nios2_setup_incoming_varargs
3165
3166 #undef TARGET_MUST_PASS_IN_STACK
3167 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
3168
3169 #undef TARGET_LEGITIMATE_CONSTANT_P
3170 #define TARGET_LEGITIMATE_CONSTANT_P nios2_legitimate_constant_p
3171
3172 #undef TARGET_LEGITIMIZE_ADDRESS
3173 #define TARGET_LEGITIMIZE_ADDRESS nios2_legitimize_address
3174
3175 #undef TARGET_LEGITIMATE_ADDRESS_P
3176 #define TARGET_LEGITIMATE_ADDRESS_P nios2_legitimate_address_p
3177
3178 #undef TARGET_PREFERRED_RELOAD_CLASS
3179 #define TARGET_PREFERRED_RELOAD_CLASS nios2_preferred_reload_class
3180
3181 #undef TARGET_RTX_COSTS
3182 #define TARGET_RTX_COSTS nios2_rtx_costs
3183
3184 #undef TARGET_HAVE_TLS
3185 #define TARGET_HAVE_TLS TARGET_LINUX_ABI
3186
3187 #undef TARGET_CANNOT_FORCE_CONST_MEM
3188 #define TARGET_CANNOT_FORCE_CONST_MEM nios2_cannot_force_const_mem
3189
3190 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
3191 #define TARGET_ASM_OUTPUT_DWARF_DTPREL nios2_output_dwarf_dtprel
3192
3193 #undef TARGET_PRINT_OPERAND
3194 #define TARGET_PRINT_OPERAND nios2_print_operand
3195
3196 #undef TARGET_PRINT_OPERAND_ADDRESS
3197 #define TARGET_PRINT_OPERAND_ADDRESS nios2_print_operand_address
3198
3199 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
3200 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA nios2_output_addr_const_extra
3201
3202 #undef TARGET_OPTION_OVERRIDE
3203 #define TARGET_OPTION_OVERRIDE nios2_option_override
3204
3205 #undef TARGET_OPTION_SAVE
3206 #define TARGET_OPTION_SAVE nios2_option_save
3207
3208 #undef TARGET_OPTION_RESTORE
3209 #define TARGET_OPTION_RESTORE nios2_option_restore
3210
3211 #undef TARGET_SET_CURRENT_FUNCTION
3212 #define TARGET_SET_CURRENT_FUNCTION nios2_set_current_function
3213
3214 #undef TARGET_OPTION_VALID_ATTRIBUTE_P
3215 #define TARGET_OPTION_VALID_ATTRIBUTE_P nios2_valid_target_attribute_p
3216
3217 #undef TARGET_OPTION_PRAGMA_PARSE
3218 #define TARGET_OPTION_PRAGMA_PARSE nios2_pragma_target_parse
3219
3220 #undef TARGET_MERGE_DECL_ATTRIBUTES
3221 #define TARGET_MERGE_DECL_ATTRIBUTES nios2_merge_decl_attributes
3222
3223 struct gcc_target targetm = TARGET_INITIALIZER;
3224
3225 #include "gt-nios2.h"