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