1 /* Target machine subroutines for Altera Nios II.
2 Copyright (C) 2012-2014 Free Software Foundation, Inc.
3 Contributed by Jonah Graham (jgraham@altera.com),
4 Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@altera.com).
5 Contributed by Mentor Graphics, Inc.
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/>. */
25 #include "coretypes.h"
30 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
34 #include "insn-attr.h"
41 #include "basic-block.h"
42 #include "diagnostic-core.h"
45 #include "target-def.h"
47 #include "langhooks.h"
52 #include "stor-layout.h"
56 /* Forward function declarations. */
57 static bool prologue_saved_reg_p (unsigned);
58 static void nios2_load_pic_register (void);
59 static void nios2_register_custom_code (unsigned int, enum nios2_ccs_code
, int);
60 static const char *nios2_unspec_reloc_name (int);
61 static void nios2_register_builtin_fndecl (unsigned, tree
);
63 /* Threshold for data being put into the small data/bss area, instead
64 of the normal data area (references to the small data/bss area take
65 1 instruction, and use the global pointer, references to the normal
66 data area takes 2 instructions). */
67 unsigned HOST_WIDE_INT nios2_section_threshold
= NIOS2_DEFAULT_GVALUE
;
69 struct GTY (()) machine_function
71 /* Current frame information, to be filled in by nios2_compute_frame_layout
72 with register save masks, and offsets for the current function. */
74 /* Mask of registers to save. */
75 unsigned int save_mask
;
76 /* Number of bytes that the entire frame takes up. */
78 /* Number of bytes that variables take up. */
80 /* Number of bytes that outgoing arguments take up. */
82 /* Number of bytes needed to store registers in frame. */
84 /* Offset from new stack pointer to store registers. */
86 /* != 0 if frame layout already calculated. */
90 /* State to track the assignment of custom codes to FPU/custom builtins. */
91 static enum nios2_ccs_code custom_code_status
[256];
92 static int custom_code_index
[256];
93 /* Set to true if any conflicts (re-use of a code between 0-255) are found. */
94 static bool custom_code_conflict
= false;
97 /* Definition of builtin function types for nios2. */
101 N2_FTYPE(1, (VOID)) \
102 N2_FTYPE(2, (DF, DF)) \
103 N2_FTYPE(3, (DF, DF, DF)) \
104 N2_FTYPE(2, (DF, SF)) \
105 N2_FTYPE(2, (DF, SI)) \
106 N2_FTYPE(2, (DF, UI)) \
107 N2_FTYPE(2, (SF, DF)) \
108 N2_FTYPE(2, (SF, SF)) \
109 N2_FTYPE(3, (SF, SF, SF)) \
110 N2_FTYPE(2, (SF, SI)) \
111 N2_FTYPE(2, (SF, UI)) \
112 N2_FTYPE(2, (SI, CVPTR)) \
113 N2_FTYPE(2, (SI, DF)) \
114 N2_FTYPE(3, (SI, DF, DF)) \
115 N2_FTYPE(2, (SI, SF)) \
116 N2_FTYPE(3, (SI, SF, SF)) \
117 N2_FTYPE(2, (SI, SI)) \
118 N2_FTYPE(2, (UI, CVPTR)) \
119 N2_FTYPE(2, (UI, DF)) \
120 N2_FTYPE(2, (UI, SF)) \
121 N2_FTYPE(2, (VOID, DF)) \
122 N2_FTYPE(2, (VOID, SF)) \
123 N2_FTYPE(3, (VOID, SI, SI)) \
124 N2_FTYPE(3, (VOID, VPTR, SI))
126 #define N2_FTYPE_OP1(R) N2_FTYPE_ ## R ## _VOID
127 #define N2_FTYPE_OP2(R, A1) N2_FTYPE_ ## R ## _ ## A1
128 #define N2_FTYPE_OP3(R, A1, A2) N2_FTYPE_ ## R ## _ ## A1 ## _ ## A2
130 /* Expand ftcode enumeration. */
132 #define N2_FTYPE(N,ARGS) N2_FTYPE_OP ## N ARGS,
138 /* Return the tree function type, based on the ftcode. */
140 nios2_ftype (enum nios2_ftcode ftcode
)
142 static tree types
[(int) N2_FTYPE_MAX
];
144 tree N2_TYPE_SF
= float_type_node
;
145 tree N2_TYPE_DF
= double_type_node
;
146 tree N2_TYPE_SI
= integer_type_node
;
147 tree N2_TYPE_UI
= unsigned_type_node
;
148 tree N2_TYPE_VOID
= void_type_node
;
150 static const_tree N2_TYPE_CVPTR
, N2_TYPE_VPTR
;
153 /* const volatile void *. */
155 = build_pointer_type (build_qualified_type (void_type_node
,
157 | TYPE_QUAL_VOLATILE
)));
158 /* volatile void *. */
160 = build_pointer_type (build_qualified_type (void_type_node
,
161 TYPE_QUAL_VOLATILE
));
163 if (types
[(int) ftcode
] == NULL_TREE
)
166 #define N2_FTYPE_ARGS1(R) N2_TYPE_ ## R
167 #define N2_FTYPE_ARGS2(R,A1) N2_TYPE_ ## R, N2_TYPE_ ## A1
168 #define N2_FTYPE_ARGS3(R,A1,A2) N2_TYPE_ ## R, N2_TYPE_ ## A1, N2_TYPE_ ## A2
169 #define N2_FTYPE(N,ARGS) \
170 case N2_FTYPE_OP ## N ARGS: \
171 types[(int) ftcode] \
172 = build_function_type_list (N2_FTYPE_ARGS ## N ARGS, NULL_TREE); \
176 default: gcc_unreachable ();
178 return types
[(int) ftcode
];
182 /* Definition of FPU instruction descriptions. */
184 struct nios2_fpu_insn_info
187 int num_operands
, *optvar
;
190 #define N2F_DFREQ 0x2
191 #define N2F_UNSAFE 0x4
192 #define N2F_FINITE 0x8
194 enum insn_code icode
;
195 enum nios2_ftcode ftcode
;
198 /* Base macro for defining FPU instructions. */
199 #define N2FPU_INSN_DEF_BASE(insn, nop, flags, icode, args) \
200 { #insn, nop, &nios2_custom_ ## insn, OPT_mcustom_##insn##_, \
201 OPT_mno_custom_##insn, flags, CODE_FOR_ ## icode, \
202 N2_FTYPE_OP ## nop args }
204 /* Arithmetic and math functions; 2 or 3 operand FP operations. */
205 #define N2FPU_OP2(mode) (mode, mode)
206 #define N2FPU_OP3(mode) (mode, mode, mode)
207 #define N2FPU_INSN_DEF(code, icode, nop, flags, m, M) \
208 N2FPU_INSN_DEF_BASE (f ## code ## m, nop, flags, \
209 icode ## m ## f ## nop, N2FPU_OP ## nop (M ## F))
210 #define N2FPU_INSN_SF(code, nop, flags) \
211 N2FPU_INSN_DEF (code, code, nop, flags, s, S)
212 #define N2FPU_INSN_DF(code, nop, flags) \
213 N2FPU_INSN_DEF (code, code, nop, flags | N2F_DF, d, D)
215 /* Compare instructions, 3 operand FP operation with a SI result. */
216 #define N2FPU_CMP_DEF(code, flags, m, M) \
217 N2FPU_INSN_DEF_BASE (fcmp ## code ## m, 3, flags, \
218 nios2_s ## code ## m ## f, (SI, M ## F, M ## F))
219 #define N2FPU_CMP_SF(code) N2FPU_CMP_DEF (code, 0, s, S)
220 #define N2FPU_CMP_DF(code) N2FPU_CMP_DEF (code, N2F_DF, d, D)
222 /* The order of definition needs to be maintained consistent with
223 enum n2fpu_code in nios2-opts.h. */
224 struct nios2_fpu_insn_info nios2_fpu_insn
[] =
226 /* Single precision instructions. */
227 N2FPU_INSN_SF (add
, 3, 0),
228 N2FPU_INSN_SF (sub
, 3, 0),
229 N2FPU_INSN_SF (mul
, 3, 0),
230 N2FPU_INSN_SF (div
, 3, 0),
231 /* Due to textual difference between min/max and smin/smax. */
232 N2FPU_INSN_DEF (min
, smin
, 3, N2F_FINITE
, s
, S
),
233 N2FPU_INSN_DEF (max
, smax
, 3, N2F_FINITE
, s
, S
),
234 N2FPU_INSN_SF (neg
, 2, 0),
235 N2FPU_INSN_SF (abs
, 2, 0),
236 N2FPU_INSN_SF (sqrt
, 2, 0),
237 N2FPU_INSN_SF (sin
, 2, N2F_UNSAFE
),
238 N2FPU_INSN_SF (cos
, 2, N2F_UNSAFE
),
239 N2FPU_INSN_SF (tan
, 2, N2F_UNSAFE
),
240 N2FPU_INSN_SF (atan
, 2, N2F_UNSAFE
),
241 N2FPU_INSN_SF (exp
, 2, N2F_UNSAFE
),
242 N2FPU_INSN_SF (log
, 2, N2F_UNSAFE
),
243 /* Single precision compares. */
244 N2FPU_CMP_SF (eq
), N2FPU_CMP_SF (ne
),
245 N2FPU_CMP_SF (lt
), N2FPU_CMP_SF (le
),
246 N2FPU_CMP_SF (gt
), N2FPU_CMP_SF (ge
),
248 /* Double precision instructions. */
249 N2FPU_INSN_DF (add
, 3, 0),
250 N2FPU_INSN_DF (sub
, 3, 0),
251 N2FPU_INSN_DF (mul
, 3, 0),
252 N2FPU_INSN_DF (div
, 3, 0),
253 /* Due to textual difference between min/max and smin/smax. */
254 N2FPU_INSN_DEF (min
, smin
, 3, N2F_FINITE
, d
, D
),
255 N2FPU_INSN_DEF (max
, smax
, 3, N2F_FINITE
, d
, D
),
256 N2FPU_INSN_DF (neg
, 2, 0),
257 N2FPU_INSN_DF (abs
, 2, 0),
258 N2FPU_INSN_DF (sqrt
, 2, 0),
259 N2FPU_INSN_DF (sin
, 2, N2F_UNSAFE
),
260 N2FPU_INSN_DF (cos
, 2, N2F_UNSAFE
),
261 N2FPU_INSN_DF (tan
, 2, N2F_UNSAFE
),
262 N2FPU_INSN_DF (atan
, 2, N2F_UNSAFE
),
263 N2FPU_INSN_DF (exp
, 2, N2F_UNSAFE
),
264 N2FPU_INSN_DF (log
, 2, N2F_UNSAFE
),
265 /* Double precision compares. */
266 N2FPU_CMP_DF (eq
), N2FPU_CMP_DF (ne
),
267 N2FPU_CMP_DF (lt
), N2FPU_CMP_DF (le
),
268 N2FPU_CMP_DF (gt
), N2FPU_CMP_DF (ge
),
270 /* Conversion instructions. */
271 N2FPU_INSN_DEF_BASE (floatis
, 2, 0, floatsisf2
, (SF
, SI
)),
272 N2FPU_INSN_DEF_BASE (floatus
, 2, 0, floatunssisf2
, (SF
, UI
)),
273 N2FPU_INSN_DEF_BASE (floatid
, 2, 0, floatsidf2
, (DF
, SI
)),
274 N2FPU_INSN_DEF_BASE (floatud
, 2, 0, floatunssidf2
, (DF
, UI
)),
275 N2FPU_INSN_DEF_BASE (fixsi
, 2, 0, fix_truncsfsi2
, (SI
, SF
)),
276 N2FPU_INSN_DEF_BASE (fixsu
, 2, 0, fixuns_truncsfsi2
, (UI
, SF
)),
277 N2FPU_INSN_DEF_BASE (fixdi
, 2, 0, fix_truncdfsi2
, (SI
, DF
)),
278 N2FPU_INSN_DEF_BASE (fixdu
, 2, 0, fixuns_truncdfsi2
, (UI
, DF
)),
279 N2FPU_INSN_DEF_BASE (fextsd
, 2, 0, extendsfdf2
, (DF
, SF
)),
280 N2FPU_INSN_DEF_BASE (ftruncds
, 2, 0, truncdfsf2
, (SF
, DF
)),
282 /* X, Y access instructions. */
283 N2FPU_INSN_DEF_BASE (fwrx
, 2, N2F_DFREQ
, nios2_fwrx
, (VOID
, DF
)),
284 N2FPU_INSN_DEF_BASE (fwry
, 2, N2F_DFREQ
, nios2_fwry
, (VOID
, SF
)),
285 N2FPU_INSN_DEF_BASE (frdxlo
, 1, N2F_DFREQ
, nios2_frdxlo
, (SF
)),
286 N2FPU_INSN_DEF_BASE (frdxhi
, 1, N2F_DFREQ
, nios2_frdxhi
, (SF
)),
287 N2FPU_INSN_DEF_BASE (frdy
, 1, N2F_DFREQ
, nios2_frdy
, (SF
))
290 /* Some macros for ease of access. */
291 #define N2FPU(code) nios2_fpu_insn[(int) code]
292 #define N2FPU_ENABLED_P(code) (N2FPU_N(code) >= 0)
293 #define N2FPU_N(code) (*N2FPU(code).optvar)
294 #define N2FPU_NAME(code) (N2FPU(code).name)
295 #define N2FPU_ICODE(code) (N2FPU(code).icode)
296 #define N2FPU_FTCODE(code) (N2FPU(code).ftcode)
297 #define N2FPU_FINITE_P(code) (N2FPU(code).flags & N2F_FINITE)
298 #define N2FPU_UNSAFE_P(code) (N2FPU(code).flags & N2F_UNSAFE)
299 #define N2FPU_DOUBLE_P(code) (N2FPU(code).flags & N2F_DF)
300 #define N2FPU_DOUBLE_REQUIRED_P(code) (N2FPU(code).flags & N2F_DFREQ)
302 /* Same as above, but for cases where using only the op part is shorter. */
303 #define N2FPU_OP(op) N2FPU(n2fpu_ ## op)
304 #define N2FPU_OP_NAME(op) N2FPU_NAME(n2fpu_ ## op)
305 #define N2FPU_OP_ENABLED_P(op) N2FPU_ENABLED_P(n2fpu_ ## op)
307 /* Export the FPU insn enabled predicate to nios2.md. */
309 nios2_fpu_insn_enabled (enum n2fpu_code code
)
311 return N2FPU_ENABLED_P (code
);
314 /* Return true if COND comparison for mode MODE is enabled under current
318 nios2_fpu_compare_enabled (enum rtx_code cond
, enum machine_mode mode
)
323 case EQ
: return N2FPU_OP_ENABLED_P (fcmpeqs
);
324 case NE
: return N2FPU_OP_ENABLED_P (fcmpnes
);
325 case GT
: return N2FPU_OP_ENABLED_P (fcmpgts
);
326 case GE
: return N2FPU_OP_ENABLED_P (fcmpges
);
327 case LT
: return N2FPU_OP_ENABLED_P (fcmplts
);
328 case LE
: return N2FPU_OP_ENABLED_P (fcmples
);
331 else if (mode
== DFmode
)
334 case EQ
: return N2FPU_OP_ENABLED_P (fcmpeqd
);
335 case NE
: return N2FPU_OP_ENABLED_P (fcmpned
);
336 case GT
: return N2FPU_OP_ENABLED_P (fcmpgtd
);
337 case GE
: return N2FPU_OP_ENABLED_P (fcmpged
);
338 case LT
: return N2FPU_OP_ENABLED_P (fcmpltd
);
339 case LE
: return N2FPU_OP_ENABLED_P (fcmpled
);
345 /* Stack layout and calling conventions. */
347 #define NIOS2_STACK_ALIGN(LOC) \
348 (((LOC) + ((PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) - 1)) \
349 & ~((PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) - 1))
351 /* Return the bytes needed to compute the frame pointer from the current
354 nios2_compute_frame_layout (void)
357 unsigned int save_mask
= 0;
363 if (cfun
->machine
->initialized
)
364 return cfun
->machine
->total_size
;
366 var_size
= NIOS2_STACK_ALIGN (get_frame_size ());
367 out_args_size
= NIOS2_STACK_ALIGN (crtl
->outgoing_args_size
);
368 total_size
= var_size
+ out_args_size
;
370 /* Calculate space needed for gp registers. */
372 for (regno
= 0; regno
<= LAST_GP_REG
; regno
++)
373 if (prologue_saved_reg_p (regno
))
375 save_mask
|= 1 << regno
;
379 /* If we call eh_return, we need to save the EH data registers. */
380 if (crtl
->calls_eh_return
)
385 for (i
= 0; (r
= EH_RETURN_DATA_REGNO (i
)) != INVALID_REGNUM
; i
++)
386 if (!(save_mask
& (1 << r
)))
393 save_reg_size
= NIOS2_STACK_ALIGN (save_reg_size
);
394 total_size
+= save_reg_size
;
395 total_size
+= NIOS2_STACK_ALIGN (crtl
->args
.pretend_args_size
);
397 /* Save other computed information. */
398 cfun
->machine
->save_mask
= save_mask
;
399 cfun
->machine
->total_size
= total_size
;
400 cfun
->machine
->var_size
= var_size
;
401 cfun
->machine
->args_size
= out_args_size
;
402 cfun
->machine
->save_reg_size
= save_reg_size
;
403 cfun
->machine
->initialized
= reload_completed
;
404 cfun
->machine
->save_regs_offset
= out_args_size
+ var_size
;
409 /* Generate save/restore of register REGNO at SP + OFFSET. Used by the
410 prologue/epilogue expand routines. */
412 save_reg (int regno
, unsigned offset
)
414 rtx reg
= gen_rtx_REG (SImode
, regno
);
415 rtx addr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
416 gen_int_mode (offset
, Pmode
));
417 rtx insn
= emit_move_insn (gen_frame_mem (Pmode
, addr
), reg
);
418 RTX_FRAME_RELATED_P (insn
) = 1;
422 restore_reg (int regno
, unsigned offset
)
424 rtx reg
= gen_rtx_REG (SImode
, regno
);
425 rtx addr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
426 gen_int_mode (offset
, Pmode
));
427 rtx insn
= emit_move_insn (reg
, gen_frame_mem (Pmode
, addr
));
428 /* Tag epilogue unwind note. */
429 add_reg_note (insn
, REG_CFA_RESTORE
, reg
);
430 RTX_FRAME_RELATED_P (insn
) = 1;
433 /* Emit conditional trap for checking stack limit. */
435 nios2_emit_stack_limit_check (void)
437 if (REG_P (stack_limit_rtx
))
438 emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode
, stack_pointer_rtx
,
440 stack_pointer_rtx
, stack_limit_rtx
, GEN_INT (3)));
442 sorry ("only register based stack limit is supported");
445 /* Temp regno used inside prologue/epilogue. */
446 #define TEMP_REG_NUM 8
449 nios2_expand_prologue (void)
452 int total_frame_size
, save_offset
;
453 int sp_offset
; /* offset from base_reg to final stack value. */
454 int fp_offset
; /* offset from base_reg to final fp value. */
457 total_frame_size
= nios2_compute_frame_layout ();
459 if (flag_stack_usage_info
)
460 current_function_static_stack_size
= total_frame_size
;
462 /* Decrement the stack pointer. */
463 if (!SMALL_INT (total_frame_size
))
465 /* We need an intermediary point, this will point at the spill block. */
467 (gen_add2_insn (stack_pointer_rtx
,
468 gen_int_mode (cfun
->machine
->save_regs_offset
469 - total_frame_size
, Pmode
)));
470 RTX_FRAME_RELATED_P (insn
) = 1;
473 sp_offset
= -cfun
->machine
->save_regs_offset
;
475 else if (total_frame_size
)
477 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
,
478 gen_int_mode (-total_frame_size
,
480 RTX_FRAME_RELATED_P (insn
) = 1;
481 fp_offset
= cfun
->machine
->save_regs_offset
;
485 fp_offset
= sp_offset
= 0;
487 if (crtl
->limit_stack
)
488 nios2_emit_stack_limit_check ();
490 save_offset
= fp_offset
+ cfun
->machine
->save_reg_size
;
492 for (regno
= LAST_GP_REG
; regno
> 0; regno
--)
493 if (cfun
->machine
->save_mask
& (1 << regno
))
496 save_reg (regno
, save_offset
);
499 if (frame_pointer_needed
)
501 insn
= emit_insn (gen_add3_insn (hard_frame_pointer_rtx
,
503 gen_int_mode (fp_offset
, Pmode
)));
504 RTX_FRAME_RELATED_P (insn
) = 1;
510 = gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
511 plus_constant (Pmode
, stack_pointer_rtx
, sp_offset
));
512 if (SMALL_INT (sp_offset
))
513 insn
= emit_insn (sp_adjust
);
516 rtx tmp
= gen_rtx_REG (Pmode
, TEMP_REG_NUM
);
517 emit_move_insn (tmp
, gen_int_mode (sp_offset
, Pmode
));
518 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
, tmp
));
519 /* Attach the sp_adjust as a note indicating what happened. */
520 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
, sp_adjust
);
522 RTX_FRAME_RELATED_P (insn
) = 1;
524 if (crtl
->limit_stack
)
525 nios2_emit_stack_limit_check ();
528 /* Load the PIC register if needed. */
529 if (crtl
->uses_pic_offset_table
)
530 nios2_load_pic_register ();
532 /* If we are profiling, make sure no instructions are scheduled before
533 the call to mcount. */
535 emit_insn (gen_blockage ());
539 nios2_expand_epilogue (bool sibcall_p
)
542 int total_frame_size
;
543 int sp_adjust
, save_offset
;
546 if (!sibcall_p
&& nios2_can_use_return_insn ())
548 emit_jump_insn (gen_return ());
552 emit_insn (gen_blockage ());
554 total_frame_size
= nios2_compute_frame_layout ();
555 if (frame_pointer_needed
)
557 /* Recover the stack pointer. */
558 insn
= emit_move_insn (stack_pointer_rtx
, hard_frame_pointer_rtx
);
559 cfa_adj
= plus_constant (Pmode
, stack_pointer_rtx
,
561 - cfun
->machine
->save_regs_offset
));
562 add_reg_note (insn
, REG_CFA_DEF_CFA
, cfa_adj
);
563 RTX_FRAME_RELATED_P (insn
) = 1;
566 sp_adjust
= total_frame_size
- cfun
->machine
->save_regs_offset
;
568 else if (!SMALL_INT (total_frame_size
))
570 rtx tmp
= gen_rtx_REG (Pmode
, TEMP_REG_NUM
);
571 emit_move_insn (tmp
, gen_int_mode (cfun
->machine
->save_regs_offset
,
573 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
, tmp
));
574 cfa_adj
= gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
575 plus_constant (Pmode
, stack_pointer_rtx
,
576 cfun
->machine
->save_regs_offset
));
577 add_reg_note (insn
, REG_CFA_ADJUST_CFA
, cfa_adj
);
578 RTX_FRAME_RELATED_P (insn
) = 1;
580 sp_adjust
= total_frame_size
- cfun
->machine
->save_regs_offset
;
584 save_offset
= cfun
->machine
->save_regs_offset
;
585 sp_adjust
= total_frame_size
;
588 save_offset
+= cfun
->machine
->save_reg_size
;
590 for (regno
= LAST_GP_REG
; regno
> 0; regno
--)
591 if (cfun
->machine
->save_mask
& (1 << regno
))
594 restore_reg (regno
, save_offset
);
599 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
,
600 gen_int_mode (sp_adjust
, Pmode
)));
601 cfa_adj
= gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
602 plus_constant (Pmode
, stack_pointer_rtx
,
604 add_reg_note (insn
, REG_CFA_ADJUST_CFA
, cfa_adj
);
605 RTX_FRAME_RELATED_P (insn
) = 1;
608 /* Add in the __builtin_eh_return stack adjustment. */
609 if (crtl
->calls_eh_return
)
610 emit_insn (gen_add2_insn (stack_pointer_rtx
, EH_RETURN_STACKADJ_RTX
));
613 emit_jump_insn (gen_simple_return ());
616 /* Implement RETURN_ADDR_RTX. Note, we do not support moving
617 back to a previous frame. */
619 nios2_get_return_address (int count
)
624 return get_hard_reg_initial_val (Pmode
, RA_REGNO
);
627 /* Emit code to change the current function's return address to
628 ADDRESS. SCRATCH is available as a scratch register, if needed.
629 ADDRESS and SCRATCH are both word-mode GPRs. */
631 nios2_set_return_address (rtx address
, rtx scratch
)
633 nios2_compute_frame_layout ();
634 if (cfun
->machine
->save_mask
& (1 << RA_REGNO
))
636 unsigned offset
= cfun
->machine
->save_reg_size
- 4;
639 if (frame_pointer_needed
)
640 base
= hard_frame_pointer_rtx
;
643 base
= stack_pointer_rtx
;
644 offset
+= cfun
->machine
->save_regs_offset
;
646 if (!SMALL_INT (offset
))
648 emit_move_insn (scratch
, gen_int_mode (offset
, Pmode
));
649 emit_insn (gen_add2_insn (scratch
, base
));
655 base
= plus_constant (Pmode
, base
, offset
);
656 emit_move_insn (gen_rtx_MEM (Pmode
, base
), address
);
659 emit_move_insn (gen_rtx_REG (Pmode
, RA_REGNO
), address
);
662 /* Implement FUNCTION_PROFILER macro. */
664 nios2_function_profiler (FILE *file
, int labelno ATTRIBUTE_UNUSED
)
666 fprintf (file
, "\tmov\tr8, ra\n");
669 fprintf (file
, "\tnextpc\tr2\n");
670 fprintf (file
, "\t1: movhi\tr3, %%hiadj(_gp_got - 1b)\n");
671 fprintf (file
, "\taddi\tr3, r3, %%lo(_gp_got - 1b)\n");
672 fprintf (file
, "\tadd\tr2, r2, r3\n");
673 fprintf (file
, "\tldw\tr2, %%call(_mcount)(r2)\n");
674 fprintf (file
, "\tcallr\tr2\n");
677 fprintf (file
, "\tcall\t_mcount\n");
678 fprintf (file
, "\tmov\tra, r8\n");
681 /* Dump stack layout. */
683 nios2_dump_frame_layout (FILE *file
)
685 fprintf (file
, "\t%s Current Frame Info\n", ASM_COMMENT_START
);
686 fprintf (file
, "\t%s total_size = %d\n", ASM_COMMENT_START
,
687 cfun
->machine
->total_size
);
688 fprintf (file
, "\t%s var_size = %d\n", ASM_COMMENT_START
,
689 cfun
->machine
->var_size
);
690 fprintf (file
, "\t%s args_size = %d\n", ASM_COMMENT_START
,
691 cfun
->machine
->args_size
);
692 fprintf (file
, "\t%s save_reg_size = %d\n", ASM_COMMENT_START
,
693 cfun
->machine
->save_reg_size
);
694 fprintf (file
, "\t%s initialized = %d\n", ASM_COMMENT_START
,
695 cfun
->machine
->initialized
);
696 fprintf (file
, "\t%s save_regs_offset = %d\n", ASM_COMMENT_START
,
697 cfun
->machine
->save_regs_offset
);
698 fprintf (file
, "\t%s is_leaf = %d\n", ASM_COMMENT_START
,
700 fprintf (file
, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START
,
701 frame_pointer_needed
);
702 fprintf (file
, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START
,
703 crtl
->args
.pretend_args_size
);
706 /* Return true if REGNO should be saved in the prologue. */
708 prologue_saved_reg_p (unsigned regno
)
710 gcc_assert (GP_REG_P (regno
));
712 if (df_regs_ever_live_p (regno
) && !call_used_regs
[regno
])
715 if (regno
== HARD_FRAME_POINTER_REGNUM
&& frame_pointer_needed
)
718 if (regno
== PIC_OFFSET_TABLE_REGNUM
&& crtl
->uses_pic_offset_table
)
721 if (regno
== RA_REGNO
&& df_regs_ever_live_p (RA_REGNO
))
727 /* Implement TARGET_CAN_ELIMINATE. */
729 nios2_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
731 if (to
== STACK_POINTER_REGNUM
)
732 return !frame_pointer_needed
;
736 /* Implement INITIAL_ELIMINATION_OFFSET macro. */
738 nios2_initial_elimination_offset (int from
, int to
)
742 nios2_compute_frame_layout ();
744 /* Set OFFSET to the offset from the stack pointer. */
747 case FRAME_POINTER_REGNUM
:
748 offset
= cfun
->machine
->args_size
;
751 case ARG_POINTER_REGNUM
:
752 offset
= cfun
->machine
->total_size
;
753 offset
-= crtl
->args
.pretend_args_size
;
760 /* If we are asked for the frame pointer offset, then adjust OFFSET
761 by the offset from the frame pointer to the stack pointer. */
762 if (to
== HARD_FRAME_POINTER_REGNUM
)
763 offset
-= cfun
->machine
->save_regs_offset
;
768 /* Return nonzero if this function is known to have a null epilogue.
769 This allows the optimizer to omit jumps to jumps if no stack
772 nios2_can_use_return_insn (void)
774 if (!reload_completed
|| crtl
->profile
)
777 return nios2_compute_frame_layout () == 0;
781 /* Check and signal some warnings/errors on FPU insn options. */
783 nios2_custom_check_insns (void)
788 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
789 if (N2FPU_ENABLED_P (i
) && N2FPU_DOUBLE_P (i
))
791 for (j
= 0; j
< ARRAY_SIZE (nios2_fpu_insn
); j
++)
792 if (N2FPU_DOUBLE_REQUIRED_P (j
) && ! N2FPU_ENABLED_P (j
))
794 error ("switch %<-mcustom-%s%> is required for double "
795 "precision floating point", N2FPU_NAME (j
));
801 /* Warn if the user has certain exotic operations that won't get used
802 without -funsafe-math-optimizations. See expand_builtin () in
804 if (!flag_unsafe_math_optimizations
)
805 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
806 if (N2FPU_ENABLED_P (i
) && N2FPU_UNSAFE_P (i
))
807 warning (0, "switch %<-mcustom-%s%> has no effect unless "
808 "-funsafe-math-optimizations is specified", N2FPU_NAME (i
));
810 /* Warn if the user is trying to use -mcustom-fmins et. al, that won't
811 get used without -ffinite-math-only. See fold_builtin_fmin_fmax ()
813 if (!flag_finite_math_only
)
814 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
815 if (N2FPU_ENABLED_P (i
) && N2FPU_FINITE_P (i
))
816 warning (0, "switch %<-mcustom-%s%> has no effect unless "
817 "-ffinite-math-only is specified", N2FPU_NAME (i
));
819 if (errors
|| custom_code_conflict
)
820 fatal_error ("conflicting use of -mcustom switches, target attributes, "
821 "and/or __builtin_custom_ functions");
825 nios2_set_fpu_custom_code (enum n2fpu_code code
, int n
, bool override_p
)
827 if (override_p
|| N2FPU_N (code
) == -1)
829 nios2_register_custom_code (n
, CCS_FPU
, (int) code
);
832 /* Type to represent a standard FPU config. */
833 struct nios2_fpu_config
836 bool set_sp_constants
;
837 int code
[n2fpu_code_num
];
840 #define NIOS2_FPU_CONFIG_NUM 3
841 static struct nios2_fpu_config custom_fpu_config
[NIOS2_FPU_CONFIG_NUM
];
844 nios2_init_fpu_configs (void)
846 struct nios2_fpu_config
* cfg
;
848 #define NEXT_FPU_CONFIG \
850 cfg = &custom_fpu_config[i++]; \
851 memset (cfg, -1, sizeof (struct nios2_fpu_config));\
856 cfg
->set_sp_constants
= true;
857 cfg
->code
[n2fpu_fmuls
] = 252;
858 cfg
->code
[n2fpu_fadds
] = 253;
859 cfg
->code
[n2fpu_fsubs
] = 254;
863 cfg
->set_sp_constants
= true;
864 cfg
->code
[n2fpu_fmuls
] = 252;
865 cfg
->code
[n2fpu_fadds
] = 253;
866 cfg
->code
[n2fpu_fsubs
] = 254;
867 cfg
->code
[n2fpu_fdivs
] = 255;
871 cfg
->set_sp_constants
= true;
872 cfg
->code
[n2fpu_floatus
] = 243;
873 cfg
->code
[n2fpu_fixsi
] = 244;
874 cfg
->code
[n2fpu_floatis
] = 245;
875 cfg
->code
[n2fpu_fcmpgts
] = 246;
876 cfg
->code
[n2fpu_fcmples
] = 249;
877 cfg
->code
[n2fpu_fcmpeqs
] = 250;
878 cfg
->code
[n2fpu_fcmpnes
] = 251;
879 cfg
->code
[n2fpu_fmuls
] = 252;
880 cfg
->code
[n2fpu_fadds
] = 253;
881 cfg
->code
[n2fpu_fsubs
] = 254;
882 cfg
->code
[n2fpu_fdivs
] = 255;
884 #undef NEXT_FPU_CONFIG
885 gcc_assert (i
== NIOS2_FPU_CONFIG_NUM
);
888 static struct nios2_fpu_config
*
889 nios2_match_custom_fpu_cfg (const char *cfgname
, const char *endp
)
892 for (i
= 0; i
< NIOS2_FPU_CONFIG_NUM
; i
++)
894 bool match
= !(endp
!= NULL
895 ? strncmp (custom_fpu_config
[i
].name
, cfgname
,
897 : strcmp (custom_fpu_config
[i
].name
, cfgname
));
899 return &custom_fpu_config
[i
];
904 /* Use CFGNAME to lookup FPU config, ENDP if not NULL marks end of string.
905 OVERRIDE is true if loaded config codes should overwrite current state. */
907 nios2_handle_custom_fpu_cfg (const char *cfgname
, const char *endp
,
910 struct nios2_fpu_config
*cfg
= nios2_match_custom_fpu_cfg (cfgname
, endp
);
914 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
915 if (cfg
->code
[i
] >= 0)
916 nios2_set_fpu_custom_code ((enum n2fpu_code
) i
, cfg
->code
[i
],
918 if (cfg
->set_sp_constants
)
919 flag_single_precision_constant
= 1;
922 warning (0, "ignoring unrecognized switch %<-mcustom-fpu-cfg%> "
923 "value %<%s%>", cfg
);
925 /* Guard against errors in the standard configurations. */
926 nios2_custom_check_insns ();
929 /* Check individual FPU insn options, and register custom code. */
931 nios2_handle_custom_fpu_insn_option (int fpu_insn_index
)
933 int param
= N2FPU_N (fpu_insn_index
);
935 if (0 <= param
&& param
<= 255)
936 nios2_register_custom_code (param
, CCS_FPU
, fpu_insn_index
);
938 /* Valid values are 0-255, but also allow -1 so that the
939 -mno-custom-<opt> switches work. */
940 else if (param
!= -1)
941 error ("switch %<-mcustom-%s%> value %d must be between 0 and 255",
942 N2FPU_NAME (fpu_insn_index
), param
);
945 /* Allocate a chunk of memory for per-function machine-dependent data. */
946 static struct machine_function
*
947 nios2_init_machine_status (void)
949 return ggc_alloc_cleared_machine_function ();
952 /* Implement TARGET_OPTION_OVERRIDE. */
954 nios2_option_override (void)
958 #ifdef SUBTARGET_OVERRIDE_OPTIONS
959 SUBTARGET_OVERRIDE_OPTIONS
;
962 /* Check for unsupported options. */
963 if (flag_pic
&& !TARGET_LINUX_ABI
)
964 sorry ("position-independent code requires the Linux ABI");
966 /* Function to allocate machine-dependent function status. */
967 init_machine_status
= &nios2_init_machine_status
;
969 nios2_section_threshold
970 = (global_options_set
.x_g_switch_value
971 ? g_switch_value
: NIOS2_DEFAULT_GVALUE
);
973 /* Default to -mgpopt unless -fpic or -fPIC. */
974 if (TARGET_GPOPT
== -1 && flag_pic
)
977 /* If we don't have mul, we don't have mulx either! */
978 if (!TARGET_HAS_MUL
&& TARGET_HAS_MULX
)
979 target_flags
&= ~MASK_HAS_MULX
;
981 /* Initialize default FPU configurations. */
982 nios2_init_fpu_configs ();
984 /* Set up default handling for floating point custom instructions.
986 Putting things in this order means that the -mcustom-fpu-cfg=
987 switch will always be overridden by individual -mcustom-fadds=
988 switches, regardless of the order in which they were specified
991 This behavior of prioritization of individual -mcustom-<insn>=
992 options before the -mcustom-fpu-cfg= switch is maintained for
994 if (nios2_custom_fpu_cfg_string
&& *nios2_custom_fpu_cfg_string
)
995 nios2_handle_custom_fpu_cfg (nios2_custom_fpu_cfg_string
, NULL
, false);
997 /* Handle options for individual FPU insns. */
998 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
999 nios2_handle_custom_fpu_insn_option (i
);
1001 nios2_custom_check_insns ();
1003 /* Save the initial options in case the user does function specific
1005 target_option_default_node
= target_option_current_node
1006 = build_target_option_node (&global_options
);
1010 /* Return true if CST is a constant within range of movi/movui/movhi. */
1012 nios2_simple_const_p (const_rtx cst
)
1014 HOST_WIDE_INT val
= INTVAL (cst
);
1015 return SMALL_INT (val
) || SMALL_INT_UNSIGNED (val
) || UPPER16_INT (val
);
1018 /* Compute a (partial) cost for rtx X. Return true if the complete
1019 cost has been computed, and false if subexpressions should be
1020 scanned. In either case, *TOTAL contains the cost result. */
1022 nios2_rtx_costs (rtx x
, int code
, int outer_code ATTRIBUTE_UNUSED
,
1023 int opno ATTRIBUTE_UNUSED
,
1024 int *total
, bool speed ATTRIBUTE_UNUSED
)
1029 if (INTVAL (x
) == 0)
1031 *total
= COSTS_N_INSNS (0);
1034 else if (nios2_simple_const_p (x
))
1036 *total
= COSTS_N_INSNS (2);
1041 *total
= COSTS_N_INSNS (4);
1050 *total
= COSTS_N_INSNS (4);
1056 /* Recognize 'nor' insn pattern. */
1057 if (GET_CODE (XEXP (x
, 0)) == NOT
1058 && GET_CODE (XEXP (x
, 1)) == NOT
)
1060 *total
= COSTS_N_INSNS (1);
1068 *total
= COSTS_N_INSNS (1);
1073 *total
= COSTS_N_INSNS (3);
1078 *total
= COSTS_N_INSNS (1);
1087 /* Implement TARGET_PREFERRED_RELOAD_CLASS. */
1089 nios2_preferred_reload_class (rtx x ATTRIBUTE_UNUSED
, reg_class_t regclass
)
1091 return regclass
== NO_REGS
? GENERAL_REGS
: regclass
;
1094 /* Emit a call to __tls_get_addr. TI is the argument to this function.
1095 RET is an RTX for the return value location. The entire insn sequence
1097 static GTY(()) rtx nios2_tls_symbol
;
1100 nios2_call_tls_get_addr (rtx ti
)
1102 rtx arg
= gen_rtx_REG (Pmode
, FIRST_ARG_REGNO
);
1103 rtx ret
= gen_rtx_REG (Pmode
, FIRST_RETVAL_REGNO
);
1106 if (!nios2_tls_symbol
)
1107 nios2_tls_symbol
= init_one_libfunc ("__tls_get_addr");
1109 emit_move_insn (arg
, ti
);
1110 fn
= gen_rtx_MEM (QImode
, nios2_tls_symbol
);
1111 insn
= emit_call_insn (gen_call_value (ret
, fn
, const0_rtx
));
1112 RTL_CONST_CALL_P (insn
) = 1;
1113 use_reg (&CALL_INSN_FUNCTION_USAGE (insn
), ret
);
1114 use_reg (&CALL_INSN_FUNCTION_USAGE (insn
), arg
);
1120 nios2_unspec_address (rtx loc
, rtx base_reg
, int unspec
)
1123 gen_rtx_CONST (Pmode
, gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, loc
),
1125 return gen_rtx_PLUS (Pmode
, base_reg
, unspec_offset
);
1129 nios2_got_address (rtx loc
, int unspec
)
1131 crtl
->uses_pic_offset_table
= 1;
1132 return nios2_unspec_address (loc
, pic_offset_table_rtx
, unspec
);
1135 /* Generate the code to access LOC, a thread local SYMBOL_REF. The
1136 return value will be a valid address and move_operand (either a REG
1139 nios2_legitimize_tls_address (rtx loc
)
1142 enum tls_model model
= SYMBOL_REF_TLS_MODEL (loc
);
1146 case TLS_MODEL_GLOBAL_DYNAMIC
:
1147 tmp
= gen_reg_rtx (Pmode
);
1148 emit_move_insn (tmp
, nios2_got_address (loc
, UNSPEC_ADD_TLS_GD
));
1149 return nios2_call_tls_get_addr (tmp
);
1151 case TLS_MODEL_LOCAL_DYNAMIC
:
1152 tmp
= gen_reg_rtx (Pmode
);
1153 emit_move_insn (tmp
, nios2_got_address (loc
, UNSPEC_ADD_TLS_LDM
));
1154 return nios2_unspec_address (loc
, nios2_call_tls_get_addr (tmp
),
1155 UNSPEC_ADD_TLS_LDO
);
1157 case TLS_MODEL_INITIAL_EXEC
:
1158 tmp
= gen_reg_rtx (Pmode
);
1159 mem
= gen_const_mem (Pmode
, nios2_got_address (loc
, UNSPEC_LOAD_TLS_IE
));
1160 emit_move_insn (tmp
, mem
);
1161 tp
= gen_rtx_REG (Pmode
, TP_REGNO
);
1162 return gen_rtx_PLUS (Pmode
, tp
, tmp
);
1164 case TLS_MODEL_LOCAL_EXEC
:
1165 tp
= gen_rtx_REG (Pmode
, TP_REGNO
);
1166 return nios2_unspec_address (loc
, tp
, UNSPEC_ADD_TLS_LE
);
1175 If -O3 is used, we want to output a table lookup for
1176 divides between small numbers (both num and den >= 0
1177 and < 0x10). The overhead of this method in the worst
1178 case is 40 bytes in the text section (10 insns) and
1179 256 bytes in the data section. Additional divides do
1180 not incur additional penalties in the data section.
1182 Code speed is improved for small divides by about 5x
1183 when using this method in the worse case (~9 cycles
1184 vs ~45). And in the worst case divides not within the
1185 table are penalized by about 10% (~5 cycles vs ~45).
1186 However in the typical case the penalty is not as bad
1187 because doing the long divide in only 45 cycles is
1190 ??? would be nice to have some benchmarks other
1191 than Dhrystone to back this up.
1193 This bit of expansion is to create this instruction
1200 add $12, $11, divide_table
1206 # continue here with result in $2
1208 ??? Ideally I would like the libcall block to contain all
1209 of this code, but I don't know how to do that. What it
1210 means is that if the divide can be eliminated, it may not
1211 completely disappear.
1213 ??? The __divsi3_table label should ideally be moved out
1214 of this block and into a global. If it is placed into the
1215 sdata section we can save even more cycles by doing things
1218 nios2_emit_expensive_div (rtx
*operands
, enum machine_mode mode
)
1220 rtx or_result
, shift_left_result
;
1229 /* It may look a little generic, but only SImode is supported for now. */
1230 gcc_assert (mode
== SImode
);
1231 libfunc
= optab_libfunc (sdiv_optab
, SImode
);
1233 lab1
= gen_label_rtx ();
1234 lab3
= gen_label_rtx ();
1236 or_result
= expand_simple_binop (SImode
, IOR
,
1237 operands
[1], operands
[2],
1238 0, 0, OPTAB_LIB_WIDEN
);
1240 emit_cmp_and_jump_insns (or_result
, GEN_INT (15), GTU
, 0,
1241 GET_MODE (or_result
), 0, lab3
);
1242 JUMP_LABEL (get_last_insn ()) = lab3
;
1244 shift_left_result
= expand_simple_binop (SImode
, ASHIFT
,
1245 operands
[1], GEN_INT (4),
1246 0, 0, OPTAB_LIB_WIDEN
);
1248 lookup_value
= expand_simple_binop (SImode
, IOR
,
1249 shift_left_result
, operands
[2],
1250 0, 0, OPTAB_LIB_WIDEN
);
1251 table
= gen_rtx_PLUS (SImode
, lookup_value
,
1252 gen_rtx_SYMBOL_REF (SImode
, "__divsi3_table"));
1253 convert_move (operands
[0], gen_rtx_MEM (QImode
, table
), 1);
1255 tmp
= emit_jump_insn (gen_jump (lab1
));
1256 JUMP_LABEL (tmp
) = lab1
;
1260 LABEL_NUSES (lab3
) = 1;
1263 final_result
= emit_library_call_value (libfunc
, NULL_RTX
,
1264 LCT_CONST
, SImode
, 2,
1265 operands
[1], SImode
,
1266 operands
[2], SImode
);
1268 insns
= get_insns ();
1270 emit_libcall_block (insns
, operands
[0], final_result
,
1271 gen_rtx_DIV (SImode
, operands
[1], operands
[2]));
1274 LABEL_NUSES (lab1
) = 1;
1278 /* Branches and compares. */
1280 /* Return in *ALT_CODE and *ALT_OP, an alternate equivalent constant
1281 comparison, e.g. >= 1 into > 0. */
1283 nios2_alternate_compare_const (enum rtx_code code
, rtx op
,
1284 enum rtx_code
*alt_code
, rtx
*alt_op
,
1285 enum machine_mode mode
)
1287 HOST_WIDE_INT opval
= INTVAL (op
);
1288 enum rtx_code scode
= signed_condition (code
);
1289 bool dec_p
= (scode
== LT
|| scode
== GE
);
1291 if (code
== EQ
|| code
== NE
)
1299 ? gen_int_mode (opval
- 1, mode
)
1300 : gen_int_mode (opval
+ 1, mode
));
1302 /* The required conversion between [>,>=] and [<,<=] is captured
1303 by a reverse + swap of condition codes. */
1304 *alt_code
= reverse_condition (swap_condition (code
));
1307 /* Test if the incremented/decremented value crosses the over/underflow
1308 boundary. Supposedly, such boundary cases should already be transformed
1309 into always-true/false or EQ conditions, so use an assertion here. */
1310 unsigned HOST_WIDE_INT alt_opval
= INTVAL (*alt_op
);
1312 alt_opval
^= (1 << (GET_MODE_BITSIZE (mode
) - 1));
1313 alt_opval
&= GET_MODE_MASK (mode
);
1314 gcc_assert (dec_p
? alt_opval
!= GET_MODE_MASK (mode
) : alt_opval
!= 0);
1318 /* Return true if the constant comparison is supported by nios2. */
1320 nios2_valid_compare_const_p (enum rtx_code code
, rtx op
)
1324 case EQ
: case NE
: case GE
: case LT
:
1325 return SMALL_INT (INTVAL (op
));
1327 return SMALL_INT_UNSIGNED (INTVAL (op
));
1333 /* Checks if the FPU comparison in *CMP, *OP1, and *OP2 can be supported in
1334 the current configuration. Perform modifications if MODIFY_P is true.
1335 Returns true if FPU compare can be done. */
1338 nios2_validate_fpu_compare (enum machine_mode mode
, rtx
*cmp
, rtx
*op1
, rtx
*op2
,
1342 enum rtx_code code
= GET_CODE (*cmp
);
1344 if (!nios2_fpu_compare_enabled (code
, mode
))
1346 code
= swap_condition (code
);
1347 if (nios2_fpu_compare_enabled (code
, mode
))
1361 *op1
= force_reg (mode
, *op1
);
1362 *op2
= force_reg (mode
, *op2
);
1363 *cmp
= gen_rtx_fmt_ee (code
, mode
, *op1
, *op2
);
1368 /* Checks and modifies the comparison in *CMP, *OP1, and *OP2 into valid
1369 nios2 supported form. Returns true if success. */
1371 nios2_validate_compare (enum machine_mode mode
, rtx
*cmp
, rtx
*op1
, rtx
*op2
)
1373 enum rtx_code code
= GET_CODE (*cmp
);
1374 enum rtx_code alt_code
;
1377 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
)
1378 return nios2_validate_fpu_compare (mode
, cmp
, op1
, op2
, true);
1380 if (!reg_or_0_operand (*op2
, mode
))
1382 /* Create alternate constant compare. */
1383 nios2_alternate_compare_const (code
, *op2
, &alt_code
, &alt_op2
, mode
);
1385 /* If alterate op2 is zero(0), we can use it directly, possibly
1386 swapping the compare code. */
1387 if (alt_op2
== const0_rtx
)
1391 goto check_rebuild_cmp
;
1394 /* Check if either constant compare can be used. */
1395 if (nios2_valid_compare_const_p (code
, *op2
))
1397 else if (nios2_valid_compare_const_p (alt_code
, alt_op2
))
1404 /* We have to force op2 into a register now. Try to pick one
1405 with a lower cost. */
1406 if (! nios2_simple_const_p (*op2
)
1407 && nios2_simple_const_p (alt_op2
))
1412 *op2
= force_reg (SImode
, *op2
);
1415 if (code
== GT
|| code
== GTU
|| code
== LE
|| code
== LEU
)
1417 rtx t
= *op1
; *op1
= *op2
; *op2
= t
;
1418 code
= swap_condition (code
);
1421 *cmp
= gen_rtx_fmt_ee (code
, mode
, *op1
, *op2
);
1426 /* Addressing Modes. */
1428 /* Implement TARGET_LEGITIMATE_CONSTANT_P. */
1430 nios2_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x
)
1433 split_const (x
, &base
, &offset
);
1434 return GET_CODE (base
) != SYMBOL_REF
|| !SYMBOL_REF_TLS_MODEL (base
);
1437 /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
1439 nios2_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x
)
1441 return nios2_legitimate_constant_p (mode
, x
) == false;
1444 /* Return true if register REGNO is a valid base register.
1445 STRICT_P is true if REG_OK_STRICT is in effect. */
1448 nios2_regno_ok_for_base_p (int regno
, bool strict_p
)
1450 if (!HARD_REGISTER_NUM_P (regno
))
1458 regno
= reg_renumber
[regno
];
1461 /* The fake registers will be eliminated to either the stack or
1462 hard frame pointer, both of which are usually valid base registers.
1463 Reload deals with the cases where the eliminated form isn't valid. */
1464 return (GP_REG_P (regno
)
1465 || regno
== FRAME_POINTER_REGNUM
1466 || regno
== ARG_POINTER_REGNUM
);
1469 /* Return true if the address expression formed by BASE + OFFSET is
1472 nios2_valid_addr_expr_p (rtx base
, rtx offset
, bool strict_p
)
1474 if (!strict_p
&& GET_CODE (base
) == SUBREG
)
1475 base
= SUBREG_REG (base
);
1476 return (REG_P (base
)
1477 && nios2_regno_ok_for_base_p (REGNO (base
), strict_p
)
1478 && (offset
== NULL_RTX
1479 || const_arith_operand (offset
, Pmode
)
1480 || nios2_unspec_reloc_p (offset
)));
1483 /* Implement TARGET_LEGITIMATE_ADDRESS_P. */
1485 nios2_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
1486 rtx operand
, bool strict_p
)
1488 switch (GET_CODE (operand
))
1492 if (SYMBOL_REF_TLS_MODEL (operand
))
1495 if (nios2_symbol_ref_in_small_data_p (operand
))
1498 /* Else, fall through. */
1505 /* Register indirect. */
1507 return nios2_regno_ok_for_base_p (REGNO (operand
), strict_p
);
1509 /* Register indirect with displacement. */
1512 rtx op0
= XEXP (operand
, 0);
1513 rtx op1
= XEXP (operand
, 1);
1515 return (nios2_valid_addr_expr_p (op0
, op1
, strict_p
)
1516 || nios2_valid_addr_expr_p (op1
, op0
, strict_p
));
1525 /* Return true if SECTION is a small section name. */
1527 nios2_small_section_name_p (const char *section
)
1529 return (strcmp (section
, ".sbss") == 0
1530 || strncmp (section
, ".sbss.", 6) == 0
1531 || strcmp (section
, ".sdata") == 0
1532 || strncmp (section
, ".sdata.", 7) == 0);
1535 /* Return true if EXP should be placed in the small data section. */
1537 nios2_in_small_data_p (const_tree exp
)
1539 /* We want to merge strings, so we never consider them small data. */
1540 if (TREE_CODE (exp
) == STRING_CST
)
1543 if (TREE_CODE (exp
) == VAR_DECL
)
1545 if (DECL_SECTION_NAME (exp
))
1547 const char *section
= TREE_STRING_POINTER (DECL_SECTION_NAME (exp
));
1548 if (nios2_section_threshold
> 0
1549 && nios2_small_section_name_p (section
))
1554 HOST_WIDE_INT size
= int_size_in_bytes (TREE_TYPE (exp
));
1556 /* If this is an incomplete type with size 0, then we can't put it
1557 in sdata because it might be too big when completed. */
1559 && (unsigned HOST_WIDE_INT
) size
<= nios2_section_threshold
)
1567 /* Return true if symbol is in small data section. */
1570 nios2_symbol_ref_in_small_data_p (rtx sym
)
1572 gcc_assert (GET_CODE (sym
) == SYMBOL_REF
);
1575 /* GP-relative access cannot be used for externally defined symbols,
1576 because the compilation unit that defines the symbol may place it
1577 in a section that cannot be reached from GP. */
1578 && !SYMBOL_REF_EXTERNAL_P (sym
)
1579 /* True if a symbol is both small and not weak. */
1580 && SYMBOL_REF_SMALL_P (sym
)
1581 && !(SYMBOL_REF_DECL (sym
) && DECL_WEAK (SYMBOL_REF_DECL (sym
)))
1582 /* TLS variables are not accessed through the GP. */
1583 && SYMBOL_REF_TLS_MODEL (sym
) == 0);
1587 /* Implement TARGET_SECTION_TYPE_FLAGS. */
1590 nios2_section_type_flags (tree decl
, const char *name
, int reloc
)
1594 flags
= default_section_type_flags (decl
, name
, reloc
);
1596 if (nios2_small_section_name_p (name
))
1597 flags
|= SECTION_SMALL
;
1603 /* Position independent code related. */
1605 /* Emit code to load the PIC register. */
1607 nios2_load_pic_register (void)
1609 rtx tmp
= gen_rtx_REG (Pmode
, TEMP_REG_NUM
);
1611 emit_insn (gen_load_got_register (pic_offset_table_rtx
, tmp
));
1612 emit_insn (gen_add3_insn (pic_offset_table_rtx
, pic_offset_table_rtx
, tmp
));
1615 /* Generate a PIC address as a MEM rtx. */
1617 nios2_load_pic_address (rtx sym
, int unspec
)
1619 rtx gotaddr
= nios2_got_address (sym
, unspec
);
1620 return gen_const_mem (Pmode
, gotaddr
);
1623 /* Nonzero if the constant value X is a legitimate general operand
1624 when generating PIC code. It is given that flag_pic is on and
1625 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
1627 nios2_legitimate_pic_operand_p (rtx x
)
1629 return ! (GET_CODE (x
) == SYMBOL_REF
1630 || GET_CODE (x
) == LABEL_REF
|| GET_CODE (x
) == CONST
);
1633 /* Return TRUE if X is a thread-local symbol. */
1635 nios2_tls_symbol_p (rtx x
)
1637 return (targetm
.have_tls
&& GET_CODE (x
) == SYMBOL_REF
1638 && SYMBOL_REF_TLS_MODEL (x
) != 0);
1641 /* Legitimize addresses that are CONSTANT_P expressions. */
1643 nios2_legitimize_constant_address (rtx addr
)
1646 split_const (addr
, &base
, &offset
);
1648 if (nios2_tls_symbol_p (base
))
1649 base
= nios2_legitimize_tls_address (base
);
1651 base
= nios2_load_pic_address (base
, UNSPEC_PIC_SYM
);
1655 if (offset
!= const0_rtx
)
1657 gcc_assert (can_create_pseudo_p ());
1658 return gen_rtx_PLUS (Pmode
, force_reg (Pmode
, base
),
1659 (CONST_INT_P (offset
)
1660 ? (SMALL_INT (INTVAL (offset
))
1661 ? offset
: force_reg (Pmode
, offset
))
1667 /* Implement TARGET_LEGITIMIZE_ADDRESS. */
1669 nios2_legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
1670 enum machine_mode mode ATTRIBUTE_UNUSED
)
1673 return nios2_legitimize_constant_address (x
);
1675 /* For the TLS LE (Local Exec) model, the compiler may try to
1676 combine constant offsets with unspec relocs, creating address RTXs
1678 (plus:SI (reg:SI 23 r23)
1681 (unspec:SI [(symbol_ref:SI ("var"))] UNSPEC_ADD_TLS_LE)
1682 (const_int 48 [0x30]))))
1684 This usually happens when 'var' is a thread-local struct variable,
1685 and access of a field in var causes the addend.
1687 We typically want this combining, so transform the above into this
1688 form, which is allowed:
1689 (plus:SI (reg:SI 23 r23)
1693 (plus:SI (symbol_ref:SI ("var"))
1694 (const_int 48 [0x30])))] UNSPEC_ADD_TLS_LE)))
1696 Which will be output as '%tls_le(var+48)(r23)' in assembly. */
1697 if (GET_CODE (x
) == PLUS
1698 && GET_CODE (XEXP (x
, 0)) == REG
1699 && GET_CODE (XEXP (x
, 1)) == CONST
)
1701 rtx unspec
, offset
, reg
= XEXP (x
, 0);
1702 split_const (XEXP (x
, 1), &unspec
, &offset
);
1703 if (GET_CODE (unspec
) == UNSPEC
1704 && nios2_unspec_reloc_name (XINT (unspec
, 1)) != NULL
1705 && offset
!= const0_rtx
)
1707 unspec
= copy_rtx (unspec
);
1708 XVECEXP (unspec
, 0, 0)
1709 = plus_constant (Pmode
, XVECEXP (unspec
, 0, 0), INTVAL (offset
));
1710 x
= gen_rtx_PLUS (Pmode
, reg
, gen_rtx_CONST (Pmode
, unspec
));
1717 /* Main expander function for RTL moves. */
1719 nios2_emit_move_sequence (rtx
*operands
, enum machine_mode mode
)
1721 rtx to
= operands
[0];
1722 rtx from
= operands
[1];
1724 if (!register_operand (to
, mode
) && !reg_or_0_operand (from
, mode
))
1726 gcc_assert (can_create_pseudo_p ());
1727 from
= copy_to_mode_reg (mode
, from
);
1730 if (GET_CODE (from
) == SYMBOL_REF
|| GET_CODE (from
) == LABEL_REF
1731 || GET_CODE (from
) == CONST
)
1732 from
= nios2_legitimize_constant_address (from
);
1739 /* The function with address *ADDR is being called. If the address
1740 needs to be loaded from the GOT, emit the instruction to do so and
1741 update *ADDR to point to the rtx for the loaded value. */
1743 nios2_adjust_call_address (rtx
*call_op
)
1746 gcc_assert (MEM_P (*call_op
));
1747 addr
= XEXP (*call_op
, 0);
1748 if (flag_pic
&& CONSTANT_P (addr
))
1750 rtx reg
= gen_reg_rtx (Pmode
);
1751 emit_move_insn (reg
, nios2_load_pic_address (addr
, UNSPEC_PIC_CALL_SYM
));
1752 XEXP (*call_op
, 0) = reg
;
1757 /* Output assembly language related definitions. */
1759 /* Print the operand OP to file stream FILE modified by LETTER.
1760 LETTER can be one of:
1762 i: print "i" if OP is an immediate, except 0
1763 o: print "io" if OP is volatile
1764 z: for const0_rtx print $0 instead of 0
1767 U: for upper half of 32 bit value
1768 D: for the upper 32-bits of a 64-bit double value
1769 R: prints reverse condition.
1772 nios2_print_operand (FILE *file
, rtx op
, int letter
)
1778 if (CONSTANT_P (op
) && op
!= const0_rtx
)
1779 fprintf (file
, "i");
1783 if (GET_CODE (op
) == MEM
1784 && ((MEM_VOLATILE_P (op
) && TARGET_BYPASS_CACHE_VOLATILE
)
1785 || TARGET_BYPASS_CACHE
))
1786 fprintf (file
, "io");
1793 if (comparison_operator (op
, VOIDmode
))
1795 enum rtx_code cond
= GET_CODE (op
);
1798 fprintf (file
, "%s", GET_RTX_NAME (cond
));
1803 fprintf (file
, "%s", GET_RTX_NAME (reverse_condition (cond
)));
1808 switch (GET_CODE (op
))
1811 if (letter
== 0 || letter
== 'z')
1813 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1816 else if (letter
== 'D')
1818 fprintf (file
, "%s", reg_names
[REGNO (op
)+1]);
1824 if (INTVAL (op
) == 0 && letter
== 'z')
1826 fprintf (file
, "zero");
1832 HOST_WIDE_INT val
= INTVAL (op
);
1833 val
= (val
>> 16) & 0xFFFF;
1834 output_addr_const (file
, gen_int_mode (val
, SImode
));
1837 /* Else, fall through. */
1843 if (letter
== 0 || letter
== 'z')
1845 output_addr_const (file
, op
);
1848 else if (letter
== 'H')
1850 fprintf (file
, "%%hiadj(");
1851 output_addr_const (file
, op
);
1852 fprintf (file
, ")");
1855 else if (letter
== 'L')
1857 fprintf (file
, "%%lo(");
1858 output_addr_const (file
, op
);
1859 fprintf (file
, ")");
1868 output_address (op
);
1876 output_addr_const (file
, op
);
1885 output_operand_lossage ("Unsupported operand for code '%c'", letter
);
1889 /* Return true if this is a GP-relative accessible reference. */
1891 gprel_constant_p (rtx op
)
1893 if (GET_CODE (op
) == SYMBOL_REF
1894 && nios2_symbol_ref_in_small_data_p (op
))
1896 else if (GET_CODE (op
) == CONST
1897 && GET_CODE (XEXP (op
, 0)) == PLUS
)
1898 return gprel_constant_p (XEXP (XEXP (op
, 0), 0));
1903 /* Return the name string for a supported unspec reloc offset. */
1905 nios2_unspec_reloc_name (int unspec
)
1909 case UNSPEC_PIC_SYM
:
1911 case UNSPEC_PIC_CALL_SYM
:
1913 case UNSPEC_LOAD_TLS_IE
:
1915 case UNSPEC_ADD_TLS_LE
:
1917 case UNSPEC_ADD_TLS_GD
:
1919 case UNSPEC_ADD_TLS_LDM
:
1921 case UNSPEC_ADD_TLS_LDO
:
1928 /* Return true for conforming unspec relocations. Also used in
1929 constraints.md and predicates.md. */
1931 nios2_unspec_reloc_p (rtx op
)
1933 return (GET_CODE (op
) == CONST
1934 && GET_CODE (XEXP (op
, 0)) == UNSPEC
1935 && nios2_unspec_reloc_name (XINT (XEXP (op
, 0), 1)) != NULL
);
1938 /* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */
1940 nios2_output_addr_const_extra (FILE *file
, rtx op
)
1943 gcc_assert (GET_CODE (op
) == UNSPEC
);
1945 /* Support for printing out const unspec relocations. */
1946 name
= nios2_unspec_reloc_name (XINT (op
, 1));
1949 fprintf (file
, "%%%s(", name
);
1950 output_addr_const (file
, XVECEXP (op
, 0, 0));
1951 fprintf (file
, ")");
1957 /* Implement TARGET_PRINT_OPERAND_ADDRESS. */
1959 nios2_print_operand_address (FILE *file
, rtx op
)
1961 switch (GET_CODE (op
))
1968 if (gprel_constant_p (op
))
1970 fprintf (file
, "%%gprel(");
1971 output_addr_const (file
, op
);
1972 fprintf (file
, ")(%s)", reg_names
[GP_REGNO
]);
1980 rtx op0
= XEXP (op
, 0);
1981 rtx op1
= XEXP (op
, 1);
1983 if (REG_P (op0
) && CONSTANT_P (op1
))
1985 output_addr_const (file
, op1
);
1986 fprintf (file
, "(%s)", reg_names
[REGNO (op0
)]);
1989 else if (REG_P (op1
) && CONSTANT_P (op0
))
1991 output_addr_const (file
, op0
);
1992 fprintf (file
, "(%s)", reg_names
[REGNO (op1
)]);
1999 fprintf (file
, "0(%s)", reg_names
[REGNO (op
)]);
2004 rtx base
= XEXP (op
, 0);
2005 nios2_print_operand_address (file
, base
);
2012 fprintf (stderr
, "Missing way to print address\n");
2017 /* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL. */
2019 nios2_output_dwarf_dtprel (FILE *file
, int size
, rtx x
)
2021 gcc_assert (size
== 4);
2022 fprintf (file
, "\t.4byte\t%%tls_ldo(");
2023 output_addr_const (file
, x
);
2024 fprintf (file
, ")");
2027 /* Implement TARGET_ASM_FUNCTION_PROLOGUE. */
2029 nios2_asm_function_prologue (FILE *file
, HOST_WIDE_INT size ATTRIBUTE_UNUSED
)
2031 if (flag_verbose_asm
|| flag_debug_asm
)
2033 nios2_compute_frame_layout ();
2034 nios2_dump_frame_layout (file
);
2038 /* Emit assembly of custom FPU instructions. */
2040 nios2_fpu_insn_asm (enum n2fpu_code code
)
2042 static char buf
[256];
2043 const char *op1
, *op2
, *op3
;
2044 int ln
= 256, n
= 0;
2046 int N
= N2FPU_N (code
);
2047 int num_operands
= N2FPU (code
).num_operands
;
2048 const char *insn_name
= N2FPU_NAME (code
);
2049 tree ftype
= nios2_ftype (N2FPU_FTCODE (code
));
2050 enum machine_mode dst_mode
= TYPE_MODE (TREE_TYPE (ftype
));
2051 enum machine_mode src_mode
= TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (ftype
)));
2053 /* Prepare X register for DF input operands. */
2054 if (GET_MODE_SIZE (src_mode
) == 8 && num_operands
== 3)
2055 n
= snprintf (buf
, ln
, "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t",
2056 N2FPU_N (n2fpu_fwrx
));
2058 if (src_mode
== SFmode
)
2060 if (dst_mode
== VOIDmode
)
2062 /* The fwry case. */
2069 op1
= (dst_mode
== DFmode
? "%D0" : "%0");
2071 op3
= (num_operands
== 2 ? "zero" : "%2");
2074 else if (src_mode
== DFmode
)
2076 if (dst_mode
== VOIDmode
)
2078 /* The fwrx case. */
2086 op1
= (dst_mode
== DFmode
? "%D0" : "%0");
2087 op2
= (num_operands
== 2 ? "%1" : "%2");
2088 op3
= (num_operands
== 2 ? "%D1" : "%D2");
2091 else if (src_mode
== VOIDmode
)
2093 /* frdxlo, frdxhi, frdy cases. */
2094 gcc_assert (dst_mode
== SFmode
);
2098 else if (src_mode
== SImode
)
2100 /* Conversion operators. */
2101 gcc_assert (num_operands
== 2);
2102 op1
= (dst_mode
== DFmode
? "%D0" : "%0");
2109 /* Main instruction string. */
2110 n
+= snprintf (buf
+ n
, ln
- n
, "custom\t%d, %s, %s, %s # %s %%0%s%s",
2111 N
, op1
, op2
, op3
, insn_name
,
2112 (num_operands
>= 2 ? ", %1" : ""),
2113 (num_operands
== 3 ? ", %2" : ""));
2115 /* Extraction of Y register for DF results. */
2116 if (dst_mode
== DFmode
)
2117 snprintf (buf
+ n
, ln
- n
, "\n\tcustom\t%d, %%0, zero, zero # frdy %%0",
2118 N2FPU_N (n2fpu_frdy
));
2124 /* Function argument related. */
2126 /* Define where to put the arguments to a function. Value is zero to
2127 push the argument on the stack, or a hard register in which to
2130 MODE is the argument's machine mode.
2131 TYPE is the data type of the argument (as a tree).
2132 This is null for libcalls where that information may
2134 CUM is a variable of type CUMULATIVE_ARGS which gives info about
2135 the preceding args and about the function being called.
2136 NAMED is nonzero if this argument is a named parameter
2137 (otherwise it is an extra parameter matching an ellipsis). */
2140 nios2_function_arg (cumulative_args_t cum_v
, enum machine_mode mode
,
2141 const_tree type ATTRIBUTE_UNUSED
,
2142 bool named ATTRIBUTE_UNUSED
)
2144 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2145 rtx return_rtx
= NULL_RTX
;
2147 if (cum
->regs_used
< NUM_ARG_REGS
)
2148 return_rtx
= gen_rtx_REG (mode
, FIRST_ARG_REGNO
+ cum
->regs_used
);
2153 /* Return number of bytes, at the beginning of the argument, that must be
2154 put in registers. 0 is the argument is entirely in registers or entirely
2158 nios2_arg_partial_bytes (cumulative_args_t cum_v
,
2159 enum machine_mode mode
, tree type ATTRIBUTE_UNUSED
,
2160 bool named ATTRIBUTE_UNUSED
)
2162 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2163 HOST_WIDE_INT param_size
;
2165 if (mode
== BLKmode
)
2167 param_size
= int_size_in_bytes (type
);
2168 gcc_assert (param_size
>= 0);
2171 param_size
= GET_MODE_SIZE (mode
);
2173 /* Convert to words (round up). */
2174 param_size
= (UNITS_PER_WORD
- 1 + param_size
) / UNITS_PER_WORD
;
2176 if (cum
->regs_used
< NUM_ARG_REGS
2177 && cum
->regs_used
+ param_size
> NUM_ARG_REGS
)
2178 return (NUM_ARG_REGS
- cum
->regs_used
) * UNITS_PER_WORD
;
2183 /* Update the data in CUM to advance over an argument of mode MODE
2184 and data type TYPE; TYPE is null for libcalls where that information
2185 may not be available. */
2188 nios2_function_arg_advance (cumulative_args_t cum_v
, enum machine_mode mode
,
2189 const_tree type ATTRIBUTE_UNUSED
,
2190 bool named ATTRIBUTE_UNUSED
)
2192 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2193 HOST_WIDE_INT param_size
;
2195 if (mode
== BLKmode
)
2197 param_size
= int_size_in_bytes (type
);
2198 gcc_assert (param_size
>= 0);
2201 param_size
= GET_MODE_SIZE (mode
);
2203 /* Convert to words (round up). */
2204 param_size
= (UNITS_PER_WORD
- 1 + param_size
) / UNITS_PER_WORD
;
2206 if (cum
->regs_used
+ param_size
> NUM_ARG_REGS
)
2207 cum
->regs_used
= NUM_ARG_REGS
;
2209 cum
->regs_used
+= param_size
;
2213 nios2_function_arg_padding (enum machine_mode mode
, const_tree type
)
2215 /* On little-endian targets, the first byte of every stack argument
2216 is passed in the first byte of the stack slot. */
2217 if (!BYTES_BIG_ENDIAN
)
2220 /* Otherwise, integral types are padded downward: the last byte of a
2221 stack argument is passed in the last byte of the stack slot. */
2223 ? INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
)
2224 : GET_MODE_CLASS (mode
) == MODE_INT
)
2227 /* Arguments smaller than a stack slot are padded downward. */
2228 if (mode
!= BLKmode
)
2229 return (GET_MODE_BITSIZE (mode
) >= PARM_BOUNDARY
) ? upward
: downward
;
2231 return ((int_size_in_bytes (type
) >= (PARM_BOUNDARY
/ BITS_PER_UNIT
))
2232 ? upward
: downward
);
2236 nios2_block_reg_padding (enum machine_mode mode
, tree type
,
2237 int first ATTRIBUTE_UNUSED
)
2239 return nios2_function_arg_padding (mode
, type
);
2242 /* Emit RTL insns to initialize the variable parts of a trampoline.
2243 FNADDR is an RTX for the address of the function's pure code.
2244 CXT is an RTX for the static chain value for the function.
2245 On Nios II, we handle this by a library call. */
2247 nios2_trampoline_init (rtx m_tramp
, tree fndecl
, rtx cxt
)
2249 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2250 rtx ctx_reg
= force_reg (Pmode
, cxt
);
2251 rtx addr
= force_reg (Pmode
, XEXP (m_tramp
, 0));
2253 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "__trampoline_setup"),
2254 LCT_NORMAL
, VOIDmode
, 3, addr
, Pmode
, fnaddr
, Pmode
,
2258 /* Implement TARGET_FUNCTION_VALUE. */
2260 nios2_function_value (const_tree ret_type
, const_tree fn ATTRIBUTE_UNUSED
,
2261 bool outgoing ATTRIBUTE_UNUSED
)
2263 return gen_rtx_REG (TYPE_MODE (ret_type
), FIRST_RETVAL_REGNO
);
2266 /* Implement TARGET_LIBCALL_VALUE. */
2268 nios2_libcall_value (enum machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
2270 return gen_rtx_REG (mode
, FIRST_RETVAL_REGNO
);
2273 /* Implement TARGET_FUNCTION_VALUE_REGNO_P. */
2275 nios2_function_value_regno_p (const unsigned int regno
)
2277 return regno
== FIRST_RETVAL_REGNO
;
2280 /* Implement TARGET_RETURN_IN_MEMORY. */
2282 nios2_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
2284 return (int_size_in_bytes (type
) > (2 * UNITS_PER_WORD
)
2285 || int_size_in_bytes (type
) == -1);
2288 /* TODO: It may be possible to eliminate the copyback and implement
2291 nios2_setup_incoming_varargs (cumulative_args_t cum_v
,
2292 enum machine_mode mode
, tree type
,
2293 int *pretend_size
, int second_time
)
2295 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2296 CUMULATIVE_ARGS local_cum
;
2297 cumulative_args_t local_cum_v
= pack_cumulative_args (&local_cum
);
2302 nios2_function_arg_advance (local_cum_v
, mode
, type
, 1);
2304 regs_to_push
= NUM_ARG_REGS
- local_cum
.regs_used
;
2306 if (!second_time
&& regs_to_push
> 0)
2308 rtx ptr
= virtual_incoming_args_rtx
;
2309 rtx mem
= gen_rtx_MEM (BLKmode
, ptr
);
2310 emit_insn (gen_blockage ());
2311 move_block_from_reg (local_cum
.regs_used
+ FIRST_ARG_REGNO
, mem
,
2313 emit_insn (gen_blockage ());
2316 pret_size
= regs_to_push
* UNITS_PER_WORD
;
2318 *pretend_size
= pret_size
;
2323 /* Init FPU builtins. */
2325 nios2_init_fpu_builtins (int start_code
)
2328 char builtin_name
[64] = "__builtin_custom_";
2329 unsigned int i
, n
= strlen ("__builtin_custom_");
2331 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
2333 snprintf (builtin_name
+ n
, sizeof (builtin_name
) - n
,
2334 "%s", N2FPU_NAME (i
));
2336 add_builtin_function (builtin_name
, nios2_ftype (N2FPU_FTCODE (i
)),
2337 start_code
+ i
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2338 nios2_register_builtin_fndecl (start_code
+ i
, fndecl
);
2342 /* Helper function for expanding FPU builtins. */
2344 nios2_expand_fpu_builtin (tree exp
, unsigned int code
, rtx target
)
2346 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
2347 enum insn_code icode
= N2FPU_ICODE (code
);
2348 int nargs
, argno
, opno
= 0;
2349 int num_operands
= N2FPU (code
).num_operands
;
2350 enum machine_mode dst_mode
= TYPE_MODE (TREE_TYPE (exp
));
2351 bool has_target_p
= (dst_mode
!= VOIDmode
);
2353 if (N2FPU_N (code
) < 0)
2354 fatal_error ("Cannot call %<__builtin_custom_%s%> without specifying switch"
2355 " %<-mcustom-%s%>", N2FPU_NAME (code
), N2FPU_NAME (code
));
2357 create_output_operand (&ops
[opno
++], target
, dst_mode
);
2359 /* Subtract away the count of the VOID return, mainly for fwrx/fwry. */
2361 nargs
= call_expr_nargs (exp
);
2362 for (argno
= 0; argno
< nargs
; argno
++)
2364 tree arg
= CALL_EXPR_ARG (exp
, argno
);
2365 create_input_operand (&ops
[opno
++], expand_normal (arg
),
2366 TYPE_MODE (TREE_TYPE (arg
)));
2368 if (!maybe_expand_insn (icode
, num_operands
, ops
))
2370 error ("invalid argument to built-in function");
2371 return has_target_p
? gen_reg_rtx (ops
[0].mode
) : const0_rtx
;
2373 return has_target_p
? ops
[0].value
: const0_rtx
;
2376 /* Nios II has custom instruction built-in functions of the forms:
2379 __builtin_custom_nXX
2381 __builtin_custom_XnX
2382 __builtin_custom_XnXX
2384 where each X could be either 'i' (int), 'f' (float), or 'p' (void*).
2385 Therefore with 0-1 return values, and 0-2 arguments, we have a
2386 total of (3 + 1) * (1 + 3 + 9) == 52 custom builtin functions.
2388 #define NUM_CUSTOM_BUILTINS ((3 + 1) * (1 + 3 + 9))
2389 static char custom_builtin_name
[NUM_CUSTOM_BUILTINS
][5];
2392 nios2_init_custom_builtins (int start_code
)
2394 tree builtin_ftype
, ret_type
, fndecl
;
2395 char builtin_name
[32] = "__builtin_custom_";
2396 int n
= strlen ("__builtin_custom_");
2397 int builtin_code
= 0;
2398 int lhs
, rhs1
, rhs2
;
2400 struct { tree type
; const char *c
; } op
[4];
2401 /* z */ op
[0].c
= ""; op
[0].type
= NULL_TREE
;
2402 /* f */ op
[1].c
= "f"; op
[1].type
= float_type_node
;
2403 /* i */ op
[2].c
= "i"; op
[2].type
= integer_type_node
;
2404 /* p */ op
[3].c
= "p"; op
[3].type
= ptr_type_node
;
2406 /* We enumerate through the possible operand types to create all the
2407 __builtin_custom_XnXX function tree types. Note that these may slightly
2408 overlap with the function types created for other fixed builtins. */
2410 for (lhs
= 0; lhs
< 4; lhs
++)
2411 for (rhs1
= 0; rhs1
< 4; rhs1
++)
2412 for (rhs2
= 0; rhs2
< 4; rhs2
++)
2414 if (rhs1
== 0 && rhs2
!= 0)
2416 ret_type
= (op
[lhs
].type
? op
[lhs
].type
: void_type_node
);
2418 = build_function_type_list (ret_type
, integer_type_node
,
2419 op
[rhs1
].type
, op
[rhs2
].type
,
2421 snprintf (builtin_name
+ n
, 32 - n
, "%sn%s%s",
2422 op
[lhs
].c
, op
[rhs1
].c
, op
[rhs2
].c
);
2423 /* Save copy of parameter string into custom_builtin_name[]. */
2424 strncpy (custom_builtin_name
[builtin_code
], builtin_name
+ n
, 5);
2426 add_builtin_function (builtin_name
, builtin_ftype
,
2427 start_code
+ builtin_code
,
2428 BUILT_IN_MD
, NULL
, NULL_TREE
);
2429 nios2_register_builtin_fndecl (start_code
+ builtin_code
, fndecl
);
2434 /* Helper function for expanding custom builtins. */
2436 nios2_expand_custom_builtin (tree exp
, unsigned int index
, rtx target
)
2438 bool has_target_p
= (TREE_TYPE (exp
) != void_type_node
);
2439 enum machine_mode tmode
= VOIDmode
;
2441 rtx value
, insn
, unspec_args
[3];
2447 tmode
= TYPE_MODE (TREE_TYPE (exp
));
2448 if (!target
|| GET_MODE (target
) != tmode
2450 target
= gen_reg_rtx (tmode
);
2453 nargs
= call_expr_nargs (exp
);
2454 for (argno
= 0; argno
< nargs
; argno
++)
2456 arg
= CALL_EXPR_ARG (exp
, argno
);
2457 value
= expand_normal (arg
);
2458 unspec_args
[argno
] = value
;
2461 if (!custom_insn_opcode (value
, VOIDmode
))
2462 error ("custom instruction opcode must be compile time "
2463 "constant in the range 0-255 for __builtin_custom_%s",
2464 custom_builtin_name
[index
]);
2467 /* For other arguments, force into a register. */
2468 unspec_args
[argno
] = force_reg (TYPE_MODE (TREE_TYPE (arg
)),
2469 unspec_args
[argno
]);
2471 /* Fill remaining unspec operands with zero. */
2472 for (; argno
< 3; argno
++)
2473 unspec_args
[argno
] = const0_rtx
;
2475 insn
= (has_target_p
2476 ? gen_rtx_SET (VOIDmode
, target
,
2477 gen_rtx_UNSPEC_VOLATILE (tmode
,
2478 gen_rtvec_v (3, unspec_args
),
2479 UNSPECV_CUSTOM_XNXX
))
2480 : gen_rtx_UNSPEC_VOLATILE (VOIDmode
, gen_rtvec_v (3, unspec_args
),
2481 UNSPECV_CUSTOM_NXX
));
2483 return has_target_p
? target
: const0_rtx
;
2489 /* Main definition of built-in functions. Nios II has a small number of fixed
2490 builtins, plus a large number of FPU insn builtins, and builtins for
2491 generating custom instructions. */
2493 struct nios2_builtin_desc
2495 enum insn_code icode
;
2496 enum nios2_ftcode ftype
;
2500 #define N2_BUILTINS \
2501 N2_BUILTIN_DEF (sync, N2_FTYPE_VOID_VOID) \
2502 N2_BUILTIN_DEF (ldbio, N2_FTYPE_SI_CVPTR) \
2503 N2_BUILTIN_DEF (ldbuio, N2_FTYPE_UI_CVPTR) \
2504 N2_BUILTIN_DEF (ldhio, N2_FTYPE_SI_CVPTR) \
2505 N2_BUILTIN_DEF (ldhuio, N2_FTYPE_UI_CVPTR) \
2506 N2_BUILTIN_DEF (ldwio, N2_FTYPE_SI_CVPTR) \
2507 N2_BUILTIN_DEF (stbio, N2_FTYPE_VOID_VPTR_SI) \
2508 N2_BUILTIN_DEF (sthio, N2_FTYPE_VOID_VPTR_SI) \
2509 N2_BUILTIN_DEF (stwio, N2_FTYPE_VOID_VPTR_SI) \
2510 N2_BUILTIN_DEF (rdctl, N2_FTYPE_SI_SI) \
2511 N2_BUILTIN_DEF (wrctl, N2_FTYPE_VOID_SI_SI)
2513 enum nios2_builtin_code
{
2514 #define N2_BUILTIN_DEF(name, ftype) NIOS2_BUILTIN_ ## name,
2516 #undef N2_BUILTIN_DEF
2517 NUM_FIXED_NIOS2_BUILTINS
2520 static const struct nios2_builtin_desc nios2_builtins
[] = {
2521 #define N2_BUILTIN_DEF(name, ftype) \
2522 { CODE_FOR_ ## name, ftype, "__builtin_" #name },
2524 #undef N2_BUILTIN_DEF
2527 /* Start/ends of FPU/custom insn builtin index ranges. */
2528 static unsigned int nios2_fpu_builtin_base
;
2529 static unsigned int nios2_custom_builtin_base
;
2530 static unsigned int nios2_custom_builtin_end
;
2532 /* Implement TARGET_INIT_BUILTINS. */
2534 nios2_init_builtins (void)
2538 /* Initialize fixed builtins. */
2539 for (i
= 0; i
< ARRAY_SIZE (nios2_builtins
); i
++)
2541 const struct nios2_builtin_desc
*d
= &nios2_builtins
[i
];
2543 add_builtin_function (d
->name
, nios2_ftype (d
->ftype
), i
,
2544 BUILT_IN_MD
, NULL
, NULL
);
2545 nios2_register_builtin_fndecl (i
, fndecl
);
2548 /* Initialize FPU builtins. */
2549 nios2_fpu_builtin_base
= ARRAY_SIZE (nios2_builtins
);
2550 nios2_init_fpu_builtins (nios2_fpu_builtin_base
);
2552 /* Initialize custom insn builtins. */
2553 nios2_custom_builtin_base
2554 = nios2_fpu_builtin_base
+ ARRAY_SIZE (nios2_fpu_insn
);
2555 nios2_custom_builtin_end
2556 = nios2_custom_builtin_base
+ NUM_CUSTOM_BUILTINS
;
2557 nios2_init_custom_builtins (nios2_custom_builtin_base
);
2560 /* Array of fndecls for TARGET_BUILTIN_DECL. */
2561 #define NIOS2_NUM_BUILTINS \
2562 (ARRAY_SIZE (nios2_builtins) + ARRAY_SIZE (nios2_fpu_insn) + NUM_CUSTOM_BUILTINS)
2563 static GTY(()) tree nios2_builtin_decls
[NIOS2_NUM_BUILTINS
];
2566 nios2_register_builtin_fndecl (unsigned code
, tree fndecl
)
2568 nios2_builtin_decls
[code
] = fndecl
;
2571 /* Implement TARGET_BUILTIN_DECL. */
2573 nios2_builtin_decl (unsigned code
, bool initialize_p ATTRIBUTE_UNUSED
)
2575 gcc_assert (nios2_custom_builtin_end
== ARRAY_SIZE (nios2_builtin_decls
));
2577 if (code
>= nios2_custom_builtin_end
)
2578 return error_mark_node
;
2580 if (code
>= nios2_fpu_builtin_base
2581 && code
< nios2_custom_builtin_base
2582 && ! N2FPU_ENABLED_P (code
- nios2_fpu_builtin_base
))
2583 return error_mark_node
;
2585 return nios2_builtin_decls
[code
];
2589 /* Low-level built-in expand routine. */
2591 nios2_expand_builtin_insn (const struct nios2_builtin_desc
*d
, int n
,
2592 struct expand_operand
*ops
, bool has_target_p
)
2594 if (maybe_expand_insn (d
->icode
, n
, ops
))
2595 return has_target_p
? ops
[0].value
: const0_rtx
;
2598 error ("invalid argument to built-in function %s", d
->name
);
2599 return has_target_p
? gen_reg_rtx (ops
[0].mode
) : const0_rtx
;
2603 /* Expand ldio/stio form load-store instruction builtins. */
2605 nios2_expand_ldstio_builtin (tree exp
, rtx target
,
2606 const struct nios2_builtin_desc
*d
)
2610 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
2611 enum machine_mode mode
= insn_data
[d
->icode
].operand
[0].mode
;
2613 addr
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2614 mem
= gen_rtx_MEM (mode
, addr
);
2616 if (insn_data
[d
->icode
].operand
[0].allows_mem
)
2619 val
= expand_normal (CALL_EXPR_ARG (exp
, 1));
2620 if (CONST_INT_P (val
))
2621 val
= force_reg (mode
, gen_int_mode (INTVAL (val
), mode
));
2622 val
= simplify_gen_subreg (mode
, val
, GET_MODE (val
), 0);
2623 create_output_operand (&ops
[0], mem
, mode
);
2624 create_input_operand (&ops
[1], val
, mode
);
2625 has_target_p
= false;
2630 create_output_operand (&ops
[0], target
, mode
);
2631 create_input_operand (&ops
[1], mem
, mode
);
2632 has_target_p
= true;
2634 return nios2_expand_builtin_insn (d
, 2, ops
, has_target_p
);
2637 /* Expand rdctl/wrctl builtins. */
2639 nios2_expand_rdwrctl_builtin (tree exp
, rtx target
,
2640 const struct nios2_builtin_desc
*d
)
2642 bool has_target_p
= (insn_data
[d
->icode
].operand
[0].predicate
2643 == register_operand
);
2644 rtx ctlcode
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2645 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
2646 if (!rdwrctl_operand (ctlcode
, VOIDmode
))
2648 error ("Control register number must be in range 0-31 for %s",
2650 return has_target_p
? gen_reg_rtx (SImode
) : const0_rtx
;
2654 create_output_operand (&ops
[0], target
, SImode
);
2655 create_integer_operand (&ops
[1], INTVAL (ctlcode
));
2659 rtx val
= expand_normal (CALL_EXPR_ARG (exp
, 1));
2660 create_integer_operand (&ops
[0], INTVAL (ctlcode
));
2661 create_input_operand (&ops
[1], val
, SImode
);
2663 return nios2_expand_builtin_insn (d
, 2, ops
, has_target_p
);
2666 /* Implement TARGET_EXPAND_BUILTIN. Expand an expression EXP that calls
2667 a built-in function, with result going to TARGET if that's convenient
2668 (and in mode MODE if that's convenient).
2669 SUBTARGET may be used as the target for computing one of EXP's operands.
2670 IGNORE is nonzero if the value is to be ignored. */
2673 nios2_expand_builtin (tree exp
, rtx target
, rtx subtarget ATTRIBUTE_UNUSED
,
2674 enum machine_mode mode ATTRIBUTE_UNUSED
,
2675 int ignore ATTRIBUTE_UNUSED
)
2677 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
2678 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
2680 if (fcode
< nios2_fpu_builtin_base
)
2682 const struct nios2_builtin_desc
*d
= &nios2_builtins
[fcode
];
2686 case NIOS2_BUILTIN_sync
:
2687 emit_insn (gen_sync ());
2690 case NIOS2_BUILTIN_ldbio
:
2691 case NIOS2_BUILTIN_ldbuio
:
2692 case NIOS2_BUILTIN_ldhio
:
2693 case NIOS2_BUILTIN_ldhuio
:
2694 case NIOS2_BUILTIN_ldwio
:
2695 case NIOS2_BUILTIN_stbio
:
2696 case NIOS2_BUILTIN_sthio
:
2697 case NIOS2_BUILTIN_stwio
:
2698 return nios2_expand_ldstio_builtin (exp
, target
, d
);
2700 case NIOS2_BUILTIN_rdctl
:
2701 case NIOS2_BUILTIN_wrctl
:
2702 return nios2_expand_rdwrctl_builtin (exp
, target
, d
);
2708 else if (fcode
< nios2_custom_builtin_base
)
2709 /* FPU builtin range. */
2710 return nios2_expand_fpu_builtin (exp
, fcode
- nios2_fpu_builtin_base
,
2712 else if (fcode
< nios2_custom_builtin_end
)
2713 /* Custom insn builtin range. */
2714 return nios2_expand_custom_builtin (exp
, fcode
- nios2_custom_builtin_base
,
2720 /* Implement TARGET_INIT_LIBFUNCS. */
2722 nios2_init_libfuncs (void)
2724 /* For Linux, we have access to kernel support for atomic operations. */
2725 if (TARGET_LINUX_ABI
)
2726 init_sync_libfuncs (UNITS_PER_WORD
);
2731 /* Register a custom code use, and signal error if a conflict was found. */
2733 nios2_register_custom_code (unsigned int N
, enum nios2_ccs_code status
,
2736 gcc_assert (N
<= 255);
2738 if (status
== CCS_FPU
)
2740 if (custom_code_status
[N
] == CCS_FPU
&& index
!= custom_code_index
[N
])
2742 custom_code_conflict
= true;
2743 error ("switch %<-mcustom-%s%> conflicts with switch %<-mcustom-%s%>",
2744 N2FPU_NAME (custom_code_index
[N
]), N2FPU_NAME (index
));
2746 else if (custom_code_status
[N
] == CCS_BUILTIN_CALL
)
2748 custom_code_conflict
= true;
2749 error ("call to %<__builtin_custom_%s%> conflicts with switch "
2750 "%<-mcustom-%s%>", custom_builtin_name
[custom_code_index
[N
]],
2751 N2FPU_NAME (index
));
2754 else if (status
== CCS_BUILTIN_CALL
)
2756 if (custom_code_status
[N
] == CCS_FPU
)
2758 custom_code_conflict
= true;
2759 error ("call to %<__builtin_custom_%s%> conflicts with switch "
2760 "%<-mcustom-%s%>", custom_builtin_name
[index
],
2761 N2FPU_NAME (custom_code_index
[N
]));
2765 /* Note that code conflicts between different __builtin_custom_xnxx
2766 calls are not checked. */
2772 custom_code_status
[N
] = status
;
2773 custom_code_index
[N
] = index
;
2776 /* Mark a custom code as not in use. */
2778 nios2_deregister_custom_code (unsigned int N
)
2782 custom_code_status
[N
] = CCS_UNUSED
;
2783 custom_code_index
[N
] = 0;
2787 /* Target attributes can affect per-function option state, so we need to
2788 save/restore the custom code tracking info using the
2789 TARGET_OPTION_SAVE/TARGET_OPTION_RESTORE hooks. */
2792 nios2_option_save (struct cl_target_option
*ptr
,
2793 struct gcc_options
*opts ATTRIBUTE_UNUSED
)
2796 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
2797 ptr
->saved_fpu_custom_code
[i
] = N2FPU_N (i
);
2798 memcpy (ptr
->saved_custom_code_status
, custom_code_status
,
2799 sizeof (custom_code_status
));
2800 memcpy (ptr
->saved_custom_code_index
, custom_code_index
,
2801 sizeof (custom_code_index
));
2805 nios2_option_restore (struct gcc_options
*opts ATTRIBUTE_UNUSED
,
2806 struct cl_target_option
*ptr
)
2809 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
2810 N2FPU_N (i
) = ptr
->saved_fpu_custom_code
[i
];
2811 memcpy (custom_code_status
, ptr
->saved_custom_code_status
,
2812 sizeof (custom_code_status
));
2813 memcpy (custom_code_index
, ptr
->saved_custom_code_index
,
2814 sizeof (custom_code_index
));
2817 /* Inner function to process the attribute((target(...))), take an argument and
2818 set the current options from the argument. If we have a list, recursively
2819 go over the list. */
2822 nios2_valid_target_attribute_rec (tree args
)
2824 if (TREE_CODE (args
) == TREE_LIST
)
2827 for (; args
; args
= TREE_CHAIN (args
))
2828 if (TREE_VALUE (args
)
2829 && !nios2_valid_target_attribute_rec (TREE_VALUE (args
)))
2833 else if (TREE_CODE (args
) == STRING_CST
)
2835 char *argstr
= ASTRDUP (TREE_STRING_POINTER (args
));
2836 while (argstr
&& *argstr
!= '\0')
2838 bool no_opt
= false, end_p
= false;
2839 char *eq
= NULL
, *p
;
2840 while (ISSPACE (*argstr
))
2843 while (*p
!= '\0' && *p
!= ',')
2845 if (!eq
&& *p
== '=')
2855 if (!strncmp (argstr
, "no-", 3))
2860 if (!strncmp (argstr
, "custom-fpu-cfg", 14))
2865 error ("custom-fpu-cfg option does not support %<no-%>");
2870 error ("custom-fpu-cfg option requires configuration"
2874 /* Increment and skip whitespace. */
2875 while (ISSPACE (*(++eq
))) ;
2876 /* Decrement and skip to before any trailing whitespace. */
2877 while (ISSPACE (*(--end_eq
))) ;
2879 nios2_handle_custom_fpu_cfg (eq
, end_eq
+ 1, true);
2881 else if (!strncmp (argstr
, "custom-", 7))
2885 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
2886 if (!strncmp (argstr
+ 7, N2FPU_NAME (i
),
2887 strlen (N2FPU_NAME (i
))))
2899 error ("%<no-custom-%s%> does not accept arguments",
2903 /* Disable option by setting to -1. */
2904 nios2_deregister_custom_code (N2FPU_N (code
));
2905 N2FPU_N (code
) = -1;
2911 while (ISSPACE (*(++eq
))) ;
2914 error ("%<custom-%s=%> requires argument",
2918 for (t
= eq
; t
!= p
; ++t
)
2924 error ("`custom-%s=' argument requires "
2925 "numeric digits", N2FPU_NAME (code
));
2929 /* Set option to argument. */
2930 N2FPU_N (code
) = atoi (eq
);
2931 nios2_handle_custom_fpu_insn_option (code
);
2936 error ("%<custom-%s=%> is not recognised as FPU instruction",
2943 error ("%<%s%> is unknown", argstr
);
2958 /* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. */
2961 nios2_valid_target_attribute_tree (tree args
)
2963 if (!nios2_valid_target_attribute_rec (args
))
2965 nios2_custom_check_insns ();
2966 return build_target_option_node (&global_options
);
2969 /* Hook to validate attribute((target("string"))). */
2972 nios2_valid_target_attribute_p (tree fndecl
, tree
ARG_UNUSED (name
),
2973 tree args
, int ARG_UNUSED (flags
))
2975 struct cl_target_option cur_target
;
2977 tree old_optimize
= build_optimization_node (&global_options
);
2978 tree new_target
, new_optimize
;
2979 tree func_optimize
= DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl
);
2981 /* If the function changed the optimization levels as well as setting target
2982 options, start with the optimizations specified. */
2983 if (func_optimize
&& func_optimize
!= old_optimize
)
2984 cl_optimization_restore (&global_options
,
2985 TREE_OPTIMIZATION (func_optimize
));
2987 /* The target attributes may also change some optimization flags, so update
2988 the optimization options if necessary. */
2989 cl_target_option_save (&cur_target
, &global_options
);
2990 new_target
= nios2_valid_target_attribute_tree (args
);
2991 new_optimize
= build_optimization_node (&global_options
);
2998 DECL_FUNCTION_SPECIFIC_TARGET (fndecl
) = new_target
;
3000 if (old_optimize
!= new_optimize
)
3001 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl
) = new_optimize
;
3004 cl_target_option_restore (&global_options
, &cur_target
);
3006 if (old_optimize
!= new_optimize
)
3007 cl_optimization_restore (&global_options
,
3008 TREE_OPTIMIZATION (old_optimize
));
3012 /* Remember the last target of nios2_set_current_function. */
3013 static GTY(()) tree nios2_previous_fndecl
;
3015 /* Establish appropriate back-end context for processing the function
3016 FNDECL. The argument might be NULL to indicate processing at top
3017 level, outside of any function scope. */
3019 nios2_set_current_function (tree fndecl
)
3021 tree old_tree
= (nios2_previous_fndecl
3022 ? DECL_FUNCTION_SPECIFIC_TARGET (nios2_previous_fndecl
)
3025 tree new_tree
= (fndecl
3026 ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl
)
3029 if (fndecl
&& fndecl
!= nios2_previous_fndecl
)
3031 nios2_previous_fndecl
= fndecl
;
3032 if (old_tree
== new_tree
)
3037 cl_target_option_restore (&global_options
,
3038 TREE_TARGET_OPTION (new_tree
));
3044 struct cl_target_option
*def
3045 = TREE_TARGET_OPTION (target_option_current_node
);
3047 cl_target_option_restore (&global_options
, def
);
3053 /* Hook to validate the current #pragma GCC target and set the FPU custom
3054 code option state. If ARGS is NULL, then POP_TARGET is used to reset
3057 nios2_pragma_target_parse (tree args
, tree pop_target
)
3062 cur_tree
= ((pop_target
)
3064 : target_option_default_node
);
3065 cl_target_option_restore (&global_options
,
3066 TREE_TARGET_OPTION (cur_tree
));
3070 cur_tree
= nios2_valid_target_attribute_tree (args
);
3075 target_option_current_node
= cur_tree
;
3079 /* Implement TARGET_MERGE_DECL_ATTRIBUTES.
3080 We are just using this hook to add some additional error checking to
3081 the default behavior. GCC does not provide a target hook for merging
3082 the target options, and only correctly handles merging empty vs non-empty
3083 option data; see merge_decls() in c-decl.c.
3084 So here we require either that at least one of the decls has empty
3085 target options, or that the target options/data be identical. */
3087 nios2_merge_decl_attributes (tree olddecl
, tree newdecl
)
3089 tree oldopts
= lookup_attribute ("target", DECL_ATTRIBUTES (olddecl
));
3090 tree newopts
= lookup_attribute ("target", DECL_ATTRIBUTES (newdecl
));
3091 if (newopts
&& oldopts
&& newopts
!= oldopts
)
3093 tree oldtree
= DECL_FUNCTION_SPECIFIC_TARGET (olddecl
);
3094 tree newtree
= DECL_FUNCTION_SPECIFIC_TARGET (newdecl
);
3095 if (oldtree
&& newtree
&& oldtree
!= newtree
)
3097 struct cl_target_option
*olddata
= TREE_TARGET_OPTION (oldtree
);
3098 struct cl_target_option
*newdata
= TREE_TARGET_OPTION (newtree
);
3099 if (olddata
!= newdata
3100 && memcmp (olddata
, newdata
, sizeof (struct cl_target_option
)))
3101 error ("%qE redeclared with conflicting %qs attributes",
3102 DECL_NAME (newdecl
), "target");
3105 return merge_attributes (DECL_ATTRIBUTES (olddecl
),
3106 DECL_ATTRIBUTES (newdecl
));
3110 /* Initialize the GCC target structure. */
3111 #undef TARGET_ASM_FUNCTION_PROLOGUE
3112 #define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
3114 #undef TARGET_IN_SMALL_DATA_P
3115 #define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
3117 #undef TARGET_SECTION_TYPE_FLAGS
3118 #define TARGET_SECTION_TYPE_FLAGS nios2_section_type_flags
3120 #undef TARGET_INIT_BUILTINS
3121 #define TARGET_INIT_BUILTINS nios2_init_builtins
3122 #undef TARGET_EXPAND_BUILTIN
3123 #define TARGET_EXPAND_BUILTIN nios2_expand_builtin
3124 #undef TARGET_BUILTIN_DECL
3125 #define TARGET_BUILTIN_DECL nios2_builtin_decl
3127 #undef TARGET_INIT_LIBFUNCS
3128 #define TARGET_INIT_LIBFUNCS nios2_init_libfuncs
3130 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
3131 #define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
3133 #undef TARGET_CAN_ELIMINATE
3134 #define TARGET_CAN_ELIMINATE nios2_can_eliminate
3136 #undef TARGET_FUNCTION_ARG
3137 #define TARGET_FUNCTION_ARG nios2_function_arg
3139 #undef TARGET_FUNCTION_ARG_ADVANCE
3140 #define TARGET_FUNCTION_ARG_ADVANCE nios2_function_arg_advance
3142 #undef TARGET_ARG_PARTIAL_BYTES
3143 #define TARGET_ARG_PARTIAL_BYTES nios2_arg_partial_bytes
3145 #undef TARGET_TRAMPOLINE_INIT
3146 #define TARGET_TRAMPOLINE_INIT nios2_trampoline_init
3148 #undef TARGET_FUNCTION_VALUE
3149 #define TARGET_FUNCTION_VALUE nios2_function_value
3151 #undef TARGET_LIBCALL_VALUE
3152 #define TARGET_LIBCALL_VALUE nios2_libcall_value
3154 #undef TARGET_FUNCTION_VALUE_REGNO_P
3155 #define TARGET_FUNCTION_VALUE_REGNO_P nios2_function_value_regno_p
3157 #undef TARGET_RETURN_IN_MEMORY
3158 #define TARGET_RETURN_IN_MEMORY nios2_return_in_memory
3160 #undef TARGET_PROMOTE_PROTOTYPES
3161 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
3163 #undef TARGET_SETUP_INCOMING_VARARGS
3164 #define TARGET_SETUP_INCOMING_VARARGS nios2_setup_incoming_varargs
3166 #undef TARGET_MUST_PASS_IN_STACK
3167 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
3169 #undef TARGET_LEGITIMATE_CONSTANT_P
3170 #define TARGET_LEGITIMATE_CONSTANT_P nios2_legitimate_constant_p
3172 #undef TARGET_LEGITIMIZE_ADDRESS
3173 #define TARGET_LEGITIMIZE_ADDRESS nios2_legitimize_address
3175 #undef TARGET_LEGITIMATE_ADDRESS_P
3176 #define TARGET_LEGITIMATE_ADDRESS_P nios2_legitimate_address_p
3178 #undef TARGET_PREFERRED_RELOAD_CLASS
3179 #define TARGET_PREFERRED_RELOAD_CLASS nios2_preferred_reload_class
3181 #undef TARGET_RTX_COSTS
3182 #define TARGET_RTX_COSTS nios2_rtx_costs
3184 #undef TARGET_HAVE_TLS
3185 #define TARGET_HAVE_TLS TARGET_LINUX_ABI
3187 #undef TARGET_CANNOT_FORCE_CONST_MEM
3188 #define TARGET_CANNOT_FORCE_CONST_MEM nios2_cannot_force_const_mem
3190 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
3191 #define TARGET_ASM_OUTPUT_DWARF_DTPREL nios2_output_dwarf_dtprel
3193 #undef TARGET_PRINT_OPERAND
3194 #define TARGET_PRINT_OPERAND nios2_print_operand
3196 #undef TARGET_PRINT_OPERAND_ADDRESS
3197 #define TARGET_PRINT_OPERAND_ADDRESS nios2_print_operand_address
3199 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
3200 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA nios2_output_addr_const_extra
3202 #undef TARGET_OPTION_OVERRIDE
3203 #define TARGET_OPTION_OVERRIDE nios2_option_override
3205 #undef TARGET_OPTION_SAVE
3206 #define TARGET_OPTION_SAVE nios2_option_save
3208 #undef TARGET_OPTION_RESTORE
3209 #define TARGET_OPTION_RESTORE nios2_option_restore
3211 #undef TARGET_SET_CURRENT_FUNCTION
3212 #define TARGET_SET_CURRENT_FUNCTION nios2_set_current_function
3214 #undef TARGET_OPTION_VALID_ATTRIBUTE_P
3215 #define TARGET_OPTION_VALID_ATTRIBUTE_P nios2_valid_target_attribute_p
3217 #undef TARGET_OPTION_PRAGMA_PARSE
3218 #define TARGET_OPTION_PRAGMA_PARSE nios2_pragma_target_parse
3220 #undef TARGET_MERGE_DECL_ATTRIBUTES
3221 #define TARGET_MERGE_DECL_ATTRIBUTES nios2_merge_decl_attributes
3223 struct gcc_target targetm
= TARGET_INITIALIZER
;
3225 #include "gt-nios2.h"