gcc/
[official-gcc.git] / gcc / config / nios2 / nios2.c
blob567c9215d70bd32069369b20f5f13a82d9888cbf
1 /* Target machine subroutines for Altera Nios II.
2 Copyright (C) 2012-2015 Free Software Foundation, Inc.
3 Contributed by Jonah Graham (jgraham@altera.com),
4 Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@altera.com).
5 Contributed by Mentor Graphics, Inc.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published
11 by the Free Software Foundation; either version 3, or (at your
12 option) any later version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "rtl.h"
28 #include "alias.h"
29 #include "symtab.h"
30 #include "tree.h"
31 #include "fold-const.h"
32 #include "regs.h"
33 #include "hard-reg-set.h"
34 #include "insn-config.h"
35 #include "conditions.h"
36 #include "output.h"
37 #include "insn-attr.h"
38 #include "flags.h"
39 #include "recog.h"
40 #include "function.h"
41 #include "expmed.h"
42 #include "dojump.h"
43 #include "explow.h"
44 #include "calls.h"
45 #include "emit-rtl.h"
46 #include "varasm.h"
47 #include "stmt.h"
48 #include "expr.h"
49 #include "insn-codes.h"
50 #include "optabs.h"
51 #include "predict.h"
52 #include "dominance.h"
53 #include "cfg.h"
54 #include "cfgrtl.h"
55 #include "cfganal.h"
56 #include "lcm.h"
57 #include "cfgbuild.h"
58 #include "cfgcleanup.h"
59 #include "basic-block.h"
60 #include "diagnostic-core.h"
61 #include "toplev.h"
62 #include "target.h"
63 #include "tm_p.h"
64 #include "langhooks.h"
65 #include "df.h"
66 #include "debug.h"
67 #include "reload.h"
68 #include "stor-layout.h"
69 #include "builtins.h"
71 #include "target-def.h"
73 /* Forward function declarations. */
74 static bool prologue_saved_reg_p (unsigned);
75 static void nios2_load_pic_register (void);
76 static void nios2_register_custom_code (unsigned int, enum nios2_ccs_code, int);
77 static const char *nios2_unspec_reloc_name (int);
78 static void nios2_register_builtin_fndecl (unsigned, tree);
80 /* Threshold for data being put into the small data/bss area, instead
81 of the normal data area (references to the small data/bss area take
82 1 instruction, and use the global pointer, references to the normal
83 data area takes 2 instructions). */
84 unsigned HOST_WIDE_INT nios2_section_threshold = NIOS2_DEFAULT_GVALUE;
86 struct GTY (()) machine_function
88 /* Current frame information, to be filled in by nios2_compute_frame_layout
89 with register save masks, and offsets for the current function. */
91 /* Mask of registers to save. */
92 unsigned int save_mask;
93 /* Number of bytes that the entire frame takes up. */
94 int total_size;
95 /* Number of bytes that variables take up. */
96 int var_size;
97 /* Number of bytes that outgoing arguments take up. */
98 int args_size;
99 /* Number of bytes needed to store registers in frame. */
100 int save_reg_size;
101 /* Offset from new stack pointer to store registers. */
102 int save_regs_offset;
103 /* Offset from save_regs_offset to store frame pointer register. */
104 int fp_save_offset;
105 /* != 0 if frame layout already calculated. */
106 int initialized;
109 /* State to track the assignment of custom codes to FPU/custom builtins. */
110 static enum nios2_ccs_code custom_code_status[256];
111 static int custom_code_index[256];
112 /* Set to true if any conflicts (re-use of a code between 0-255) are found. */
113 static bool custom_code_conflict = false;
116 /* Definition of builtin function types for nios2. */
118 #define N2_FTYPES \
119 N2_FTYPE(1, (SF)) \
120 N2_FTYPE(1, (VOID)) \
121 N2_FTYPE(2, (DF, DF)) \
122 N2_FTYPE(3, (DF, DF, DF)) \
123 N2_FTYPE(2, (DF, SF)) \
124 N2_FTYPE(2, (DF, SI)) \
125 N2_FTYPE(2, (DF, UI)) \
126 N2_FTYPE(2, (SF, DF)) \
127 N2_FTYPE(2, (SF, SF)) \
128 N2_FTYPE(3, (SF, SF, SF)) \
129 N2_FTYPE(2, (SF, SI)) \
130 N2_FTYPE(2, (SF, UI)) \
131 N2_FTYPE(2, (SI, CVPTR)) \
132 N2_FTYPE(2, (SI, DF)) \
133 N2_FTYPE(3, (SI, DF, DF)) \
134 N2_FTYPE(2, (SI, SF)) \
135 N2_FTYPE(3, (SI, SF, SF)) \
136 N2_FTYPE(2, (SI, SI)) \
137 N2_FTYPE(2, (UI, CVPTR)) \
138 N2_FTYPE(2, (UI, DF)) \
139 N2_FTYPE(2, (UI, SF)) \
140 N2_FTYPE(2, (VOID, DF)) \
141 N2_FTYPE(2, (VOID, SF)) \
142 N2_FTYPE(3, (VOID, SI, SI)) \
143 N2_FTYPE(3, (VOID, VPTR, SI))
145 #define N2_FTYPE_OP1(R) N2_FTYPE_ ## R ## _VOID
146 #define N2_FTYPE_OP2(R, A1) N2_FTYPE_ ## R ## _ ## A1
147 #define N2_FTYPE_OP3(R, A1, A2) N2_FTYPE_ ## R ## _ ## A1 ## _ ## A2
149 /* Expand ftcode enumeration. */
150 enum nios2_ftcode {
151 #define N2_FTYPE(N,ARGS) N2_FTYPE_OP ## N ARGS,
152 N2_FTYPES
153 #undef N2_FTYPE
154 N2_FTYPE_MAX
157 /* Return the tree function type, based on the ftcode. */
158 static tree
159 nios2_ftype (enum nios2_ftcode ftcode)
161 static tree types[(int) N2_FTYPE_MAX];
163 tree N2_TYPE_SF = float_type_node;
164 tree N2_TYPE_DF = double_type_node;
165 tree N2_TYPE_SI = integer_type_node;
166 tree N2_TYPE_UI = unsigned_type_node;
167 tree N2_TYPE_VOID = void_type_node;
169 static const_tree N2_TYPE_CVPTR, N2_TYPE_VPTR;
170 if (!N2_TYPE_CVPTR)
172 /* const volatile void *. */
173 N2_TYPE_CVPTR
174 = build_pointer_type (build_qualified_type (void_type_node,
175 (TYPE_QUAL_CONST
176 | TYPE_QUAL_VOLATILE)));
177 /* volatile void *. */
178 N2_TYPE_VPTR
179 = build_pointer_type (build_qualified_type (void_type_node,
180 TYPE_QUAL_VOLATILE));
182 if (types[(int) ftcode] == NULL_TREE)
183 switch (ftcode)
185 #define N2_FTYPE_ARGS1(R) N2_TYPE_ ## R
186 #define N2_FTYPE_ARGS2(R,A1) N2_TYPE_ ## R, N2_TYPE_ ## A1
187 #define N2_FTYPE_ARGS3(R,A1,A2) N2_TYPE_ ## R, N2_TYPE_ ## A1, N2_TYPE_ ## A2
188 #define N2_FTYPE(N,ARGS) \
189 case N2_FTYPE_OP ## N ARGS: \
190 types[(int) ftcode] \
191 = build_function_type_list (N2_FTYPE_ARGS ## N ARGS, NULL_TREE); \
192 break;
193 N2_FTYPES
194 #undef N2_FTYPE
195 default: gcc_unreachable ();
197 return types[(int) ftcode];
201 /* Definition of FPU instruction descriptions. */
203 struct nios2_fpu_insn_info
205 const char *name;
206 int num_operands, *optvar;
207 int opt, no_opt;
208 #define N2F_DF 0x1
209 #define N2F_DFREQ 0x2
210 #define N2F_UNSAFE 0x4
211 #define N2F_FINITE 0x8
212 #define N2F_NO_ERRNO 0x10
213 unsigned int flags;
214 enum insn_code icode;
215 enum nios2_ftcode ftcode;
218 /* Base macro for defining FPU instructions. */
219 #define N2FPU_INSN_DEF_BASE(insn, nop, flags, icode, args) \
220 { #insn, nop, &nios2_custom_ ## insn, OPT_mcustom_##insn##_, \
221 OPT_mno_custom_##insn, flags, CODE_FOR_ ## icode, \
222 N2_FTYPE_OP ## nop args }
224 /* Arithmetic and math functions; 2 or 3 operand FP operations. */
225 #define N2FPU_OP2(mode) (mode, mode)
226 #define N2FPU_OP3(mode) (mode, mode, mode)
227 #define N2FPU_INSN_DEF(code, icode, nop, flags, m, M) \
228 N2FPU_INSN_DEF_BASE (f ## code ## m, nop, flags, \
229 icode ## m ## f ## nop, N2FPU_OP ## nop (M ## F))
230 #define N2FPU_INSN_SF(code, nop, flags) \
231 N2FPU_INSN_DEF (code, code, nop, flags, s, S)
232 #define N2FPU_INSN_DF(code, nop, flags) \
233 N2FPU_INSN_DEF (code, code, nop, flags | N2F_DF, d, D)
235 /* Compare instructions, 3 operand FP operation with a SI result. */
236 #define N2FPU_CMP_DEF(code, flags, m, M) \
237 N2FPU_INSN_DEF_BASE (fcmp ## code ## m, 3, flags, \
238 nios2_s ## code ## m ## f, (SI, M ## F, M ## F))
239 #define N2FPU_CMP_SF(code) N2FPU_CMP_DEF (code, 0, s, S)
240 #define N2FPU_CMP_DF(code) N2FPU_CMP_DEF (code, N2F_DF, d, D)
242 /* The order of definition needs to be maintained consistent with
243 enum n2fpu_code in nios2-opts.h. */
244 struct nios2_fpu_insn_info nios2_fpu_insn[] =
246 /* Single precision instructions. */
247 N2FPU_INSN_SF (add, 3, 0),
248 N2FPU_INSN_SF (sub, 3, 0),
249 N2FPU_INSN_SF (mul, 3, 0),
250 N2FPU_INSN_SF (div, 3, 0),
251 /* Due to textual difference between min/max and smin/smax. */
252 N2FPU_INSN_DEF (min, smin, 3, N2F_FINITE, s, S),
253 N2FPU_INSN_DEF (max, smax, 3, N2F_FINITE, s, S),
254 N2FPU_INSN_SF (neg, 2, 0),
255 N2FPU_INSN_SF (abs, 2, 0),
256 N2FPU_INSN_SF (sqrt, 2, 0),
257 N2FPU_INSN_SF (sin, 2, N2F_UNSAFE),
258 N2FPU_INSN_SF (cos, 2, N2F_UNSAFE),
259 N2FPU_INSN_SF (tan, 2, N2F_UNSAFE),
260 N2FPU_INSN_SF (atan, 2, N2F_UNSAFE),
261 N2FPU_INSN_SF (exp, 2, N2F_UNSAFE),
262 N2FPU_INSN_SF (log, 2, N2F_UNSAFE),
263 /* Single precision compares. */
264 N2FPU_CMP_SF (eq), N2FPU_CMP_SF (ne),
265 N2FPU_CMP_SF (lt), N2FPU_CMP_SF (le),
266 N2FPU_CMP_SF (gt), N2FPU_CMP_SF (ge),
268 /* Double precision instructions. */
269 N2FPU_INSN_DF (add, 3, 0),
270 N2FPU_INSN_DF (sub, 3, 0),
271 N2FPU_INSN_DF (mul, 3, 0),
272 N2FPU_INSN_DF (div, 3, 0),
273 /* Due to textual difference between min/max and smin/smax. */
274 N2FPU_INSN_DEF (min, smin, 3, N2F_FINITE, d, D),
275 N2FPU_INSN_DEF (max, smax, 3, N2F_FINITE, d, D),
276 N2FPU_INSN_DF (neg, 2, 0),
277 N2FPU_INSN_DF (abs, 2, 0),
278 N2FPU_INSN_DF (sqrt, 2, 0),
279 N2FPU_INSN_DF (sin, 2, N2F_UNSAFE),
280 N2FPU_INSN_DF (cos, 2, N2F_UNSAFE),
281 N2FPU_INSN_DF (tan, 2, N2F_UNSAFE),
282 N2FPU_INSN_DF (atan, 2, N2F_UNSAFE),
283 N2FPU_INSN_DF (exp, 2, N2F_UNSAFE),
284 N2FPU_INSN_DF (log, 2, N2F_UNSAFE),
285 /* Double precision compares. */
286 N2FPU_CMP_DF (eq), N2FPU_CMP_DF (ne),
287 N2FPU_CMP_DF (lt), N2FPU_CMP_DF (le),
288 N2FPU_CMP_DF (gt), N2FPU_CMP_DF (ge),
290 /* Conversion instructions. */
291 N2FPU_INSN_DEF_BASE (floatis, 2, 0, floatsisf2, (SF, SI)),
292 N2FPU_INSN_DEF_BASE (floatus, 2, 0, floatunssisf2, (SF, UI)),
293 N2FPU_INSN_DEF_BASE (floatid, 2, 0, floatsidf2, (DF, SI)),
294 N2FPU_INSN_DEF_BASE (floatud, 2, 0, floatunssidf2, (DF, UI)),
295 N2FPU_INSN_DEF_BASE (round, 2, N2F_NO_ERRNO, lroundsfsi2, (SI, SF)),
296 N2FPU_INSN_DEF_BASE (fixsi, 2, 0, fix_truncsfsi2, (SI, SF)),
297 N2FPU_INSN_DEF_BASE (fixsu, 2, 0, fixuns_truncsfsi2, (UI, SF)),
298 N2FPU_INSN_DEF_BASE (fixdi, 2, 0, fix_truncdfsi2, (SI, DF)),
299 N2FPU_INSN_DEF_BASE (fixdu, 2, 0, fixuns_truncdfsi2, (UI, DF)),
300 N2FPU_INSN_DEF_BASE (fextsd, 2, 0, extendsfdf2, (DF, SF)),
301 N2FPU_INSN_DEF_BASE (ftruncds, 2, 0, truncdfsf2, (SF, DF)),
303 /* X, Y access instructions. */
304 N2FPU_INSN_DEF_BASE (fwrx, 2, N2F_DFREQ, nios2_fwrx, (VOID, DF)),
305 N2FPU_INSN_DEF_BASE (fwry, 2, N2F_DFREQ, nios2_fwry, (VOID, SF)),
306 N2FPU_INSN_DEF_BASE (frdxlo, 1, N2F_DFREQ, nios2_frdxlo, (SF)),
307 N2FPU_INSN_DEF_BASE (frdxhi, 1, N2F_DFREQ, nios2_frdxhi, (SF)),
308 N2FPU_INSN_DEF_BASE (frdy, 1, N2F_DFREQ, nios2_frdy, (SF))
311 /* Some macros for ease of access. */
312 #define N2FPU(code) nios2_fpu_insn[(int) code]
313 #define N2FPU_ENABLED_P(code) (N2FPU_N(code) >= 0)
314 #define N2FPU_N(code) (*N2FPU(code).optvar)
315 #define N2FPU_NAME(code) (N2FPU(code).name)
316 #define N2FPU_ICODE(code) (N2FPU(code).icode)
317 #define N2FPU_FTCODE(code) (N2FPU(code).ftcode)
318 #define N2FPU_FINITE_P(code) (N2FPU(code).flags & N2F_FINITE)
319 #define N2FPU_UNSAFE_P(code) (N2FPU(code).flags & N2F_UNSAFE)
320 #define N2FPU_NO_ERRNO_P(code) (N2FPU(code).flags & N2F_NO_ERRNO)
321 #define N2FPU_DOUBLE_P(code) (N2FPU(code).flags & N2F_DF)
322 #define N2FPU_DOUBLE_REQUIRED_P(code) (N2FPU(code).flags & N2F_DFREQ)
324 /* Same as above, but for cases where using only the op part is shorter. */
325 #define N2FPU_OP(op) N2FPU(n2fpu_ ## op)
326 #define N2FPU_OP_NAME(op) N2FPU_NAME(n2fpu_ ## op)
327 #define N2FPU_OP_ENABLED_P(op) N2FPU_ENABLED_P(n2fpu_ ## op)
329 /* Export the FPU insn enabled predicate to nios2.md. */
330 bool
331 nios2_fpu_insn_enabled (enum n2fpu_code code)
333 return N2FPU_ENABLED_P (code);
336 /* Return true if COND comparison for mode MODE is enabled under current
337 settings. */
339 static bool
340 nios2_fpu_compare_enabled (enum rtx_code cond, machine_mode mode)
342 if (mode == SFmode)
343 switch (cond)
345 case EQ: return N2FPU_OP_ENABLED_P (fcmpeqs);
346 case NE: return N2FPU_OP_ENABLED_P (fcmpnes);
347 case GT: return N2FPU_OP_ENABLED_P (fcmpgts);
348 case GE: return N2FPU_OP_ENABLED_P (fcmpges);
349 case LT: return N2FPU_OP_ENABLED_P (fcmplts);
350 case LE: return N2FPU_OP_ENABLED_P (fcmples);
351 default: break;
353 else if (mode == DFmode)
354 switch (cond)
356 case EQ: return N2FPU_OP_ENABLED_P (fcmpeqd);
357 case NE: return N2FPU_OP_ENABLED_P (fcmpned);
358 case GT: return N2FPU_OP_ENABLED_P (fcmpgtd);
359 case GE: return N2FPU_OP_ENABLED_P (fcmpged);
360 case LT: return N2FPU_OP_ENABLED_P (fcmpltd);
361 case LE: return N2FPU_OP_ENABLED_P (fcmpled);
362 default: break;
364 return false;
367 /* Stack layout and calling conventions. */
369 #define NIOS2_STACK_ALIGN(LOC) \
370 (((LOC) + ((PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) - 1)) \
371 & ~((PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) - 1))
373 /* Return the bytes needed to compute the frame pointer from the current
374 stack pointer. */
375 static int
376 nios2_compute_frame_layout (void)
378 unsigned int regno;
379 unsigned int save_mask = 0;
380 int total_size;
381 int var_size;
382 int out_args_size;
383 int save_reg_size;
385 if (cfun->machine->initialized)
386 return cfun->machine->total_size;
388 var_size = NIOS2_STACK_ALIGN (get_frame_size ());
389 out_args_size = NIOS2_STACK_ALIGN (crtl->outgoing_args_size);
390 total_size = var_size + out_args_size;
392 /* Calculate space needed for gp registers. */
393 save_reg_size = 0;
394 for (regno = 0; regno <= LAST_GP_REG; regno++)
395 if (prologue_saved_reg_p (regno))
397 save_mask |= 1 << regno;
398 save_reg_size += 4;
401 /* If we call eh_return, we need to save the EH data registers. */
402 if (crtl->calls_eh_return)
404 unsigned i;
405 unsigned r;
407 for (i = 0; (r = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++)
408 if (!(save_mask & (1 << r)))
410 save_mask |= 1 << r;
411 save_reg_size += 4;
415 cfun->machine->fp_save_offset = 0;
416 if (save_mask & (1 << HARD_FRAME_POINTER_REGNUM))
418 int fp_save_offset = 0;
419 for (regno = 0; regno < HARD_FRAME_POINTER_REGNUM; regno++)
420 if (save_mask & (1 << regno))
421 fp_save_offset += 4;
423 cfun->machine->fp_save_offset = fp_save_offset;
426 save_reg_size = NIOS2_STACK_ALIGN (save_reg_size);
427 total_size += save_reg_size;
428 total_size += NIOS2_STACK_ALIGN (crtl->args.pretend_args_size);
430 /* Save other computed information. */
431 cfun->machine->save_mask = save_mask;
432 cfun->machine->total_size = total_size;
433 cfun->machine->var_size = var_size;
434 cfun->machine->args_size = out_args_size;
435 cfun->machine->save_reg_size = save_reg_size;
436 cfun->machine->initialized = reload_completed;
437 cfun->machine->save_regs_offset = out_args_size + var_size;
439 return total_size;
442 /* Generate save/restore of register REGNO at SP + OFFSET. Used by the
443 prologue/epilogue expand routines. */
444 static void
445 save_reg (int regno, unsigned offset)
447 rtx reg = gen_rtx_REG (SImode, regno);
448 rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
449 gen_int_mode (offset, Pmode));
450 rtx insn = emit_move_insn (gen_frame_mem (Pmode, addr), reg);
451 RTX_FRAME_RELATED_P (insn) = 1;
454 static void
455 restore_reg (int regno, unsigned offset)
457 rtx reg = gen_rtx_REG (SImode, regno);
458 rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
459 gen_int_mode (offset, Pmode));
460 rtx insn = emit_move_insn (reg, gen_frame_mem (Pmode, addr));
461 /* Tag epilogue unwind note. */
462 add_reg_note (insn, REG_CFA_RESTORE, reg);
463 RTX_FRAME_RELATED_P (insn) = 1;
466 /* Emit conditional trap for checking stack limit. */
467 static void
468 nios2_emit_stack_limit_check (void)
470 if (REG_P (stack_limit_rtx))
471 emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode, stack_pointer_rtx,
472 stack_limit_rtx),
473 stack_pointer_rtx, stack_limit_rtx, GEN_INT (3)));
474 else
475 sorry ("only register based stack limit is supported");
478 /* Temp regno used inside prologue/epilogue. */
479 #define TEMP_REG_NUM 8
481 static rtx
482 nios2_emit_add_constant (rtx reg, HOST_WIDE_INT immed)
484 rtx insn;
485 if (SMALL_INT (immed))
486 insn = emit_insn (gen_add2_insn (reg, gen_int_mode (immed, Pmode)));
487 else
489 rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
490 emit_move_insn (tmp, gen_int_mode (immed, Pmode));
491 insn = emit_insn (gen_add2_insn (reg, tmp));
493 return insn;
496 void
497 nios2_expand_prologue (void)
499 unsigned int regno;
500 int total_frame_size, save_offset;
501 int sp_offset; /* offset from base_reg to final stack value. */
502 int save_regs_base; /* offset from base_reg to register save area. */
503 rtx insn;
505 total_frame_size = nios2_compute_frame_layout ();
507 if (flag_stack_usage_info)
508 current_function_static_stack_size = total_frame_size;
510 /* Decrement the stack pointer. */
511 if (!SMALL_INT (total_frame_size))
513 /* We need an intermediary point, this will point at the spill block. */
514 insn = emit_insn
515 (gen_add2_insn (stack_pointer_rtx,
516 gen_int_mode (cfun->machine->save_regs_offset
517 - total_frame_size, Pmode)));
518 RTX_FRAME_RELATED_P (insn) = 1;
519 save_regs_base = 0;
520 sp_offset = -cfun->machine->save_regs_offset;
522 else if (total_frame_size)
524 insn = emit_insn (gen_add2_insn (stack_pointer_rtx,
525 gen_int_mode (-total_frame_size,
526 Pmode)));
527 RTX_FRAME_RELATED_P (insn) = 1;
528 save_regs_base = cfun->machine->save_regs_offset;
529 sp_offset = 0;
531 else
532 save_regs_base = sp_offset = 0;
534 if (crtl->limit_stack)
535 nios2_emit_stack_limit_check ();
537 save_offset = save_regs_base + cfun->machine->save_reg_size;
539 for (regno = LAST_GP_REG; regno > 0; regno--)
540 if (cfun->machine->save_mask & (1 << regno))
542 save_offset -= 4;
543 save_reg (regno, save_offset);
546 if (frame_pointer_needed)
548 int fp_save_offset = save_regs_base + cfun->machine->fp_save_offset;
549 insn = emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
550 stack_pointer_rtx,
551 gen_int_mode (fp_save_offset, Pmode)));
552 RTX_FRAME_RELATED_P (insn) = 1;
555 if (sp_offset)
557 rtx sp_adjust
558 = gen_rtx_SET (stack_pointer_rtx,
559 plus_constant (Pmode, stack_pointer_rtx, sp_offset));
560 if (SMALL_INT (sp_offset))
561 insn = emit_insn (sp_adjust);
562 else
564 rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
565 emit_move_insn (tmp, gen_int_mode (sp_offset, Pmode));
566 insn = emit_insn (gen_add2_insn (stack_pointer_rtx, tmp));
567 /* Attach the sp_adjust as a note indicating what happened. */
568 add_reg_note (insn, REG_FRAME_RELATED_EXPR, sp_adjust);
570 RTX_FRAME_RELATED_P (insn) = 1;
572 if (crtl->limit_stack)
573 nios2_emit_stack_limit_check ();
576 /* Load the PIC register if needed. */
577 if (crtl->uses_pic_offset_table)
578 nios2_load_pic_register ();
580 /* If we are profiling, make sure no instructions are scheduled before
581 the call to mcount. */
582 if (crtl->profile)
583 emit_insn (gen_blockage ());
586 void
587 nios2_expand_epilogue (bool sibcall_p)
589 rtx insn, cfa_adj;
590 int total_frame_size;
591 int sp_adjust, save_offset;
592 unsigned int regno;
594 if (!sibcall_p && nios2_can_use_return_insn ())
596 emit_jump_insn (gen_return ());
597 return;
600 emit_insn (gen_blockage ());
602 total_frame_size = nios2_compute_frame_layout ();
603 if (frame_pointer_needed)
605 /* Recover the stack pointer. */
606 insn = emit_insn (gen_add3_insn
607 (stack_pointer_rtx, hard_frame_pointer_rtx,
608 gen_int_mode (-cfun->machine->fp_save_offset, Pmode)));
609 cfa_adj = plus_constant (Pmode, stack_pointer_rtx,
610 (total_frame_size
611 - cfun->machine->save_regs_offset));
612 add_reg_note (insn, REG_CFA_DEF_CFA, cfa_adj);
613 RTX_FRAME_RELATED_P (insn) = 1;
615 save_offset = 0;
616 sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
618 else if (!SMALL_INT (total_frame_size))
620 rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
621 emit_move_insn (tmp, gen_int_mode (cfun->machine->save_regs_offset,
622 Pmode));
623 insn = emit_insn (gen_add2_insn (stack_pointer_rtx, tmp));
624 cfa_adj = gen_rtx_SET (stack_pointer_rtx,
625 plus_constant (Pmode, stack_pointer_rtx,
626 cfun->machine->save_regs_offset));
627 add_reg_note (insn, REG_CFA_ADJUST_CFA, cfa_adj);
628 RTX_FRAME_RELATED_P (insn) = 1;
629 save_offset = 0;
630 sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
632 else
634 save_offset = cfun->machine->save_regs_offset;
635 sp_adjust = total_frame_size;
638 save_offset += cfun->machine->save_reg_size;
640 for (regno = LAST_GP_REG; regno > 0; regno--)
641 if (cfun->machine->save_mask & (1 << regno))
643 save_offset -= 4;
644 restore_reg (regno, save_offset);
647 if (sp_adjust)
649 insn = emit_insn (gen_add2_insn (stack_pointer_rtx,
650 gen_int_mode (sp_adjust, Pmode)));
651 cfa_adj = gen_rtx_SET (stack_pointer_rtx,
652 plus_constant (Pmode, stack_pointer_rtx,
653 sp_adjust));
654 add_reg_note (insn, REG_CFA_ADJUST_CFA, cfa_adj);
655 RTX_FRAME_RELATED_P (insn) = 1;
658 /* Add in the __builtin_eh_return stack adjustment. */
659 if (crtl->calls_eh_return)
660 emit_insn (gen_add2_insn (stack_pointer_rtx, EH_RETURN_STACKADJ_RTX));
662 if (!sibcall_p)
663 emit_jump_insn (gen_simple_return ());
666 /* Implement RETURN_ADDR_RTX. Note, we do not support moving
667 back to a previous frame. */
669 nios2_get_return_address (int count)
671 if (count != 0)
672 return const0_rtx;
674 return get_hard_reg_initial_val (Pmode, RA_REGNO);
677 /* Emit code to change the current function's return address to
678 ADDRESS. SCRATCH is available as a scratch register, if needed.
679 ADDRESS and SCRATCH are both word-mode GPRs. */
680 void
681 nios2_set_return_address (rtx address, rtx scratch)
683 nios2_compute_frame_layout ();
684 if (cfun->machine->save_mask & (1 << RA_REGNO))
686 unsigned offset = cfun->machine->save_reg_size - 4;
687 rtx base;
689 if (frame_pointer_needed)
690 base = hard_frame_pointer_rtx;
691 else
693 base = stack_pointer_rtx;
694 offset += cfun->machine->save_regs_offset;
696 if (!SMALL_INT (offset))
698 emit_move_insn (scratch, gen_int_mode (offset, Pmode));
699 emit_insn (gen_add2_insn (scratch, base));
700 base = scratch;
701 offset = 0;
704 if (offset)
705 base = plus_constant (Pmode, base, offset);
706 emit_move_insn (gen_rtx_MEM (Pmode, base), address);
708 else
709 emit_move_insn (gen_rtx_REG (Pmode, RA_REGNO), address);
712 /* Implement FUNCTION_PROFILER macro. */
713 void
714 nios2_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
716 fprintf (file, "\tmov\tr8, ra\n");
717 if (flag_pic == 1)
719 fprintf (file, "\tnextpc\tr2\n");
720 fprintf (file, "\t1: movhi\tr3, %%hiadj(_gp_got - 1b)\n");
721 fprintf (file, "\taddi\tr3, r3, %%lo(_gp_got - 1b)\n");
722 fprintf (file, "\tadd\tr2, r2, r3\n");
723 fprintf (file, "\tldw\tr2, %%call(_mcount)(r2)\n");
724 fprintf (file, "\tcallr\tr2\n");
726 else if (flag_pic == 2)
728 fprintf (file, "\tnextpc\tr2\n");
729 fprintf (file, "\t1: movhi\tr3, %%hiadj(_gp_got - 1b)\n");
730 fprintf (file, "\taddi\tr3, r3, %%lo(_gp_got - 1b)\n");
731 fprintf (file, "\tadd\tr2, r2, r3\n");
732 fprintf (file, "\tmovhi\tr3, %%call_hiadj(_mcount)\n");
733 fprintf (file, "\taddi\tr3, r3, %%call_lo(_mcount)\n");
734 fprintf (file, "\tadd\tr3, r2, r3\n");
735 fprintf (file, "\tldw\tr2, 0(r3)\n");
736 fprintf (file, "\tcallr\tr2\n");
738 else
739 fprintf (file, "\tcall\t_mcount\n");
740 fprintf (file, "\tmov\tra, r8\n");
743 /* Dump stack layout. */
744 static void
745 nios2_dump_frame_layout (FILE *file)
747 fprintf (file, "\t%s Current Frame Info\n", ASM_COMMENT_START);
748 fprintf (file, "\t%s total_size = %d\n", ASM_COMMENT_START,
749 cfun->machine->total_size);
750 fprintf (file, "\t%s var_size = %d\n", ASM_COMMENT_START,
751 cfun->machine->var_size);
752 fprintf (file, "\t%s args_size = %d\n", ASM_COMMENT_START,
753 cfun->machine->args_size);
754 fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START,
755 cfun->machine->save_reg_size);
756 fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START,
757 cfun->machine->initialized);
758 fprintf (file, "\t%s save_regs_offset = %d\n", ASM_COMMENT_START,
759 cfun->machine->save_regs_offset);
760 fprintf (file, "\t%s is_leaf = %d\n", ASM_COMMENT_START,
761 crtl->is_leaf);
762 fprintf (file, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START,
763 frame_pointer_needed);
764 fprintf (file, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START,
765 crtl->args.pretend_args_size);
768 /* Return true if REGNO should be saved in the prologue. */
769 static bool
770 prologue_saved_reg_p (unsigned regno)
772 gcc_assert (GP_REG_P (regno));
774 if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
775 return true;
777 if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
778 return true;
780 if (regno == PIC_OFFSET_TABLE_REGNUM && crtl->uses_pic_offset_table)
781 return true;
783 if (regno == RA_REGNO && df_regs_ever_live_p (RA_REGNO))
784 return true;
786 return false;
789 /* Implement TARGET_CAN_ELIMINATE. */
790 static bool
791 nios2_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
793 if (to == STACK_POINTER_REGNUM)
794 return !frame_pointer_needed;
795 return true;
798 /* Implement INITIAL_ELIMINATION_OFFSET macro. */
800 nios2_initial_elimination_offset (int from, int to)
802 int offset;
804 nios2_compute_frame_layout ();
806 /* Set OFFSET to the offset from the stack pointer. */
807 switch (from)
809 case FRAME_POINTER_REGNUM:
810 offset = cfun->machine->args_size;
811 break;
813 case ARG_POINTER_REGNUM:
814 offset = cfun->machine->total_size;
815 offset -= crtl->args.pretend_args_size;
816 break;
818 default:
819 gcc_unreachable ();
822 /* If we are asked for the frame pointer offset, then adjust OFFSET
823 by the offset from the frame pointer to the stack pointer. */
824 if (to == HARD_FRAME_POINTER_REGNUM)
825 offset -= (cfun->machine->save_regs_offset
826 + cfun->machine->fp_save_offset);
828 return offset;
831 /* Return nonzero if this function is known to have a null epilogue.
832 This allows the optimizer to omit jumps to jumps if no stack
833 was created. */
835 nios2_can_use_return_insn (void)
837 if (!reload_completed || crtl->profile)
838 return 0;
840 return nios2_compute_frame_layout () == 0;
844 /* Check and signal some warnings/errors on FPU insn options. */
845 static void
846 nios2_custom_check_insns (void)
848 unsigned int i, j;
849 bool errors = false;
851 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
852 if (N2FPU_ENABLED_P (i) && N2FPU_DOUBLE_P (i))
854 for (j = 0; j < ARRAY_SIZE (nios2_fpu_insn); j++)
855 if (N2FPU_DOUBLE_REQUIRED_P (j) && ! N2FPU_ENABLED_P (j))
857 error ("switch %<-mcustom-%s%> is required for double "
858 "precision floating point", N2FPU_NAME (j));
859 errors = true;
861 break;
864 /* Warn if the user has certain exotic operations that won't get used
865 without -funsafe-math-optimizations. See expand_builtin () in
866 builtins.c. */
867 if (!flag_unsafe_math_optimizations)
868 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
869 if (N2FPU_ENABLED_P (i) && N2FPU_UNSAFE_P (i))
870 warning (0, "switch %<-mcustom-%s%> has no effect unless "
871 "-funsafe-math-optimizations is specified", N2FPU_NAME (i));
873 /* Warn if the user is trying to use -mcustom-fmins et. al, that won't
874 get used without -ffinite-math-only. See fold_builtin_fmin_fmax ()
875 in builtins.c. */
876 if (!flag_finite_math_only)
877 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
878 if (N2FPU_ENABLED_P (i) && N2FPU_FINITE_P (i))
879 warning (0, "switch %<-mcustom-%s%> has no effect unless "
880 "-ffinite-math-only is specified", N2FPU_NAME (i));
882 /* Warn if the user is trying to use a custom rounding instruction
883 that won't get used without -fno-math-errno. See
884 expand_builtin_int_roundingfn_2 () in builtins.c. */
885 if (flag_errno_math)
886 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
887 if (N2FPU_ENABLED_P (i) && N2FPU_NO_ERRNO_P (i))
888 warning (0, "switch %<-mcustom-%s%> has no effect unless "
889 "-fno-math-errno is specified", N2FPU_NAME (i));
891 if (errors || custom_code_conflict)
892 fatal_error (input_location,
893 "conflicting use of -mcustom switches, target attributes, "
894 "and/or __builtin_custom_ functions");
897 static void
898 nios2_set_fpu_custom_code (enum n2fpu_code code, int n, bool override_p)
900 if (override_p || N2FPU_N (code) == -1)
901 N2FPU_N (code) = n;
902 nios2_register_custom_code (n, CCS_FPU, (int) code);
905 /* Type to represent a standard FPU config. */
906 struct nios2_fpu_config
908 const char *name;
909 bool set_sp_constants;
910 int code[n2fpu_code_num];
913 #define NIOS2_FPU_CONFIG_NUM 3
914 static struct nios2_fpu_config custom_fpu_config[NIOS2_FPU_CONFIG_NUM];
916 static void
917 nios2_init_fpu_configs (void)
919 struct nios2_fpu_config* cfg;
920 int i = 0;
921 #define NEXT_FPU_CONFIG \
922 do { \
923 cfg = &custom_fpu_config[i++]; \
924 memset (cfg, -1, sizeof (struct nios2_fpu_config));\
925 } while (0)
927 NEXT_FPU_CONFIG;
928 cfg->name = "60-1";
929 cfg->set_sp_constants = true;
930 cfg->code[n2fpu_fmuls] = 252;
931 cfg->code[n2fpu_fadds] = 253;
932 cfg->code[n2fpu_fsubs] = 254;
934 NEXT_FPU_CONFIG;
935 cfg->name = "60-2";
936 cfg->set_sp_constants = true;
937 cfg->code[n2fpu_fmuls] = 252;
938 cfg->code[n2fpu_fadds] = 253;
939 cfg->code[n2fpu_fsubs] = 254;
940 cfg->code[n2fpu_fdivs] = 255;
942 NEXT_FPU_CONFIG;
943 cfg->name = "72-3";
944 cfg->set_sp_constants = true;
945 cfg->code[n2fpu_floatus] = 243;
946 cfg->code[n2fpu_fixsi] = 244;
947 cfg->code[n2fpu_floatis] = 245;
948 cfg->code[n2fpu_fcmpgts] = 246;
949 cfg->code[n2fpu_fcmples] = 249;
950 cfg->code[n2fpu_fcmpeqs] = 250;
951 cfg->code[n2fpu_fcmpnes] = 251;
952 cfg->code[n2fpu_fmuls] = 252;
953 cfg->code[n2fpu_fadds] = 253;
954 cfg->code[n2fpu_fsubs] = 254;
955 cfg->code[n2fpu_fdivs] = 255;
957 #undef NEXT_FPU_CONFIG
958 gcc_assert (i == NIOS2_FPU_CONFIG_NUM);
961 static struct nios2_fpu_config *
962 nios2_match_custom_fpu_cfg (const char *cfgname, const char *endp)
964 int i;
965 for (i = 0; i < NIOS2_FPU_CONFIG_NUM; i++)
967 bool match = !(endp != NULL
968 ? strncmp (custom_fpu_config[i].name, cfgname,
969 endp - cfgname)
970 : strcmp (custom_fpu_config[i].name, cfgname));
971 if (match)
972 return &custom_fpu_config[i];
974 return NULL;
977 /* Use CFGNAME to lookup FPU config, ENDP if not NULL marks end of string.
978 OVERRIDE is true if loaded config codes should overwrite current state. */
979 static void
980 nios2_handle_custom_fpu_cfg (const char *cfgname, const char *endp,
981 bool override)
983 struct nios2_fpu_config *cfg = nios2_match_custom_fpu_cfg (cfgname, endp);
984 if (cfg)
986 unsigned int i;
987 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
988 if (cfg->code[i] >= 0)
989 nios2_set_fpu_custom_code ((enum n2fpu_code) i, cfg->code[i],
990 override);
991 if (cfg->set_sp_constants)
992 flag_single_precision_constant = 1;
994 else
995 warning (0, "ignoring unrecognized switch %<-mcustom-fpu-cfg%> "
996 "value %<%s%>", cfgname);
998 /* Guard against errors in the standard configurations. */
999 nios2_custom_check_insns ();
1002 /* Check individual FPU insn options, and register custom code. */
1003 static void
1004 nios2_handle_custom_fpu_insn_option (int fpu_insn_index)
1006 int param = N2FPU_N (fpu_insn_index);
1008 if (0 <= param && param <= 255)
1009 nios2_register_custom_code (param, CCS_FPU, fpu_insn_index);
1011 /* Valid values are 0-255, but also allow -1 so that the
1012 -mno-custom-<opt> switches work. */
1013 else if (param != -1)
1014 error ("switch %<-mcustom-%s%> value %d must be between 0 and 255",
1015 N2FPU_NAME (fpu_insn_index), param);
1018 /* Allocate a chunk of memory for per-function machine-dependent data. */
1019 static struct machine_function *
1020 nios2_init_machine_status (void)
1022 return ggc_cleared_alloc<machine_function> ();
1025 /* Implement TARGET_OPTION_OVERRIDE. */
1026 static void
1027 nios2_option_override (void)
1029 unsigned int i;
1031 #ifdef SUBTARGET_OVERRIDE_OPTIONS
1032 SUBTARGET_OVERRIDE_OPTIONS;
1033 #endif
1035 /* Check for unsupported options. */
1036 if (flag_pic && !TARGET_LINUX_ABI)
1037 sorry ("position-independent code requires the Linux ABI");
1039 /* Function to allocate machine-dependent function status. */
1040 init_machine_status = &nios2_init_machine_status;
1042 nios2_section_threshold
1043 = (global_options_set.x_g_switch_value
1044 ? g_switch_value : NIOS2_DEFAULT_GVALUE);
1046 if (nios2_gpopt_option == gpopt_unspecified)
1048 /* Default to -mgpopt unless -fpic or -fPIC. */
1049 if (flag_pic)
1050 nios2_gpopt_option = gpopt_none;
1051 else
1052 nios2_gpopt_option = gpopt_local;
1055 /* If we don't have mul, we don't have mulx either! */
1056 if (!TARGET_HAS_MUL && TARGET_HAS_MULX)
1057 target_flags &= ~MASK_HAS_MULX;
1059 /* Initialize default FPU configurations. */
1060 nios2_init_fpu_configs ();
1062 /* Set up default handling for floating point custom instructions.
1064 Putting things in this order means that the -mcustom-fpu-cfg=
1065 switch will always be overridden by individual -mcustom-fadds=
1066 switches, regardless of the order in which they were specified
1067 on the command line.
1069 This behavior of prioritization of individual -mcustom-<insn>=
1070 options before the -mcustom-fpu-cfg= switch is maintained for
1071 compatibility. */
1072 if (nios2_custom_fpu_cfg_string && *nios2_custom_fpu_cfg_string)
1073 nios2_handle_custom_fpu_cfg (nios2_custom_fpu_cfg_string, NULL, false);
1075 /* Handle options for individual FPU insns. */
1076 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
1077 nios2_handle_custom_fpu_insn_option (i);
1079 nios2_custom_check_insns ();
1081 /* Save the initial options in case the user does function specific
1082 options. */
1083 target_option_default_node = target_option_current_node
1084 = build_target_option_node (&global_options);
1088 /* Return true if CST is a constant within range of movi/movui/movhi. */
1089 static bool
1090 nios2_simple_const_p (const_rtx cst)
1092 HOST_WIDE_INT val = INTVAL (cst);
1093 return SMALL_INT (val) || SMALL_INT_UNSIGNED (val) || UPPER16_INT (val);
1096 /* Compute a (partial) cost for rtx X. Return true if the complete
1097 cost has been computed, and false if subexpressions should be
1098 scanned. In either case, *TOTAL contains the cost result. */
1099 static bool
1100 nios2_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
1101 int opno ATTRIBUTE_UNUSED,
1102 int *total, bool speed ATTRIBUTE_UNUSED)
1104 switch (code)
1106 case CONST_INT:
1107 if (INTVAL (x) == 0)
1109 *total = COSTS_N_INSNS (0);
1110 return true;
1112 else if (nios2_simple_const_p (x))
1114 *total = COSTS_N_INSNS (2);
1115 return true;
1117 else
1119 *total = COSTS_N_INSNS (4);
1120 return true;
1123 case LABEL_REF:
1124 case SYMBOL_REF:
1125 case CONST:
1126 case CONST_DOUBLE:
1128 *total = COSTS_N_INSNS (4);
1129 return true;
1132 case AND:
1134 /* Recognize 'nor' insn pattern. */
1135 if (GET_CODE (XEXP (x, 0)) == NOT
1136 && GET_CODE (XEXP (x, 1)) == NOT)
1138 *total = COSTS_N_INSNS (1);
1139 return true;
1141 return false;
1144 case MULT:
1146 *total = COSTS_N_INSNS (1);
1147 return false;
1149 case SIGN_EXTEND:
1151 *total = COSTS_N_INSNS (3);
1152 return false;
1154 case ZERO_EXTEND:
1156 *total = COSTS_N_INSNS (1);
1157 return false;
1160 default:
1161 return false;
1165 /* Implement TARGET_PREFERRED_RELOAD_CLASS. */
1166 static reg_class_t
1167 nios2_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t regclass)
1169 return regclass == NO_REGS ? GENERAL_REGS : regclass;
1172 /* Emit a call to __tls_get_addr. TI is the argument to this function.
1173 RET is an RTX for the return value location. The entire insn sequence
1174 is returned. */
1175 static GTY(()) rtx nios2_tls_symbol;
1177 static rtx
1178 nios2_call_tls_get_addr (rtx ti)
1180 rtx arg = gen_rtx_REG (Pmode, FIRST_ARG_REGNO);
1181 rtx ret = gen_rtx_REG (Pmode, FIRST_RETVAL_REGNO);
1182 rtx fn, insn;
1184 if (!nios2_tls_symbol)
1185 nios2_tls_symbol = init_one_libfunc ("__tls_get_addr");
1187 emit_move_insn (arg, ti);
1188 fn = gen_rtx_MEM (QImode, nios2_tls_symbol);
1189 insn = emit_call_insn (gen_call_value (ret, fn, const0_rtx));
1190 RTL_CONST_CALL_P (insn) = 1;
1191 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), ret);
1192 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), arg);
1194 return ret;
1197 /* Return true for large offsets requiring hiadj/lo relocation pairs. */
1198 static bool
1199 nios2_large_offset_p (int unspec)
1201 gcc_assert (nios2_unspec_reloc_name (unspec) != NULL);
1203 if (flag_pic == 2
1204 /* FIXME: TLS GOT offset relocations will eventually also get this
1205 treatment, after binutils support for those are also completed. */
1206 && (unspec == UNSPEC_PIC_SYM || unspec == UNSPEC_PIC_CALL_SYM))
1207 return true;
1209 /* 'gotoff' offsets are always hiadj/lo. */
1210 if (unspec == UNSPEC_PIC_GOTOFF_SYM)
1211 return true;
1213 return false;
1216 /* Return true for conforming unspec relocations. Also used in
1217 constraints.md and predicates.md. */
1218 bool
1219 nios2_unspec_reloc_p (rtx op)
1221 return (GET_CODE (op) == CONST
1222 && GET_CODE (XEXP (op, 0)) == UNSPEC
1223 && ! nios2_large_offset_p (XINT (XEXP (op, 0), 1)));
1226 /* Helper to generate unspec constant. */
1227 static rtx
1228 nios2_unspec_offset (rtx loc, int unspec)
1230 return gen_rtx_CONST (Pmode, gen_rtx_UNSPEC (Pmode, gen_rtvec (1, loc),
1231 unspec));
1234 /* Generate GOT pointer based address with large offset. */
1235 static rtx
1236 nios2_large_got_address (rtx offset, rtx tmp)
1238 if (!tmp)
1239 tmp = gen_reg_rtx (Pmode);
1240 emit_move_insn (tmp, offset);
1241 return gen_rtx_PLUS (Pmode, tmp, pic_offset_table_rtx);
1244 /* Generate a GOT pointer based address. */
1245 static rtx
1246 nios2_got_address (rtx loc, int unspec)
1248 rtx offset = nios2_unspec_offset (loc, unspec);
1249 crtl->uses_pic_offset_table = 1;
1251 if (nios2_large_offset_p (unspec))
1252 return force_reg (Pmode, nios2_large_got_address (offset, NULL_RTX));
1254 return gen_rtx_PLUS (Pmode, pic_offset_table_rtx, offset);
1257 /* Generate the code to access LOC, a thread local SYMBOL_REF. The
1258 return value will be a valid address and move_operand (either a REG
1259 or a LO_SUM). */
1260 static rtx
1261 nios2_legitimize_tls_address (rtx loc)
1263 rtx tmp, mem, tp;
1264 enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
1266 switch (model)
1268 case TLS_MODEL_GLOBAL_DYNAMIC:
1269 tmp = gen_reg_rtx (Pmode);
1270 emit_move_insn (tmp, nios2_got_address (loc, UNSPEC_ADD_TLS_GD));
1271 return nios2_call_tls_get_addr (tmp);
1273 case TLS_MODEL_LOCAL_DYNAMIC:
1274 tmp = gen_reg_rtx (Pmode);
1275 emit_move_insn (tmp, nios2_got_address (loc, UNSPEC_ADD_TLS_LDM));
1276 return gen_rtx_PLUS (Pmode, nios2_call_tls_get_addr (tmp),
1277 nios2_unspec_offset (loc, UNSPEC_ADD_TLS_LDO));
1279 case TLS_MODEL_INITIAL_EXEC:
1280 tmp = gen_reg_rtx (Pmode);
1281 mem = gen_const_mem (Pmode, nios2_got_address (loc, UNSPEC_LOAD_TLS_IE));
1282 emit_move_insn (tmp, mem);
1283 tp = gen_rtx_REG (Pmode, TP_REGNO);
1284 return gen_rtx_PLUS (Pmode, tp, tmp);
1286 case TLS_MODEL_LOCAL_EXEC:
1287 tp = gen_rtx_REG (Pmode, TP_REGNO);
1288 return gen_rtx_PLUS (Pmode, tp,
1289 nios2_unspec_offset (loc, UNSPEC_ADD_TLS_LE));
1290 default:
1291 gcc_unreachable ();
1295 /* Divide Support
1297 If -O3 is used, we want to output a table lookup for
1298 divides between small numbers (both num and den >= 0
1299 and < 0x10). The overhead of this method in the worst
1300 case is 40 bytes in the text section (10 insns) and
1301 256 bytes in the data section. Additional divides do
1302 not incur additional penalties in the data section.
1304 Code speed is improved for small divides by about 5x
1305 when using this method in the worse case (~9 cycles
1306 vs ~45). And in the worst case divides not within the
1307 table are penalized by about 10% (~5 cycles vs ~45).
1308 However in the typical case the penalty is not as bad
1309 because doing the long divide in only 45 cycles is
1310 quite optimistic.
1312 ??? would be nice to have some benchmarks other
1313 than Dhrystone to back this up.
1315 This bit of expansion is to create this instruction
1316 sequence as rtl.
1317 or $8, $4, $5
1318 slli $9, $4, 4
1319 cmpgeui $3, $8, 16
1320 beq $3, $0, .L3
1321 or $10, $9, $5
1322 add $12, $11, divide_table
1323 ldbu $2, 0($12)
1324 br .L1
1325 .L3:
1326 call slow_div
1327 .L1:
1328 # continue here with result in $2
1330 ??? Ideally I would like the libcall block to contain all
1331 of this code, but I don't know how to do that. What it
1332 means is that if the divide can be eliminated, it may not
1333 completely disappear.
1335 ??? The __divsi3_table label should ideally be moved out
1336 of this block and into a global. If it is placed into the
1337 sdata section we can save even more cycles by doing things
1338 gp relative. */
1339 void
1340 nios2_emit_expensive_div (rtx *operands, machine_mode mode)
1342 rtx or_result, shift_left_result;
1343 rtx lookup_value;
1344 rtx_code_label *lab1, *lab3;
1345 rtx insns;
1346 rtx libfunc;
1347 rtx final_result;
1348 rtx tmp;
1349 rtx table;
1351 /* It may look a little generic, but only SImode is supported for now. */
1352 gcc_assert (mode == SImode);
1353 libfunc = optab_libfunc (sdiv_optab, SImode);
1355 lab1 = gen_label_rtx ();
1356 lab3 = gen_label_rtx ();
1358 or_result = expand_simple_binop (SImode, IOR,
1359 operands[1], operands[2],
1360 0, 0, OPTAB_LIB_WIDEN);
1362 emit_cmp_and_jump_insns (or_result, GEN_INT (15), GTU, 0,
1363 GET_MODE (or_result), 0, lab3);
1364 JUMP_LABEL (get_last_insn ()) = lab3;
1366 shift_left_result = expand_simple_binop (SImode, ASHIFT,
1367 operands[1], GEN_INT (4),
1368 0, 0, OPTAB_LIB_WIDEN);
1370 lookup_value = expand_simple_binop (SImode, IOR,
1371 shift_left_result, operands[2],
1372 0, 0, OPTAB_LIB_WIDEN);
1373 table = gen_rtx_PLUS (SImode, lookup_value,
1374 gen_rtx_SYMBOL_REF (SImode, "__divsi3_table"));
1375 convert_move (operands[0], gen_rtx_MEM (QImode, table), 1);
1377 tmp = emit_jump_insn (gen_jump (lab1));
1378 JUMP_LABEL (tmp) = lab1;
1379 emit_barrier ();
1381 emit_label (lab3);
1382 LABEL_NUSES (lab3) = 1;
1384 start_sequence ();
1385 final_result = emit_library_call_value (libfunc, NULL_RTX,
1386 LCT_CONST, SImode, 2,
1387 operands[1], SImode,
1388 operands[2], SImode);
1390 insns = get_insns ();
1391 end_sequence ();
1392 emit_libcall_block (insns, operands[0], final_result,
1393 gen_rtx_DIV (SImode, operands[1], operands[2]));
1395 emit_label (lab1);
1396 LABEL_NUSES (lab1) = 1;
1400 /* Branches and compares. */
1402 /* Return in *ALT_CODE and *ALT_OP, an alternate equivalent constant
1403 comparison, e.g. >= 1 into > 0. */
1404 static void
1405 nios2_alternate_compare_const (enum rtx_code code, rtx op,
1406 enum rtx_code *alt_code, rtx *alt_op,
1407 machine_mode mode)
1409 HOST_WIDE_INT opval = INTVAL (op);
1410 enum rtx_code scode = signed_condition (code);
1411 bool dec_p = (scode == LT || scode == GE);
1413 if (code == EQ || code == NE)
1415 *alt_code = code;
1416 *alt_op = op;
1417 return;
1420 *alt_op = (dec_p
1421 ? gen_int_mode (opval - 1, mode)
1422 : gen_int_mode (opval + 1, mode));
1424 /* The required conversion between [>,>=] and [<,<=] is captured
1425 by a reverse + swap of condition codes. */
1426 *alt_code = reverse_condition (swap_condition (code));
1429 /* Test if the incremented/decremented value crosses the over/underflow
1430 boundary. Supposedly, such boundary cases should already be transformed
1431 into always-true/false or EQ conditions, so use an assertion here. */
1432 unsigned HOST_WIDE_INT alt_opval = INTVAL (*alt_op);
1433 if (code == scode)
1434 alt_opval ^= (1 << (GET_MODE_BITSIZE (mode) - 1));
1435 alt_opval &= GET_MODE_MASK (mode);
1436 gcc_assert (dec_p ? alt_opval != GET_MODE_MASK (mode) : alt_opval != 0);
1440 /* Return true if the constant comparison is supported by nios2. */
1441 static bool
1442 nios2_valid_compare_const_p (enum rtx_code code, rtx op)
1444 switch (code)
1446 case EQ: case NE: case GE: case LT:
1447 return SMALL_INT (INTVAL (op));
1448 case GEU: case LTU:
1449 return SMALL_INT_UNSIGNED (INTVAL (op));
1450 default:
1451 return false;
1455 /* Checks if the FPU comparison in *CMP, *OP1, and *OP2 can be supported in
1456 the current configuration. Perform modifications if MODIFY_P is true.
1457 Returns true if FPU compare can be done. */
1459 bool
1460 nios2_validate_fpu_compare (machine_mode mode, rtx *cmp, rtx *op1, rtx *op2,
1461 bool modify_p)
1463 bool rev_p = false;
1464 enum rtx_code code = GET_CODE (*cmp);
1466 if (!nios2_fpu_compare_enabled (code, mode))
1468 code = swap_condition (code);
1469 if (nios2_fpu_compare_enabled (code, mode))
1470 rev_p = true;
1471 else
1472 return false;
1475 if (modify_p)
1477 if (rev_p)
1479 rtx tmp = *op1;
1480 *op1 = *op2;
1481 *op2 = tmp;
1483 *op1 = force_reg (mode, *op1);
1484 *op2 = force_reg (mode, *op2);
1485 *cmp = gen_rtx_fmt_ee (code, mode, *op1, *op2);
1487 return true;
1490 /* Checks and modifies the comparison in *CMP, *OP1, and *OP2 into valid
1491 nios2 supported form. Returns true if success. */
1492 bool
1493 nios2_validate_compare (machine_mode mode, rtx *cmp, rtx *op1, rtx *op2)
1495 enum rtx_code code = GET_CODE (*cmp);
1496 enum rtx_code alt_code;
1497 rtx alt_op2;
1499 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
1500 return nios2_validate_fpu_compare (mode, cmp, op1, op2, true);
1502 if (!reg_or_0_operand (*op2, mode))
1504 /* Create alternate constant compare. */
1505 nios2_alternate_compare_const (code, *op2, &alt_code, &alt_op2, mode);
1507 /* If alterate op2 is zero(0), we can use it directly, possibly
1508 swapping the compare code. */
1509 if (alt_op2 == const0_rtx)
1511 code = alt_code;
1512 *op2 = alt_op2;
1513 goto check_rebuild_cmp;
1516 /* Check if either constant compare can be used. */
1517 if (nios2_valid_compare_const_p (code, *op2))
1518 return true;
1519 else if (nios2_valid_compare_const_p (alt_code, alt_op2))
1521 code = alt_code;
1522 *op2 = alt_op2;
1523 goto rebuild_cmp;
1526 /* We have to force op2 into a register now. Try to pick one
1527 with a lower cost. */
1528 if (! nios2_simple_const_p (*op2)
1529 && nios2_simple_const_p (alt_op2))
1531 code = alt_code;
1532 *op2 = alt_op2;
1534 *op2 = force_reg (SImode, *op2);
1536 check_rebuild_cmp:
1537 if (code == GT || code == GTU || code == LE || code == LEU)
1539 rtx t = *op1; *op1 = *op2; *op2 = t;
1540 code = swap_condition (code);
1542 rebuild_cmp:
1543 *cmp = gen_rtx_fmt_ee (code, mode, *op1, *op2);
1544 return true;
1548 /* Addressing Modes. */
1550 /* Implement TARGET_LEGITIMATE_CONSTANT_P. */
1551 static bool
1552 nios2_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1554 rtx base, offset;
1555 split_const (x, &base, &offset);
1556 return GET_CODE (base) != SYMBOL_REF || !SYMBOL_REF_TLS_MODEL (base);
1559 /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
1560 static bool
1561 nios2_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1563 return nios2_legitimate_constant_p (mode, x) == false;
1566 /* Return true if register REGNO is a valid base register.
1567 STRICT_P is true if REG_OK_STRICT is in effect. */
1569 bool
1570 nios2_regno_ok_for_base_p (int regno, bool strict_p)
1572 if (!HARD_REGISTER_NUM_P (regno))
1574 if (!strict_p)
1575 return true;
1577 if (!reg_renumber)
1578 return false;
1580 regno = reg_renumber[regno];
1583 /* The fake registers will be eliminated to either the stack or
1584 hard frame pointer, both of which are usually valid base registers.
1585 Reload deals with the cases where the eliminated form isn't valid. */
1586 return (GP_REG_P (regno)
1587 || regno == FRAME_POINTER_REGNUM
1588 || regno == ARG_POINTER_REGNUM);
1591 /* Return true if the address expression formed by BASE + OFFSET is
1592 valid. */
1593 static bool
1594 nios2_valid_addr_expr_p (rtx base, rtx offset, bool strict_p)
1596 if (!strict_p && GET_CODE (base) == SUBREG)
1597 base = SUBREG_REG (base);
1598 return (REG_P (base)
1599 && nios2_regno_ok_for_base_p (REGNO (base), strict_p)
1600 && (offset == NULL_RTX
1601 || const_arith_operand (offset, Pmode)
1602 || nios2_unspec_reloc_p (offset)));
1605 /* Implement TARGET_LEGITIMATE_ADDRESS_P. */
1606 static bool
1607 nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
1608 rtx operand, bool strict_p)
1610 switch (GET_CODE (operand))
1612 /* Direct. */
1613 case SYMBOL_REF:
1614 if (SYMBOL_REF_TLS_MODEL (operand))
1615 return false;
1617 if (nios2_symbol_ref_in_small_data_p (operand))
1618 return true;
1620 /* Else, fall through. */
1621 case LABEL_REF:
1622 case CONST_INT:
1623 case CONST:
1624 case CONST_DOUBLE:
1625 return false;
1627 /* Register indirect. */
1628 case REG:
1629 return nios2_regno_ok_for_base_p (REGNO (operand), strict_p);
1631 /* Register indirect with displacement. */
1632 case PLUS:
1634 rtx op0 = XEXP (operand, 0);
1635 rtx op1 = XEXP (operand, 1);
1637 return (nios2_valid_addr_expr_p (op0, op1, strict_p)
1638 || nios2_valid_addr_expr_p (op1, op0, strict_p));
1641 default:
1642 break;
1644 return false;
1647 /* Return true if SECTION is a small section name. */
1648 static bool
1649 nios2_small_section_name_p (const char *section)
1651 return (strcmp (section, ".sbss") == 0
1652 || strncmp (section, ".sbss.", 6) == 0
1653 || strcmp (section, ".sdata") == 0
1654 || strncmp (section, ".sdata.", 7) == 0);
1657 /* Return true if EXP should be placed in the small data section. */
1658 static bool
1659 nios2_in_small_data_p (const_tree exp)
1661 /* We want to merge strings, so we never consider them small data. */
1662 if (TREE_CODE (exp) == STRING_CST)
1663 return false;
1665 if (TREE_CODE (exp) == VAR_DECL)
1667 if (DECL_SECTION_NAME (exp))
1669 const char *section = DECL_SECTION_NAME (exp);
1670 if (nios2_small_section_name_p (section))
1671 return true;
1673 else
1675 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
1677 /* If this is an incomplete type with size 0, then we can't put it
1678 in sdata because it might be too big when completed. */
1679 if (size > 0
1680 && (unsigned HOST_WIDE_INT) size <= nios2_section_threshold)
1681 return true;
1685 return false;
1688 /* Return true if symbol is in small data section. */
1690 bool
1691 nios2_symbol_ref_in_small_data_p (rtx sym)
1693 tree decl;
1695 gcc_assert (GET_CODE (sym) == SYMBOL_REF);
1696 decl = SYMBOL_REF_DECL (sym);
1698 /* TLS variables are not accessed through the GP. */
1699 if (SYMBOL_REF_TLS_MODEL (sym) != 0)
1700 return false;
1702 /* If the user has explicitly placed the symbol in a small data section
1703 via an attribute, generate gp-relative addressing even if the symbol
1704 is external, weak, or larger than we'd automatically put in the
1705 small data section. OTOH, if the symbol is located in some
1706 non-small-data section, we can't use gp-relative accesses on it
1707 unless the user has requested gpopt_data or gpopt_all. */
1709 switch (nios2_gpopt_option)
1711 case gpopt_none:
1712 /* Don't generate a gp-relative addressing mode if that's been
1713 disabled. */
1714 return false;
1716 case gpopt_local:
1717 /* Use GP-relative addressing for small data symbols that are
1718 not external or weak, plus any symbols that have explicitly
1719 been placed in a small data section. */
1720 if (decl && DECL_SECTION_NAME (decl))
1721 return nios2_small_section_name_p (DECL_SECTION_NAME (decl));
1722 return (SYMBOL_REF_SMALL_P (sym)
1723 && !SYMBOL_REF_EXTERNAL_P (sym)
1724 && !(decl && DECL_WEAK (decl)));
1726 case gpopt_global:
1727 /* Use GP-relative addressing for small data symbols, even if
1728 they are external or weak. Note that SYMBOL_REF_SMALL_P
1729 is also true of symbols that have explicitly been placed
1730 in a small data section. */
1731 return SYMBOL_REF_SMALL_P (sym);
1733 case gpopt_data:
1734 /* Use GP-relative addressing for all data symbols regardless
1735 of the object size, but not for code symbols. This option
1736 is equivalent to the user asserting that the entire data
1737 section is accessible from the GP. */
1738 return !SYMBOL_REF_FUNCTION_P (sym);
1740 case gpopt_all:
1741 /* Use GP-relative addressing for everything, including code.
1742 Effectively, the user has asserted that the entire program
1743 fits within the 64K range of the GP offset. */
1744 return true;
1746 default:
1747 /* We shouldn't get here. */
1748 return false;
1752 /* Implement TARGET_SECTION_TYPE_FLAGS. */
1754 static unsigned int
1755 nios2_section_type_flags (tree decl, const char *name, int reloc)
1757 unsigned int flags;
1759 flags = default_section_type_flags (decl, name, reloc);
1761 if (nios2_small_section_name_p (name))
1762 flags |= SECTION_SMALL;
1764 return flags;
1767 /* Return true if SYMBOL_REF X binds locally. */
1769 static bool
1770 nios2_symbol_binds_local_p (const_rtx x)
1772 return (SYMBOL_REF_DECL (x)
1773 ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
1774 : SYMBOL_REF_LOCAL_P (x));
1777 /* Position independent code related. */
1779 /* Emit code to load the PIC register. */
1780 static void
1781 nios2_load_pic_register (void)
1783 rtx tmp = gen_rtx_REG (Pmode, TEMP_REG_NUM);
1785 emit_insn (gen_load_got_register (pic_offset_table_rtx, tmp));
1786 emit_insn (gen_add3_insn (pic_offset_table_rtx, pic_offset_table_rtx, tmp));
1789 /* Generate a PIC address as a MEM rtx. */
1790 static rtx
1791 nios2_load_pic_address (rtx sym, int unspec, rtx tmp)
1793 if (flag_pic == 2
1794 && GET_CODE (sym) == SYMBOL_REF
1795 && nios2_symbol_binds_local_p (sym))
1796 /* Under -fPIC, generate a GOTOFF address for local symbols. */
1798 rtx offset = nios2_unspec_offset (sym, UNSPEC_PIC_GOTOFF_SYM);
1799 crtl->uses_pic_offset_table = 1;
1800 return nios2_large_got_address (offset, tmp);
1803 return gen_const_mem (Pmode, nios2_got_address (sym, unspec));
1806 /* Nonzero if the constant value X is a legitimate general operand
1807 when generating PIC code. It is given that flag_pic is on and
1808 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
1809 bool
1810 nios2_legitimate_pic_operand_p (rtx x)
1812 if (GET_CODE (x) == CONST
1813 && GET_CODE (XEXP (x, 0)) == UNSPEC
1814 && nios2_large_offset_p (XINT (XEXP (x, 0), 1)))
1815 return true;
1817 return ! (GET_CODE (x) == SYMBOL_REF
1818 || GET_CODE (x) == LABEL_REF || GET_CODE (x) == CONST);
1821 /* Return TRUE if X is a thread-local symbol. */
1822 static bool
1823 nios2_tls_symbol_p (rtx x)
1825 return (targetm.have_tls && GET_CODE (x) == SYMBOL_REF
1826 && SYMBOL_REF_TLS_MODEL (x) != 0);
1829 /* Legitimize addresses that are CONSTANT_P expressions. */
1830 static rtx
1831 nios2_legitimize_constant_address (rtx addr)
1833 rtx base, offset;
1834 split_const (addr, &base, &offset);
1836 if (nios2_tls_symbol_p (base))
1837 base = nios2_legitimize_tls_address (base);
1838 else if (flag_pic)
1839 base = nios2_load_pic_address (base, UNSPEC_PIC_SYM, NULL_RTX);
1840 else
1841 return addr;
1843 if (offset != const0_rtx)
1845 gcc_assert (can_create_pseudo_p ());
1846 return gen_rtx_PLUS (Pmode, force_reg (Pmode, base),
1847 (CONST_INT_P (offset)
1848 ? (SMALL_INT (INTVAL (offset))
1849 ? offset : force_reg (Pmode, offset))
1850 : offset));
1852 return base;
1855 /* Implement TARGET_LEGITIMIZE_ADDRESS. */
1856 static rtx
1857 nios2_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
1858 machine_mode mode ATTRIBUTE_UNUSED)
1860 if (CONSTANT_P (x))
1861 return nios2_legitimize_constant_address (x);
1863 /* For the TLS LE (Local Exec) model, the compiler may try to
1864 combine constant offsets with unspec relocs, creating address RTXs
1865 looking like this:
1866 (plus:SI (reg:SI 23 r23)
1867 (const:SI
1868 (plus:SI
1869 (unspec:SI [(symbol_ref:SI ("var"))] UNSPEC_ADD_TLS_LE)
1870 (const_int 48 [0x30]))))
1872 This usually happens when 'var' is a thread-local struct variable,
1873 and access of a field in var causes the addend.
1875 We typically want this combining, so transform the above into this
1876 form, which is allowed:
1877 (plus:SI (reg:SI 23 r23)
1878 (const:SI
1879 (unspec:SI
1880 [(const:SI
1881 (plus:SI (symbol_ref:SI ("var"))
1882 (const_int 48 [0x30])))] UNSPEC_ADD_TLS_LE)))
1884 Which will be output as '%tls_le(var+48)(r23)' in assembly. */
1885 if (GET_CODE (x) == PLUS
1886 && GET_CODE (XEXP (x, 0)) == REG
1887 && GET_CODE (XEXP (x, 1)) == CONST)
1889 rtx unspec, offset, reg = XEXP (x, 0);
1890 split_const (XEXP (x, 1), &unspec, &offset);
1891 if (GET_CODE (unspec) == UNSPEC
1892 && !nios2_large_offset_p (XINT (unspec, 1))
1893 && offset != const0_rtx)
1895 unspec = copy_rtx (unspec);
1896 XVECEXP (unspec, 0, 0)
1897 = plus_constant (Pmode, XVECEXP (unspec, 0, 0), INTVAL (offset));
1898 x = gen_rtx_PLUS (Pmode, reg, gen_rtx_CONST (Pmode, unspec));
1902 return x;
1905 static rtx
1906 nios2_delegitimize_address (rtx x)
1908 x = delegitimize_mem_from_attrs (x);
1910 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC)
1912 switch (XINT (XEXP (x, 0), 1))
1914 case UNSPEC_PIC_SYM:
1915 case UNSPEC_PIC_CALL_SYM:
1916 case UNSPEC_PIC_GOTOFF_SYM:
1917 case UNSPEC_ADD_TLS_GD:
1918 case UNSPEC_ADD_TLS_LDM:
1919 case UNSPEC_LOAD_TLS_IE:
1920 case UNSPEC_ADD_TLS_LE:
1921 x = XVECEXP (XEXP (x, 0), 0, 0);
1922 gcc_assert (GET_CODE (x) == SYMBOL_REF);
1923 break;
1926 return x;
1929 /* Main expander function for RTL moves. */
1931 nios2_emit_move_sequence (rtx *operands, machine_mode mode)
1933 rtx to = operands[0];
1934 rtx from = operands[1];
1936 if (!register_operand (to, mode) && !reg_or_0_operand (from, mode))
1938 gcc_assert (can_create_pseudo_p ());
1939 from = copy_to_mode_reg (mode, from);
1942 if (GET_CODE (from) == SYMBOL_REF || GET_CODE (from) == LABEL_REF
1943 || (GET_CODE (from) == CONST
1944 && GET_CODE (XEXP (from, 0)) != UNSPEC))
1945 from = nios2_legitimize_constant_address (from);
1947 operands[0] = to;
1948 operands[1] = from;
1949 return 0;
1952 /* The function with address *ADDR is being called. If the address
1953 needs to be loaded from the GOT, emit the instruction to do so and
1954 update *ADDR to point to the rtx for the loaded value.
1955 If REG != NULL_RTX, it is used as the target/scratch register in the
1956 GOT address calculation. */
1957 void
1958 nios2_adjust_call_address (rtx *call_op, rtx reg)
1960 if (MEM_P (*call_op))
1961 call_op = &XEXP (*call_op, 0);
1963 rtx addr = *call_op;
1964 if (flag_pic && CONSTANT_P (addr))
1966 rtx tmp = reg ? reg : NULL_RTX;
1967 if (!reg)
1968 reg = gen_reg_rtx (Pmode);
1969 addr = nios2_load_pic_address (addr, UNSPEC_PIC_CALL_SYM, tmp);
1970 emit_insn (gen_rtx_SET (reg, addr));
1971 *call_op = reg;
1976 /* Output assembly language related definitions. */
1978 /* Print the operand OP to file stream FILE modified by LETTER.
1979 LETTER can be one of:
1981 i: print "i" if OP is an immediate, except 0
1982 o: print "io" if OP is volatile
1983 z: for const0_rtx print $0 instead of 0
1984 H: for %hiadj
1985 L: for %lo
1986 U: for upper half of 32 bit value
1987 D: for the upper 32-bits of a 64-bit double value
1988 R: prints reverse condition.
1990 static void
1991 nios2_print_operand (FILE *file, rtx op, int letter)
1994 switch (letter)
1996 case 'i':
1997 if (CONSTANT_P (op) && op != const0_rtx)
1998 fprintf (file, "i");
1999 return;
2001 case 'o':
2002 if (GET_CODE (op) == MEM
2003 && ((MEM_VOLATILE_P (op) && TARGET_BYPASS_CACHE_VOLATILE)
2004 || TARGET_BYPASS_CACHE))
2005 fprintf (file, "io");
2006 return;
2008 default:
2009 break;
2012 if (comparison_operator (op, VOIDmode))
2014 enum rtx_code cond = GET_CODE (op);
2015 if (letter == 0)
2017 fprintf (file, "%s", GET_RTX_NAME (cond));
2018 return;
2020 if (letter == 'R')
2022 fprintf (file, "%s", GET_RTX_NAME (reverse_condition (cond)));
2023 return;
2027 switch (GET_CODE (op))
2029 case REG:
2030 if (letter == 0 || letter == 'z')
2032 fprintf (file, "%s", reg_names[REGNO (op)]);
2033 return;
2035 else if (letter == 'D')
2037 fprintf (file, "%s", reg_names[REGNO (op)+1]);
2038 return;
2040 break;
2042 case CONST_INT:
2043 if (INTVAL (op) == 0 && letter == 'z')
2045 fprintf (file, "zero");
2046 return;
2049 if (letter == 'U')
2051 HOST_WIDE_INT val = INTVAL (op);
2052 val = (val >> 16) & 0xFFFF;
2053 output_addr_const (file, gen_int_mode (val, SImode));
2054 return;
2056 /* Else, fall through. */
2058 case CONST:
2059 case LABEL_REF:
2060 case SYMBOL_REF:
2061 case CONST_DOUBLE:
2062 if (letter == 0 || letter == 'z')
2064 output_addr_const (file, op);
2065 return;
2067 else if (letter == 'H' || letter == 'L')
2069 fprintf (file, "%%");
2070 if (GET_CODE (op) == CONST
2071 && GET_CODE (XEXP (op, 0)) == UNSPEC)
2073 rtx unspec = XEXP (op, 0);
2074 int unspec_reloc = XINT (unspec, 1);
2075 gcc_assert (nios2_large_offset_p (unspec_reloc));
2076 fprintf (file, "%s_", nios2_unspec_reloc_name (unspec_reloc));
2077 op = XVECEXP (unspec, 0, 0);
2079 fprintf (file, letter == 'H' ? "hiadj(" : "lo(");
2080 output_addr_const (file, op);
2081 fprintf (file, ")");
2082 return;
2084 break;
2086 case SUBREG:
2087 case MEM:
2088 if (letter == 0)
2090 output_address (op);
2091 return;
2093 break;
2095 case CODE_LABEL:
2096 if (letter == 0)
2098 output_addr_const (file, op);
2099 return;
2101 break;
2103 default:
2104 break;
2107 output_operand_lossage ("Unsupported operand for code '%c'", letter);
2108 gcc_unreachable ();
2111 /* Return true if this is a GP-relative accessible reference. */
2112 static bool
2113 gprel_constant_p (rtx op)
2115 if (GET_CODE (op) == SYMBOL_REF
2116 && nios2_symbol_ref_in_small_data_p (op))
2117 return true;
2118 else if (GET_CODE (op) == CONST
2119 && GET_CODE (XEXP (op, 0)) == PLUS)
2120 return gprel_constant_p (XEXP (XEXP (op, 0), 0));
2122 return false;
2125 /* Return the name string for a supported unspec reloc offset. */
2126 static const char *
2127 nios2_unspec_reloc_name (int unspec)
2129 switch (unspec)
2131 case UNSPEC_PIC_SYM:
2132 return "got";
2133 case UNSPEC_PIC_CALL_SYM:
2134 return "call";
2135 case UNSPEC_PIC_GOTOFF_SYM:
2136 return "gotoff";
2137 case UNSPEC_LOAD_TLS_IE:
2138 return "tls_ie";
2139 case UNSPEC_ADD_TLS_LE:
2140 return "tls_le";
2141 case UNSPEC_ADD_TLS_GD:
2142 return "tls_gd";
2143 case UNSPEC_ADD_TLS_LDM:
2144 return "tls_ldm";
2145 case UNSPEC_ADD_TLS_LDO:
2146 return "tls_ldo";
2147 default:
2148 return NULL;
2152 /* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */
2153 static bool
2154 nios2_output_addr_const_extra (FILE *file, rtx op)
2156 const char *name;
2157 gcc_assert (GET_CODE (op) == UNSPEC);
2159 /* Support for printing out const unspec relocations. */
2160 name = nios2_unspec_reloc_name (XINT (op, 1));
2161 if (name)
2163 fprintf (file, "%%%s(", name);
2164 output_addr_const (file, XVECEXP (op, 0, 0));
2165 fprintf (file, ")");
2166 return true;
2168 return false;
2171 /* Implement TARGET_PRINT_OPERAND_ADDRESS. */
2172 static void
2173 nios2_print_operand_address (FILE *file, rtx op)
2175 switch (GET_CODE (op))
2177 case CONST:
2178 case CONST_INT:
2179 case LABEL_REF:
2180 case CONST_DOUBLE:
2181 case SYMBOL_REF:
2182 if (gprel_constant_p (op))
2184 fprintf (file, "%%gprel(");
2185 output_addr_const (file, op);
2186 fprintf (file, ")(%s)", reg_names[GP_REGNO]);
2187 return;
2190 break;
2192 case PLUS:
2194 rtx op0 = XEXP (op, 0);
2195 rtx op1 = XEXP (op, 1);
2197 if (REG_P (op0) && CONSTANT_P (op1))
2199 output_addr_const (file, op1);
2200 fprintf (file, "(%s)", reg_names[REGNO (op0)]);
2201 return;
2203 else if (REG_P (op1) && CONSTANT_P (op0))
2205 output_addr_const (file, op0);
2206 fprintf (file, "(%s)", reg_names[REGNO (op1)]);
2207 return;
2210 break;
2212 case REG:
2213 fprintf (file, "0(%s)", reg_names[REGNO (op)]);
2214 return;
2216 case MEM:
2218 rtx base = XEXP (op, 0);
2219 nios2_print_operand_address (file, base);
2220 return;
2222 default:
2223 break;
2226 fprintf (stderr, "Missing way to print address\n");
2227 debug_rtx (op);
2228 gcc_unreachable ();
2231 /* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL. */
2232 static void
2233 nios2_output_dwarf_dtprel (FILE *file, int size, rtx x)
2235 gcc_assert (size == 4);
2236 fprintf (file, "\t.4byte\t%%tls_ldo(");
2237 output_addr_const (file, x);
2238 fprintf (file, ")");
2241 /* Implemet TARGET_ASM_FILE_END. */
2243 static void
2244 nios2_asm_file_end (void)
2246 /* The Nios II Linux stack is mapped non-executable by default, so add a
2247 .note.GNU-stack section for switching to executable stacks only when
2248 trampolines are generated. */
2249 if (TARGET_LINUX_ABI && trampolines_created)
2250 file_end_indicate_exec_stack ();
2253 /* Implement TARGET_ASM_FUNCTION_PROLOGUE. */
2254 static void
2255 nios2_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
2257 if (flag_verbose_asm || flag_debug_asm)
2259 nios2_compute_frame_layout ();
2260 nios2_dump_frame_layout (file);
2264 /* Emit assembly of custom FPU instructions. */
2265 const char *
2266 nios2_fpu_insn_asm (enum n2fpu_code code)
2268 static char buf[256];
2269 const char *op1, *op2, *op3;
2270 int ln = 256, n = 0;
2272 int N = N2FPU_N (code);
2273 int num_operands = N2FPU (code).num_operands;
2274 const char *insn_name = N2FPU_NAME (code);
2275 tree ftype = nios2_ftype (N2FPU_FTCODE (code));
2276 machine_mode dst_mode = TYPE_MODE (TREE_TYPE (ftype));
2277 machine_mode src_mode = TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (ftype)));
2279 /* Prepare X register for DF input operands. */
2280 if (GET_MODE_SIZE (src_mode) == 8 && num_operands == 3)
2281 n = snprintf (buf, ln, "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t",
2282 N2FPU_N (n2fpu_fwrx));
2284 if (src_mode == SFmode)
2286 if (dst_mode == VOIDmode)
2288 /* The fwry case. */
2289 op1 = op3 = "zero";
2290 op2 = "%0";
2291 num_operands -= 1;
2293 else
2295 op1 = (dst_mode == DFmode ? "%D0" : "%0");
2296 op2 = "%1";
2297 op3 = (num_operands == 2 ? "zero" : "%2");
2300 else if (src_mode == DFmode)
2302 if (dst_mode == VOIDmode)
2304 /* The fwrx case. */
2305 op1 = "zero";
2306 op2 = "%0";
2307 op3 = "%D0";
2308 num_operands -= 1;
2310 else
2312 op1 = (dst_mode == DFmode ? "%D0" : "%0");
2313 op2 = (num_operands == 2 ? "%1" : "%2");
2314 op3 = (num_operands == 2 ? "%D1" : "%D2");
2317 else if (src_mode == VOIDmode)
2319 /* frdxlo, frdxhi, frdy cases. */
2320 gcc_assert (dst_mode == SFmode);
2321 op1 = "%0";
2322 op2 = op3 = "zero";
2324 else if (src_mode == SImode)
2326 /* Conversion operators. */
2327 gcc_assert (num_operands == 2);
2328 op1 = (dst_mode == DFmode ? "%D0" : "%0");
2329 op2 = "%1";
2330 op3 = "zero";
2332 else
2333 gcc_unreachable ();
2335 /* Main instruction string. */
2336 n += snprintf (buf + n, ln - n, "custom\t%d, %s, %s, %s # %s %%0%s%s",
2337 N, op1, op2, op3, insn_name,
2338 (num_operands >= 2 ? ", %1" : ""),
2339 (num_operands == 3 ? ", %2" : ""));
2341 /* Extraction of Y register for DF results. */
2342 if (dst_mode == DFmode)
2343 snprintf (buf + n, ln - n, "\n\tcustom\t%d, %%0, zero, zero # frdy %%0",
2344 N2FPU_N (n2fpu_frdy));
2345 return buf;
2350 /* Function argument related. */
2352 /* Define where to put the arguments to a function. Value is zero to
2353 push the argument on the stack, or a hard register in which to
2354 store the argument.
2356 MODE is the argument's machine mode.
2357 TYPE is the data type of the argument (as a tree).
2358 This is null for libcalls where that information may
2359 not be available.
2360 CUM is a variable of type CUMULATIVE_ARGS which gives info about
2361 the preceding args and about the function being called.
2362 NAMED is nonzero if this argument is a named parameter
2363 (otherwise it is an extra parameter matching an ellipsis). */
2365 static rtx
2366 nios2_function_arg (cumulative_args_t cum_v, machine_mode mode,
2367 const_tree type ATTRIBUTE_UNUSED,
2368 bool named ATTRIBUTE_UNUSED)
2370 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2371 rtx return_rtx = NULL_RTX;
2373 if (cum->regs_used < NUM_ARG_REGS)
2374 return_rtx = gen_rtx_REG (mode, FIRST_ARG_REGNO + cum->regs_used);
2376 return return_rtx;
2379 /* Return number of bytes, at the beginning of the argument, that must be
2380 put in registers. 0 is the argument is entirely in registers or entirely
2381 in memory. */
2383 static int
2384 nios2_arg_partial_bytes (cumulative_args_t cum_v,
2385 machine_mode mode, tree type ATTRIBUTE_UNUSED,
2386 bool named ATTRIBUTE_UNUSED)
2388 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2389 HOST_WIDE_INT param_size;
2391 if (mode == BLKmode)
2393 param_size = int_size_in_bytes (type);
2394 gcc_assert (param_size >= 0);
2396 else
2397 param_size = GET_MODE_SIZE (mode);
2399 /* Convert to words (round up). */
2400 param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
2402 if (cum->regs_used < NUM_ARG_REGS
2403 && cum->regs_used + param_size > NUM_ARG_REGS)
2404 return (NUM_ARG_REGS - cum->regs_used) * UNITS_PER_WORD;
2406 return 0;
2409 /* Update the data in CUM to advance over an argument of mode MODE
2410 and data type TYPE; TYPE is null for libcalls where that information
2411 may not be available. */
2413 static void
2414 nios2_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
2415 const_tree type ATTRIBUTE_UNUSED,
2416 bool named ATTRIBUTE_UNUSED)
2418 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2419 HOST_WIDE_INT param_size;
2421 if (mode == BLKmode)
2423 param_size = int_size_in_bytes (type);
2424 gcc_assert (param_size >= 0);
2426 else
2427 param_size = GET_MODE_SIZE (mode);
2429 /* Convert to words (round up). */
2430 param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
2432 if (cum->regs_used + param_size > NUM_ARG_REGS)
2433 cum->regs_used = NUM_ARG_REGS;
2434 else
2435 cum->regs_used += param_size;
2438 enum direction
2439 nios2_function_arg_padding (machine_mode mode, const_tree type)
2441 /* On little-endian targets, the first byte of every stack argument
2442 is passed in the first byte of the stack slot. */
2443 if (!BYTES_BIG_ENDIAN)
2444 return upward;
2446 /* Otherwise, integral types are padded downward: the last byte of a
2447 stack argument is passed in the last byte of the stack slot. */
2448 if (type != 0
2449 ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
2450 : GET_MODE_CLASS (mode) == MODE_INT)
2451 return downward;
2453 /* Arguments smaller than a stack slot are padded downward. */
2454 if (mode != BLKmode)
2455 return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY) ? upward : downward;
2457 return ((int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
2458 ? upward : downward);
2461 enum direction
2462 nios2_block_reg_padding (machine_mode mode, tree type,
2463 int first ATTRIBUTE_UNUSED)
2465 return nios2_function_arg_padding (mode, type);
2468 /* Emit RTL insns to initialize the variable parts of a trampoline.
2469 FNADDR is an RTX for the address of the function's pure code.
2470 CXT is an RTX for the static chain value for the function.
2471 On Nios II, we handle this by a library call. */
2472 static void
2473 nios2_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
2475 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2476 rtx ctx_reg = force_reg (Pmode, cxt);
2477 rtx addr = force_reg (Pmode, XEXP (m_tramp, 0));
2479 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__trampoline_setup"),
2480 LCT_NORMAL, VOIDmode, 3, addr, Pmode, fnaddr, Pmode,
2481 ctx_reg, Pmode);
2484 /* Implement TARGET_FUNCTION_VALUE. */
2485 static rtx
2486 nios2_function_value (const_tree ret_type, const_tree fn ATTRIBUTE_UNUSED,
2487 bool outgoing ATTRIBUTE_UNUSED)
2489 return gen_rtx_REG (TYPE_MODE (ret_type), FIRST_RETVAL_REGNO);
2492 /* Implement TARGET_LIBCALL_VALUE. */
2493 static rtx
2494 nios2_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
2496 return gen_rtx_REG (mode, FIRST_RETVAL_REGNO);
2499 /* Implement TARGET_FUNCTION_VALUE_REGNO_P. */
2500 static bool
2501 nios2_function_value_regno_p (const unsigned int regno)
2503 return regno == FIRST_RETVAL_REGNO;
2506 /* Implement TARGET_RETURN_IN_MEMORY. */
2507 static bool
2508 nios2_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2510 return (int_size_in_bytes (type) > (2 * UNITS_PER_WORD)
2511 || int_size_in_bytes (type) == -1);
2514 /* TODO: It may be possible to eliminate the copyback and implement
2515 own va_arg type. */
2516 static void
2517 nios2_setup_incoming_varargs (cumulative_args_t cum_v,
2518 machine_mode mode, tree type,
2519 int *pretend_size, int second_time)
2521 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2522 CUMULATIVE_ARGS local_cum;
2523 cumulative_args_t local_cum_v = pack_cumulative_args (&local_cum);
2524 int regs_to_push;
2525 int pret_size;
2527 local_cum = *cum;
2528 nios2_function_arg_advance (local_cum_v, mode, type, 1);
2530 regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
2532 if (!second_time && regs_to_push > 0)
2534 rtx ptr = virtual_incoming_args_rtx;
2535 rtx mem = gen_rtx_MEM (BLKmode, ptr);
2536 emit_insn (gen_blockage ());
2537 move_block_from_reg (local_cum.regs_used + FIRST_ARG_REGNO, mem,
2538 regs_to_push);
2539 emit_insn (gen_blockage ());
2542 pret_size = regs_to_push * UNITS_PER_WORD;
2543 if (pret_size)
2544 *pretend_size = pret_size;
2549 /* Init FPU builtins. */
2550 static void
2551 nios2_init_fpu_builtins (int start_code)
2553 tree fndecl;
2554 char builtin_name[64] = "__builtin_custom_";
2555 unsigned int i, n = strlen ("__builtin_custom_");
2557 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
2559 snprintf (builtin_name + n, sizeof (builtin_name) - n,
2560 "%s", N2FPU_NAME (i));
2561 fndecl =
2562 add_builtin_function (builtin_name, nios2_ftype (N2FPU_FTCODE (i)),
2563 start_code + i, BUILT_IN_MD, NULL, NULL_TREE);
2564 nios2_register_builtin_fndecl (start_code + i, fndecl);
2568 /* Helper function for expanding FPU builtins. */
2569 static rtx
2570 nios2_expand_fpu_builtin (tree exp, unsigned int code, rtx target)
2572 struct expand_operand ops[MAX_RECOG_OPERANDS];
2573 enum insn_code icode = N2FPU_ICODE (code);
2574 int nargs, argno, opno = 0;
2575 int num_operands = N2FPU (code).num_operands;
2576 machine_mode dst_mode = TYPE_MODE (TREE_TYPE (exp));
2577 bool has_target_p = (dst_mode != VOIDmode);
2579 if (N2FPU_N (code) < 0)
2580 fatal_error (input_location,
2581 "Cannot call %<__builtin_custom_%s%> without specifying switch"
2582 " %<-mcustom-%s%>", N2FPU_NAME (code), N2FPU_NAME (code));
2583 if (has_target_p)
2584 create_output_operand (&ops[opno++], target, dst_mode);
2585 else
2586 /* Subtract away the count of the VOID return, mainly for fwrx/fwry. */
2587 num_operands -= 1;
2588 nargs = call_expr_nargs (exp);
2589 for (argno = 0; argno < nargs; argno++)
2591 tree arg = CALL_EXPR_ARG (exp, argno);
2592 create_input_operand (&ops[opno++], expand_normal (arg),
2593 TYPE_MODE (TREE_TYPE (arg)));
2595 if (!maybe_expand_insn (icode, num_operands, ops))
2597 error ("invalid argument to built-in function");
2598 return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
2600 return has_target_p ? ops[0].value : const0_rtx;
2603 /* Nios II has custom instruction built-in functions of the forms:
2604 __builtin_custom_n
2605 __builtin_custom_nX
2606 __builtin_custom_nXX
2607 __builtin_custom_Xn
2608 __builtin_custom_XnX
2609 __builtin_custom_XnXX
2611 where each X could be either 'i' (int), 'f' (float), or 'p' (void*).
2612 Therefore with 0-1 return values, and 0-2 arguments, we have a
2613 total of (3 + 1) * (1 + 3 + 9) == 52 custom builtin functions.
2615 #define NUM_CUSTOM_BUILTINS ((3 + 1) * (1 + 3 + 9))
2616 static char custom_builtin_name[NUM_CUSTOM_BUILTINS][5];
2618 static void
2619 nios2_init_custom_builtins (int start_code)
2621 tree builtin_ftype, ret_type, fndecl;
2622 char builtin_name[32] = "__builtin_custom_";
2623 int n = strlen ("__builtin_custom_");
2624 int builtin_code = 0;
2625 int lhs, rhs1, rhs2;
2627 struct { tree type; const char *c; } op[4];
2628 /* z */ op[0].c = ""; op[0].type = NULL_TREE;
2629 /* f */ op[1].c = "f"; op[1].type = float_type_node;
2630 /* i */ op[2].c = "i"; op[2].type = integer_type_node;
2631 /* p */ op[3].c = "p"; op[3].type = ptr_type_node;
2633 /* We enumerate through the possible operand types to create all the
2634 __builtin_custom_XnXX function tree types. Note that these may slightly
2635 overlap with the function types created for other fixed builtins. */
2637 for (lhs = 0; lhs < 4; lhs++)
2638 for (rhs1 = 0; rhs1 < 4; rhs1++)
2639 for (rhs2 = 0; rhs2 < 4; rhs2++)
2641 if (rhs1 == 0 && rhs2 != 0)
2642 continue;
2643 ret_type = (op[lhs].type ? op[lhs].type : void_type_node);
2644 builtin_ftype
2645 = build_function_type_list (ret_type, integer_type_node,
2646 op[rhs1].type, op[rhs2].type,
2647 NULL_TREE);
2648 snprintf (builtin_name + n, 32 - n, "%sn%s%s",
2649 op[lhs].c, op[rhs1].c, op[rhs2].c);
2650 /* Save copy of parameter string into custom_builtin_name[]. */
2651 strncpy (custom_builtin_name[builtin_code], builtin_name + n, 5);
2652 fndecl =
2653 add_builtin_function (builtin_name, builtin_ftype,
2654 start_code + builtin_code,
2655 BUILT_IN_MD, NULL, NULL_TREE);
2656 nios2_register_builtin_fndecl (start_code + builtin_code, fndecl);
2657 builtin_code += 1;
2661 /* Helper function for expanding custom builtins. */
2662 static rtx
2663 nios2_expand_custom_builtin (tree exp, unsigned int index, rtx target)
2665 bool has_target_p = (TREE_TYPE (exp) != void_type_node);
2666 machine_mode tmode = VOIDmode;
2667 int nargs, argno;
2668 rtx value, insn, unspec_args[3];
2669 tree arg;
2671 /* XnXX form. */
2672 if (has_target_p)
2674 tmode = TYPE_MODE (TREE_TYPE (exp));
2675 if (!target || GET_MODE (target) != tmode
2676 || !REG_P (target))
2677 target = gen_reg_rtx (tmode);
2680 nargs = call_expr_nargs (exp);
2681 for (argno = 0; argno < nargs; argno++)
2683 arg = CALL_EXPR_ARG (exp, argno);
2684 value = expand_normal (arg);
2685 unspec_args[argno] = value;
2686 if (argno == 0)
2688 if (!custom_insn_opcode (value, VOIDmode))
2689 error ("custom instruction opcode must be compile time "
2690 "constant in the range 0-255 for __builtin_custom_%s",
2691 custom_builtin_name[index]);
2693 else
2694 /* For other arguments, force into a register. */
2695 unspec_args[argno] = force_reg (TYPE_MODE (TREE_TYPE (arg)),
2696 unspec_args[argno]);
2698 /* Fill remaining unspec operands with zero. */
2699 for (; argno < 3; argno++)
2700 unspec_args[argno] = const0_rtx;
2702 insn = (has_target_p
2703 ? gen_rtx_SET (target,
2704 gen_rtx_UNSPEC_VOLATILE (tmode,
2705 gen_rtvec_v (3, unspec_args),
2706 UNSPECV_CUSTOM_XNXX))
2707 : gen_rtx_UNSPEC_VOLATILE (VOIDmode, gen_rtvec_v (3, unspec_args),
2708 UNSPECV_CUSTOM_NXX));
2709 emit_insn (insn);
2710 return has_target_p ? target : const0_rtx;
2716 /* Main definition of built-in functions. Nios II has a small number of fixed
2717 builtins, plus a large number of FPU insn builtins, and builtins for
2718 generating custom instructions. */
2720 struct nios2_builtin_desc
2722 enum insn_code icode;
2723 enum nios2_ftcode ftype;
2724 const char *name;
2727 #define N2_BUILTINS \
2728 N2_BUILTIN_DEF (sync, N2_FTYPE_VOID_VOID) \
2729 N2_BUILTIN_DEF (ldbio, N2_FTYPE_SI_CVPTR) \
2730 N2_BUILTIN_DEF (ldbuio, N2_FTYPE_UI_CVPTR) \
2731 N2_BUILTIN_DEF (ldhio, N2_FTYPE_SI_CVPTR) \
2732 N2_BUILTIN_DEF (ldhuio, N2_FTYPE_UI_CVPTR) \
2733 N2_BUILTIN_DEF (ldwio, N2_FTYPE_SI_CVPTR) \
2734 N2_BUILTIN_DEF (stbio, N2_FTYPE_VOID_VPTR_SI) \
2735 N2_BUILTIN_DEF (sthio, N2_FTYPE_VOID_VPTR_SI) \
2736 N2_BUILTIN_DEF (stwio, N2_FTYPE_VOID_VPTR_SI) \
2737 N2_BUILTIN_DEF (rdctl, N2_FTYPE_SI_SI) \
2738 N2_BUILTIN_DEF (wrctl, N2_FTYPE_VOID_SI_SI)
2740 enum nios2_builtin_code {
2741 #define N2_BUILTIN_DEF(name, ftype) NIOS2_BUILTIN_ ## name,
2742 N2_BUILTINS
2743 #undef N2_BUILTIN_DEF
2744 NUM_FIXED_NIOS2_BUILTINS
2747 static const struct nios2_builtin_desc nios2_builtins[] = {
2748 #define N2_BUILTIN_DEF(name, ftype) \
2749 { CODE_FOR_ ## name, ftype, "__builtin_" #name },
2750 N2_BUILTINS
2751 #undef N2_BUILTIN_DEF
2754 /* Start/ends of FPU/custom insn builtin index ranges. */
2755 static unsigned int nios2_fpu_builtin_base;
2756 static unsigned int nios2_custom_builtin_base;
2757 static unsigned int nios2_custom_builtin_end;
2759 /* Implement TARGET_INIT_BUILTINS. */
2760 static void
2761 nios2_init_builtins (void)
2763 unsigned int i;
2765 /* Initialize fixed builtins. */
2766 for (i = 0; i < ARRAY_SIZE (nios2_builtins); i++)
2768 const struct nios2_builtin_desc *d = &nios2_builtins[i];
2769 tree fndecl =
2770 add_builtin_function (d->name, nios2_ftype (d->ftype), i,
2771 BUILT_IN_MD, NULL, NULL);
2772 nios2_register_builtin_fndecl (i, fndecl);
2775 /* Initialize FPU builtins. */
2776 nios2_fpu_builtin_base = ARRAY_SIZE (nios2_builtins);
2777 nios2_init_fpu_builtins (nios2_fpu_builtin_base);
2779 /* Initialize custom insn builtins. */
2780 nios2_custom_builtin_base
2781 = nios2_fpu_builtin_base + ARRAY_SIZE (nios2_fpu_insn);
2782 nios2_custom_builtin_end
2783 = nios2_custom_builtin_base + NUM_CUSTOM_BUILTINS;
2784 nios2_init_custom_builtins (nios2_custom_builtin_base);
2787 /* Array of fndecls for TARGET_BUILTIN_DECL. */
2788 #define NIOS2_NUM_BUILTINS \
2789 (ARRAY_SIZE (nios2_builtins) + ARRAY_SIZE (nios2_fpu_insn) + NUM_CUSTOM_BUILTINS)
2790 static GTY(()) tree nios2_builtin_decls[NIOS2_NUM_BUILTINS];
2792 static void
2793 nios2_register_builtin_fndecl (unsigned code, tree fndecl)
2795 nios2_builtin_decls[code] = fndecl;
2798 /* Implement TARGET_BUILTIN_DECL. */
2799 static tree
2800 nios2_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
2802 gcc_assert (nios2_custom_builtin_end == ARRAY_SIZE (nios2_builtin_decls));
2804 if (code >= nios2_custom_builtin_end)
2805 return error_mark_node;
2807 if (code >= nios2_fpu_builtin_base
2808 && code < nios2_custom_builtin_base
2809 && ! N2FPU_ENABLED_P (code - nios2_fpu_builtin_base))
2810 return error_mark_node;
2812 return nios2_builtin_decls[code];
2816 /* Low-level built-in expand routine. */
2817 static rtx
2818 nios2_expand_builtin_insn (const struct nios2_builtin_desc *d, int n,
2819 struct expand_operand *ops, bool has_target_p)
2821 if (maybe_expand_insn (d->icode, n, ops))
2822 return has_target_p ? ops[0].value : const0_rtx;
2823 else
2825 error ("invalid argument to built-in function %s", d->name);
2826 return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
2830 /* Expand ldio/stio form load-store instruction builtins. */
2831 static rtx
2832 nios2_expand_ldstio_builtin (tree exp, rtx target,
2833 const struct nios2_builtin_desc *d)
2835 bool has_target_p;
2836 rtx addr, mem, val;
2837 struct expand_operand ops[MAX_RECOG_OPERANDS];
2838 machine_mode mode = insn_data[d->icode].operand[0].mode;
2840 addr = expand_normal (CALL_EXPR_ARG (exp, 0));
2841 mem = gen_rtx_MEM (mode, addr);
2843 if (insn_data[d->icode].operand[0].allows_mem)
2845 /* stxio. */
2846 val = expand_normal (CALL_EXPR_ARG (exp, 1));
2847 if (CONST_INT_P (val))
2848 val = force_reg (mode, gen_int_mode (INTVAL (val), mode));
2849 val = simplify_gen_subreg (mode, val, GET_MODE (val), 0);
2850 create_output_operand (&ops[0], mem, mode);
2851 create_input_operand (&ops[1], val, mode);
2852 has_target_p = false;
2854 else
2856 /* ldxio. */
2857 create_output_operand (&ops[0], target, mode);
2858 create_input_operand (&ops[1], mem, mode);
2859 has_target_p = true;
2861 return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
2864 /* Expand rdctl/wrctl builtins. */
2865 static rtx
2866 nios2_expand_rdwrctl_builtin (tree exp, rtx target,
2867 const struct nios2_builtin_desc *d)
2869 bool has_target_p = (insn_data[d->icode].operand[0].predicate
2870 == register_operand);
2871 rtx ctlcode = expand_normal (CALL_EXPR_ARG (exp, 0));
2872 struct expand_operand ops[MAX_RECOG_OPERANDS];
2873 if (!rdwrctl_operand (ctlcode, VOIDmode))
2875 error ("Control register number must be in range 0-31 for %s",
2876 d->name);
2877 return has_target_p ? gen_reg_rtx (SImode) : const0_rtx;
2879 if (has_target_p)
2881 create_output_operand (&ops[0], target, SImode);
2882 create_integer_operand (&ops[1], INTVAL (ctlcode));
2884 else
2886 rtx val = expand_normal (CALL_EXPR_ARG (exp, 1));
2887 create_integer_operand (&ops[0], INTVAL (ctlcode));
2888 create_input_operand (&ops[1], val, SImode);
2890 return nios2_expand_builtin_insn (d, 2, ops, has_target_p);
2893 /* Implement TARGET_EXPAND_BUILTIN. Expand an expression EXP that calls
2894 a built-in function, with result going to TARGET if that's convenient
2895 (and in mode MODE if that's convenient).
2896 SUBTARGET may be used as the target for computing one of EXP's operands.
2897 IGNORE is nonzero if the value is to be ignored. */
2899 static rtx
2900 nios2_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
2901 machine_mode mode ATTRIBUTE_UNUSED,
2902 int ignore ATTRIBUTE_UNUSED)
2904 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2905 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2907 if (fcode < nios2_fpu_builtin_base)
2909 const struct nios2_builtin_desc *d = &nios2_builtins[fcode];
2911 switch (fcode)
2913 case NIOS2_BUILTIN_sync:
2914 emit_insn (gen_sync ());
2915 return const0_rtx;
2917 case NIOS2_BUILTIN_ldbio:
2918 case NIOS2_BUILTIN_ldbuio:
2919 case NIOS2_BUILTIN_ldhio:
2920 case NIOS2_BUILTIN_ldhuio:
2921 case NIOS2_BUILTIN_ldwio:
2922 case NIOS2_BUILTIN_stbio:
2923 case NIOS2_BUILTIN_sthio:
2924 case NIOS2_BUILTIN_stwio:
2925 return nios2_expand_ldstio_builtin (exp, target, d);
2927 case NIOS2_BUILTIN_rdctl:
2928 case NIOS2_BUILTIN_wrctl:
2929 return nios2_expand_rdwrctl_builtin (exp, target, d);
2931 default:
2932 gcc_unreachable ();
2935 else if (fcode < nios2_custom_builtin_base)
2936 /* FPU builtin range. */
2937 return nios2_expand_fpu_builtin (exp, fcode - nios2_fpu_builtin_base,
2938 target);
2939 else if (fcode < nios2_custom_builtin_end)
2940 /* Custom insn builtin range. */
2941 return nios2_expand_custom_builtin (exp, fcode - nios2_custom_builtin_base,
2942 target);
2943 else
2944 gcc_unreachable ();
2947 /* Implement TARGET_INIT_LIBFUNCS. */
2948 static void
2949 nios2_init_libfuncs (void)
2951 /* For Linux, we have access to kernel support for atomic operations. */
2952 if (TARGET_LINUX_ABI)
2953 init_sync_libfuncs (UNITS_PER_WORD);
2958 /* Register a custom code use, and signal error if a conflict was found. */
2959 static void
2960 nios2_register_custom_code (unsigned int N, enum nios2_ccs_code status,
2961 int index)
2963 gcc_assert (N <= 255);
2965 if (status == CCS_FPU)
2967 if (custom_code_status[N] == CCS_FPU && index != custom_code_index[N])
2969 custom_code_conflict = true;
2970 error ("switch %<-mcustom-%s%> conflicts with switch %<-mcustom-%s%>",
2971 N2FPU_NAME (custom_code_index[N]), N2FPU_NAME (index));
2973 else if (custom_code_status[N] == CCS_BUILTIN_CALL)
2975 custom_code_conflict = true;
2976 error ("call to %<__builtin_custom_%s%> conflicts with switch "
2977 "%<-mcustom-%s%>", custom_builtin_name[custom_code_index[N]],
2978 N2FPU_NAME (index));
2981 else if (status == CCS_BUILTIN_CALL)
2983 if (custom_code_status[N] == CCS_FPU)
2985 custom_code_conflict = true;
2986 error ("call to %<__builtin_custom_%s%> conflicts with switch "
2987 "%<-mcustom-%s%>", custom_builtin_name[index],
2988 N2FPU_NAME (custom_code_index[N]));
2990 else
2992 /* Note that code conflicts between different __builtin_custom_xnxx
2993 calls are not checked. */
2996 else
2997 gcc_unreachable ();
2999 custom_code_status[N] = status;
3000 custom_code_index[N] = index;
3003 /* Mark a custom code as not in use. */
3004 static void
3005 nios2_deregister_custom_code (unsigned int N)
3007 if (N <= 255)
3009 custom_code_status[N] = CCS_UNUSED;
3010 custom_code_index[N] = 0;
3014 /* Target attributes can affect per-function option state, so we need to
3015 save/restore the custom code tracking info using the
3016 TARGET_OPTION_SAVE/TARGET_OPTION_RESTORE hooks. */
3018 static void
3019 nios2_option_save (struct cl_target_option *ptr,
3020 struct gcc_options *opts ATTRIBUTE_UNUSED)
3022 unsigned int i;
3023 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
3024 ptr->saved_fpu_custom_code[i] = N2FPU_N (i);
3025 memcpy (ptr->saved_custom_code_status, custom_code_status,
3026 sizeof (custom_code_status));
3027 memcpy (ptr->saved_custom_code_index, custom_code_index,
3028 sizeof (custom_code_index));
3031 static void
3032 nios2_option_restore (struct gcc_options *opts ATTRIBUTE_UNUSED,
3033 struct cl_target_option *ptr)
3035 unsigned int i;
3036 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
3037 N2FPU_N (i) = ptr->saved_fpu_custom_code[i];
3038 memcpy (custom_code_status, ptr->saved_custom_code_status,
3039 sizeof (custom_code_status));
3040 memcpy (custom_code_index, ptr->saved_custom_code_index,
3041 sizeof (custom_code_index));
3044 /* Inner function to process the attribute((target(...))), take an argument and
3045 set the current options from the argument. If we have a list, recursively
3046 go over the list. */
3048 static bool
3049 nios2_valid_target_attribute_rec (tree args)
3051 if (TREE_CODE (args) == TREE_LIST)
3053 bool ret = true;
3054 for (; args; args = TREE_CHAIN (args))
3055 if (TREE_VALUE (args)
3056 && !nios2_valid_target_attribute_rec (TREE_VALUE (args)))
3057 ret = false;
3058 return ret;
3060 else if (TREE_CODE (args) == STRING_CST)
3062 char *argstr = ASTRDUP (TREE_STRING_POINTER (args));
3063 while (argstr && *argstr != '\0')
3065 bool no_opt = false, end_p = false;
3066 char *eq = NULL, *p;
3067 while (ISSPACE (*argstr))
3068 argstr++;
3069 p = argstr;
3070 while (*p != '\0' && *p != ',')
3072 if (!eq && *p == '=')
3073 eq = p;
3074 ++p;
3076 if (*p == '\0')
3077 end_p = true;
3078 else
3079 *p = '\0';
3080 if (eq) *eq = '\0';
3082 if (!strncmp (argstr, "no-", 3))
3084 no_opt = true;
3085 argstr += 3;
3087 if (!strncmp (argstr, "custom-fpu-cfg", 14))
3089 char *end_eq = p;
3090 if (no_opt)
3092 error ("custom-fpu-cfg option does not support %<no-%>");
3093 return false;
3095 if (!eq)
3097 error ("custom-fpu-cfg option requires configuration"
3098 " argument");
3099 return false;
3101 /* Increment and skip whitespace. */
3102 while (ISSPACE (*(++eq))) ;
3103 /* Decrement and skip to before any trailing whitespace. */
3104 while (ISSPACE (*(--end_eq))) ;
3106 nios2_handle_custom_fpu_cfg (eq, end_eq + 1, true);
3108 else if (!strncmp (argstr, "custom-", 7))
3110 int code = -1;
3111 unsigned int i;
3112 for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
3113 if (!strncmp (argstr + 7, N2FPU_NAME (i),
3114 strlen (N2FPU_NAME (i))))
3116 /* Found insn. */
3117 code = i;
3118 break;
3120 if (code >= 0)
3122 if (no_opt)
3124 if (eq)
3126 error ("%<no-custom-%s%> does not accept arguments",
3127 N2FPU_NAME (code));
3128 return false;
3130 /* Disable option by setting to -1. */
3131 nios2_deregister_custom_code (N2FPU_N (code));
3132 N2FPU_N (code) = -1;
3134 else
3136 char *t;
3137 if (eq)
3138 while (ISSPACE (*(++eq))) ;
3139 if (!eq || eq == p)
3141 error ("%<custom-%s=%> requires argument",
3142 N2FPU_NAME (code));
3143 return false;
3145 for (t = eq; t != p; ++t)
3147 if (ISSPACE (*t))
3148 continue;
3149 if (!ISDIGIT (*t))
3151 error ("`custom-%s=' argument requires "
3152 "numeric digits", N2FPU_NAME (code));
3153 return false;
3156 /* Set option to argument. */
3157 N2FPU_N (code) = atoi (eq);
3158 nios2_handle_custom_fpu_insn_option (code);
3161 else
3163 error ("%<custom-%s=%> is not recognised as FPU instruction",
3164 argstr + 7);
3165 return false;
3168 else
3170 error ("%<%s%> is unknown", argstr);
3171 return false;
3174 if (end_p)
3175 break;
3176 else
3177 argstr = p + 1;
3179 return true;
3181 else
3182 gcc_unreachable ();
3185 /* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. */
3187 static tree
3188 nios2_valid_target_attribute_tree (tree args)
3190 if (!nios2_valid_target_attribute_rec (args))
3191 return NULL_TREE;
3192 nios2_custom_check_insns ();
3193 return build_target_option_node (&global_options);
3196 /* Hook to validate attribute((target("string"))). */
3198 static bool
3199 nios2_valid_target_attribute_p (tree fndecl, tree ARG_UNUSED (name),
3200 tree args, int ARG_UNUSED (flags))
3202 struct cl_target_option cur_target;
3203 bool ret = true;
3204 tree old_optimize = build_optimization_node (&global_options);
3205 tree new_target, new_optimize;
3206 tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
3208 /* If the function changed the optimization levels as well as setting target
3209 options, start with the optimizations specified. */
3210 if (func_optimize && func_optimize != old_optimize)
3211 cl_optimization_restore (&global_options,
3212 TREE_OPTIMIZATION (func_optimize));
3214 /* The target attributes may also change some optimization flags, so update
3215 the optimization options if necessary. */
3216 cl_target_option_save (&cur_target, &global_options);
3217 new_target = nios2_valid_target_attribute_tree (args);
3218 new_optimize = build_optimization_node (&global_options);
3220 if (!new_target)
3221 ret = false;
3223 else if (fndecl)
3225 DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
3227 if (old_optimize != new_optimize)
3228 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
3231 cl_target_option_restore (&global_options, &cur_target);
3233 if (old_optimize != new_optimize)
3234 cl_optimization_restore (&global_options,
3235 TREE_OPTIMIZATION (old_optimize));
3236 return ret;
3239 /* Remember the last target of nios2_set_current_function. */
3240 static GTY(()) tree nios2_previous_fndecl;
3242 /* Establish appropriate back-end context for processing the function
3243 FNDECL. The argument might be NULL to indicate processing at top
3244 level, outside of any function scope. */
3245 static void
3246 nios2_set_current_function (tree fndecl)
3248 tree old_tree = (nios2_previous_fndecl
3249 ? DECL_FUNCTION_SPECIFIC_TARGET (nios2_previous_fndecl)
3250 : NULL_TREE);
3252 tree new_tree = (fndecl
3253 ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl)
3254 : NULL_TREE);
3256 if (fndecl && fndecl != nios2_previous_fndecl)
3258 nios2_previous_fndecl = fndecl;
3259 if (old_tree == new_tree)
3262 else if (new_tree)
3264 cl_target_option_restore (&global_options,
3265 TREE_TARGET_OPTION (new_tree));
3266 target_reinit ();
3269 else if (old_tree)
3271 struct cl_target_option *def
3272 = TREE_TARGET_OPTION (target_option_current_node);
3274 cl_target_option_restore (&global_options, def);
3275 target_reinit ();
3280 /* Hook to validate the current #pragma GCC target and set the FPU custom
3281 code option state. If ARGS is NULL, then POP_TARGET is used to reset
3282 the options. */
3283 static bool
3284 nios2_pragma_target_parse (tree args, tree pop_target)
3286 tree cur_tree;
3287 if (! args)
3289 cur_tree = ((pop_target)
3290 ? pop_target
3291 : target_option_default_node);
3292 cl_target_option_restore (&global_options,
3293 TREE_TARGET_OPTION (cur_tree));
3295 else
3297 cur_tree = nios2_valid_target_attribute_tree (args);
3298 if (!cur_tree)
3299 return false;
3302 target_option_current_node = cur_tree;
3303 return true;
3306 /* Implement TARGET_MERGE_DECL_ATTRIBUTES.
3307 We are just using this hook to add some additional error checking to
3308 the default behavior. GCC does not provide a target hook for merging
3309 the target options, and only correctly handles merging empty vs non-empty
3310 option data; see merge_decls() in c-decl.c.
3311 So here we require either that at least one of the decls has empty
3312 target options, or that the target options/data be identical. */
3313 static tree
3314 nios2_merge_decl_attributes (tree olddecl, tree newdecl)
3316 tree oldopts = lookup_attribute ("target", DECL_ATTRIBUTES (olddecl));
3317 tree newopts = lookup_attribute ("target", DECL_ATTRIBUTES (newdecl));
3318 if (newopts && oldopts && newopts != oldopts)
3320 tree oldtree = DECL_FUNCTION_SPECIFIC_TARGET (olddecl);
3321 tree newtree = DECL_FUNCTION_SPECIFIC_TARGET (newdecl);
3322 if (oldtree && newtree && oldtree != newtree)
3324 struct cl_target_option *olddata = TREE_TARGET_OPTION (oldtree);
3325 struct cl_target_option *newdata = TREE_TARGET_OPTION (newtree);
3326 if (olddata != newdata
3327 && memcmp (olddata, newdata, sizeof (struct cl_target_option)))
3328 error ("%qE redeclared with conflicting %qs attributes",
3329 DECL_NAME (newdecl), "target");
3332 return merge_attributes (DECL_ATTRIBUTES (olddecl),
3333 DECL_ATTRIBUTES (newdecl));
3336 /* Implement TARGET_ASM_OUTPUT_MI_THUNK. */
3337 static void
3338 nios2_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
3339 HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
3340 tree function)
3342 rtx this_rtx, funexp;
3343 rtx_insn *insn;
3345 /* Pretend to be a post-reload pass while generating rtl. */
3346 reload_completed = 1;
3348 if (flag_pic)
3349 nios2_load_pic_register ();
3351 /* Mark the end of the (empty) prologue. */
3352 emit_note (NOTE_INSN_PROLOGUE_END);
3354 /* Find the "this" pointer. If the function returns a structure,
3355 the structure return pointer is in $5. */
3356 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
3357 this_rtx = gen_rtx_REG (Pmode, FIRST_ARG_REGNO + 1);
3358 else
3359 this_rtx = gen_rtx_REG (Pmode, FIRST_ARG_REGNO);
3361 /* Add DELTA to THIS_RTX. */
3362 nios2_emit_add_constant (this_rtx, delta);
3364 /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */
3365 if (vcall_offset)
3367 rtx tmp;
3369 tmp = gen_rtx_REG (Pmode, 2);
3370 emit_move_insn (tmp, gen_rtx_MEM (Pmode, this_rtx));
3371 nios2_emit_add_constant (tmp, vcall_offset);
3372 emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
3373 emit_insn (gen_add2_insn (this_rtx, tmp));
3376 /* Generate a tail call to the target function. */
3377 if (!TREE_USED (function))
3379 assemble_external (function);
3380 TREE_USED (function) = 1;
3382 funexp = XEXP (DECL_RTL (function), 0);
3383 /* Function address needs to be constructed under PIC,
3384 provide r2 to use here. */
3385 nios2_adjust_call_address (&funexp, gen_rtx_REG (Pmode, 2));
3386 insn = emit_call_insn (gen_sibcall_internal (funexp, const0_rtx));
3387 SIBLING_CALL_P (insn) = 1;
3389 /* Run just enough of rest_of_compilation to get the insns emitted.
3390 There's not really enough bulk here to make other passes such as
3391 instruction scheduling worth while. Note that use_thunk calls
3392 assemble_start_function and assemble_end_function. */
3393 insn = get_insns ();
3394 shorten_branches (insn);
3395 final_start_function (insn, file, 1);
3396 final (insn, file, 1);
3397 final_end_function ();
3399 /* Stop pretending to be a post-reload pass. */
3400 reload_completed = 0;
3404 /* Initialize the GCC target structure. */
3405 #undef TARGET_ASM_FUNCTION_PROLOGUE
3406 #define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
3408 #undef TARGET_IN_SMALL_DATA_P
3409 #define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
3411 #undef TARGET_SECTION_TYPE_FLAGS
3412 #define TARGET_SECTION_TYPE_FLAGS nios2_section_type_flags
3414 #undef TARGET_INIT_BUILTINS
3415 #define TARGET_INIT_BUILTINS nios2_init_builtins
3416 #undef TARGET_EXPAND_BUILTIN
3417 #define TARGET_EXPAND_BUILTIN nios2_expand_builtin
3418 #undef TARGET_BUILTIN_DECL
3419 #define TARGET_BUILTIN_DECL nios2_builtin_decl
3421 #undef TARGET_INIT_LIBFUNCS
3422 #define TARGET_INIT_LIBFUNCS nios2_init_libfuncs
3424 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
3425 #define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
3427 #undef TARGET_CAN_ELIMINATE
3428 #define TARGET_CAN_ELIMINATE nios2_can_eliminate
3430 #undef TARGET_FUNCTION_ARG
3431 #define TARGET_FUNCTION_ARG nios2_function_arg
3433 #undef TARGET_FUNCTION_ARG_ADVANCE
3434 #define TARGET_FUNCTION_ARG_ADVANCE nios2_function_arg_advance
3436 #undef TARGET_ARG_PARTIAL_BYTES
3437 #define TARGET_ARG_PARTIAL_BYTES nios2_arg_partial_bytes
3439 #undef TARGET_TRAMPOLINE_INIT
3440 #define TARGET_TRAMPOLINE_INIT nios2_trampoline_init
3442 #undef TARGET_FUNCTION_VALUE
3443 #define TARGET_FUNCTION_VALUE nios2_function_value
3445 #undef TARGET_LIBCALL_VALUE
3446 #define TARGET_LIBCALL_VALUE nios2_libcall_value
3448 #undef TARGET_FUNCTION_VALUE_REGNO_P
3449 #define TARGET_FUNCTION_VALUE_REGNO_P nios2_function_value_regno_p
3451 #undef TARGET_RETURN_IN_MEMORY
3452 #define TARGET_RETURN_IN_MEMORY nios2_return_in_memory
3454 #undef TARGET_PROMOTE_PROTOTYPES
3455 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
3457 #undef TARGET_SETUP_INCOMING_VARARGS
3458 #define TARGET_SETUP_INCOMING_VARARGS nios2_setup_incoming_varargs
3460 #undef TARGET_MUST_PASS_IN_STACK
3461 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
3463 #undef TARGET_LEGITIMATE_CONSTANT_P
3464 #define TARGET_LEGITIMATE_CONSTANT_P nios2_legitimate_constant_p
3466 #undef TARGET_LEGITIMIZE_ADDRESS
3467 #define TARGET_LEGITIMIZE_ADDRESS nios2_legitimize_address
3469 #undef TARGET_DELEGITIMIZE_ADDRESS
3470 #define TARGET_DELEGITIMIZE_ADDRESS nios2_delegitimize_address
3472 #undef TARGET_LEGITIMATE_ADDRESS_P
3473 #define TARGET_LEGITIMATE_ADDRESS_P nios2_legitimate_address_p
3475 #undef TARGET_PREFERRED_RELOAD_CLASS
3476 #define TARGET_PREFERRED_RELOAD_CLASS nios2_preferred_reload_class
3478 #undef TARGET_RTX_COSTS
3479 #define TARGET_RTX_COSTS nios2_rtx_costs
3481 #undef TARGET_HAVE_TLS
3482 #define TARGET_HAVE_TLS TARGET_LINUX_ABI
3484 #undef TARGET_CANNOT_FORCE_CONST_MEM
3485 #define TARGET_CANNOT_FORCE_CONST_MEM nios2_cannot_force_const_mem
3487 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
3488 #define TARGET_ASM_OUTPUT_DWARF_DTPREL nios2_output_dwarf_dtprel
3490 #undef TARGET_PRINT_OPERAND
3491 #define TARGET_PRINT_OPERAND nios2_print_operand
3493 #undef TARGET_PRINT_OPERAND_ADDRESS
3494 #define TARGET_PRINT_OPERAND_ADDRESS nios2_print_operand_address
3496 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
3497 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA nios2_output_addr_const_extra
3499 #undef TARGET_ASM_FILE_END
3500 #define TARGET_ASM_FILE_END nios2_asm_file_end
3502 #undef TARGET_OPTION_OVERRIDE
3503 #define TARGET_OPTION_OVERRIDE nios2_option_override
3505 #undef TARGET_OPTION_SAVE
3506 #define TARGET_OPTION_SAVE nios2_option_save
3508 #undef TARGET_OPTION_RESTORE
3509 #define TARGET_OPTION_RESTORE nios2_option_restore
3511 #undef TARGET_SET_CURRENT_FUNCTION
3512 #define TARGET_SET_CURRENT_FUNCTION nios2_set_current_function
3514 #undef TARGET_OPTION_VALID_ATTRIBUTE_P
3515 #define TARGET_OPTION_VALID_ATTRIBUTE_P nios2_valid_target_attribute_p
3517 #undef TARGET_OPTION_PRAGMA_PARSE
3518 #define TARGET_OPTION_PRAGMA_PARSE nios2_pragma_target_parse
3520 #undef TARGET_MERGE_DECL_ATTRIBUTES
3521 #define TARGET_MERGE_DECL_ATTRIBUTES nios2_merge_decl_attributes
3523 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
3524 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
3525 hook_bool_const_tree_hwi_hwi_const_tree_true
3527 #undef TARGET_ASM_OUTPUT_MI_THUNK
3528 #define TARGET_ASM_OUTPUT_MI_THUNK nios2_asm_output_mi_thunk
3530 struct gcc_target targetm = TARGET_INITIALIZER;
3532 #include "gt-nios2.h"