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(_GLOBAL_OFFSET_TABLE_ - 1b)\n");
671 fprintf (file
, "\taddi\tr3, r3, %%lo(_GLOBAL_OFFSET_TABLE_ - 1b)\n");
672 fprintf (file
, "\tadd\tr2, r2, r3\n");
673 fprintf (file
, "\tldw\tr2, %%call(_mcount)(r2)\n");
674 fprintf (file
, "\tcallr\tr2\n");
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
= "%0"; op2
= "%1";
2070 op3
= (num_operands
== 2 ? "zero" : "%2");
2073 else if (src_mode
== DFmode
)
2075 if (dst_mode
== VOIDmode
)
2077 /* The fwrx case. */
2085 op1
= (dst_mode
== DFmode
? "%D0" : "%0");
2086 op2
= (num_operands
== 2 ? "%1" : "%2");
2087 op3
= (num_operands
== 2 ? "%D1" : "%D2");
2090 else if (src_mode
== VOIDmode
)
2092 /* frdxlo, frdxhi, frdy cases. */
2093 gcc_assert (dst_mode
== SFmode
);
2097 else if (src_mode
== SImode
)
2099 /* Conversion operators. */
2100 gcc_assert (num_operands
== 2);
2101 op1
= (dst_mode
== DFmode
? "%D0" : "%0");
2108 /* Main instruction string. */
2109 n
+= snprintf (buf
+ n
, ln
- n
, "custom\t%d, %s, %s, %s # %s %%0%s%s",
2110 N
, op1
, op2
, op3
, insn_name
,
2111 (num_operands
>= 2 ? ", %1" : ""),
2112 (num_operands
== 3 ? ", %2" : ""));
2114 /* Extraction of Y register for DF results. */
2115 if (dst_mode
== DFmode
)
2116 snprintf (buf
+ n
, ln
- n
, "\n\tcustom\t%d, %%0, zero, zero # frdy %%0",
2117 N2FPU_N (n2fpu_frdy
));
2123 /* Function argument related. */
2125 /* Define where to put the arguments to a function. Value is zero to
2126 push the argument on the stack, or a hard register in which to
2129 MODE is the argument's machine mode.
2130 TYPE is the data type of the argument (as a tree).
2131 This is null for libcalls where that information may
2133 CUM is a variable of type CUMULATIVE_ARGS which gives info about
2134 the preceding args and about the function being called.
2135 NAMED is nonzero if this argument is a named parameter
2136 (otherwise it is an extra parameter matching an ellipsis). */
2139 nios2_function_arg (cumulative_args_t cum_v
, enum machine_mode mode
,
2140 const_tree type ATTRIBUTE_UNUSED
,
2141 bool named ATTRIBUTE_UNUSED
)
2143 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2144 rtx return_rtx
= NULL_RTX
;
2146 if (cum
->regs_used
< NUM_ARG_REGS
)
2147 return_rtx
= gen_rtx_REG (mode
, FIRST_ARG_REGNO
+ cum
->regs_used
);
2152 /* Return number of bytes, at the beginning of the argument, that must be
2153 put in registers. 0 is the argument is entirely in registers or entirely
2157 nios2_arg_partial_bytes (cumulative_args_t cum_v
,
2158 enum machine_mode mode
, tree type ATTRIBUTE_UNUSED
,
2159 bool named ATTRIBUTE_UNUSED
)
2161 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2162 HOST_WIDE_INT param_size
;
2164 if (mode
== BLKmode
)
2166 param_size
= int_size_in_bytes (type
);
2167 gcc_assert (param_size
>= 0);
2170 param_size
= GET_MODE_SIZE (mode
);
2172 /* Convert to words (round up). */
2173 param_size
= (UNITS_PER_WORD
- 1 + param_size
) / UNITS_PER_WORD
;
2175 if (cum
->regs_used
< NUM_ARG_REGS
2176 && cum
->regs_used
+ param_size
> NUM_ARG_REGS
)
2177 return (NUM_ARG_REGS
- cum
->regs_used
) * UNITS_PER_WORD
;
2182 /* Update the data in CUM to advance over an argument of mode MODE
2183 and data type TYPE; TYPE is null for libcalls where that information
2184 may not be available. */
2187 nios2_function_arg_advance (cumulative_args_t cum_v
, enum machine_mode mode
,
2188 const_tree type ATTRIBUTE_UNUSED
,
2189 bool named ATTRIBUTE_UNUSED
)
2191 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2192 HOST_WIDE_INT param_size
;
2194 if (mode
== BLKmode
)
2196 param_size
= int_size_in_bytes (type
);
2197 gcc_assert (param_size
>= 0);
2200 param_size
= GET_MODE_SIZE (mode
);
2202 /* Convert to words (round up). */
2203 param_size
= (UNITS_PER_WORD
- 1 + param_size
) / UNITS_PER_WORD
;
2205 if (cum
->regs_used
+ param_size
> NUM_ARG_REGS
)
2206 cum
->regs_used
= NUM_ARG_REGS
;
2208 cum
->regs_used
+= param_size
;
2212 nios2_function_arg_padding (enum machine_mode mode
, const_tree type
)
2214 /* On little-endian targets, the first byte of every stack argument
2215 is passed in the first byte of the stack slot. */
2216 if (!BYTES_BIG_ENDIAN
)
2219 /* Otherwise, integral types are padded downward: the last byte of a
2220 stack argument is passed in the last byte of the stack slot. */
2222 ? INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
)
2223 : GET_MODE_CLASS (mode
) == MODE_INT
)
2226 /* Arguments smaller than a stack slot are padded downward. */
2227 if (mode
!= BLKmode
)
2228 return (GET_MODE_BITSIZE (mode
) >= PARM_BOUNDARY
) ? upward
: downward
;
2230 return ((int_size_in_bytes (type
) >= (PARM_BOUNDARY
/ BITS_PER_UNIT
))
2231 ? upward
: downward
);
2235 nios2_block_reg_padding (enum machine_mode mode
, tree type
,
2236 int first ATTRIBUTE_UNUSED
)
2238 return nios2_function_arg_padding (mode
, type
);
2241 /* Emit RTL insns to initialize the variable parts of a trampoline.
2242 FNADDR is an RTX for the address of the function's pure code.
2243 CXT is an RTX for the static chain value for the function.
2244 On Nios II, we handle this by a library call. */
2246 nios2_trampoline_init (rtx m_tramp
, tree fndecl
, rtx cxt
)
2248 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2249 rtx ctx_reg
= force_reg (Pmode
, cxt
);
2250 rtx addr
= force_reg (Pmode
, XEXP (m_tramp
, 0));
2252 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "__trampoline_setup"),
2253 LCT_NORMAL
, VOIDmode
, 3, addr
, Pmode
, fnaddr
, Pmode
,
2257 /* Implement TARGET_FUNCTION_VALUE. */
2259 nios2_function_value (const_tree ret_type
, const_tree fn ATTRIBUTE_UNUSED
,
2260 bool outgoing ATTRIBUTE_UNUSED
)
2262 return gen_rtx_REG (TYPE_MODE (ret_type
), FIRST_RETVAL_REGNO
);
2265 /* Implement TARGET_LIBCALL_VALUE. */
2267 nios2_libcall_value (enum machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
2269 return gen_rtx_REG (mode
, FIRST_RETVAL_REGNO
);
2272 /* Implement TARGET_FUNCTION_VALUE_REGNO_P. */
2274 nios2_function_value_regno_p (const unsigned int regno
)
2276 return regno
== FIRST_RETVAL_REGNO
;
2279 /* Implement TARGET_RETURN_IN_MEMORY. */
2281 nios2_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
2283 return (int_size_in_bytes (type
) > (2 * UNITS_PER_WORD
)
2284 || int_size_in_bytes (type
) == -1);
2287 /* TODO: It may be possible to eliminate the copyback and implement
2290 nios2_setup_incoming_varargs (cumulative_args_t cum_v
,
2291 enum machine_mode mode
, tree type
,
2292 int *pretend_size
, int second_time
)
2294 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2295 CUMULATIVE_ARGS local_cum
;
2296 cumulative_args_t local_cum_v
= pack_cumulative_args (&local_cum
);
2301 nios2_function_arg_advance (local_cum_v
, mode
, type
, 1);
2303 regs_to_push
= NUM_ARG_REGS
- local_cum
.regs_used
;
2305 if (!second_time
&& regs_to_push
> 0)
2307 rtx ptr
= virtual_incoming_args_rtx
;
2308 rtx mem
= gen_rtx_MEM (BLKmode
, ptr
);
2309 emit_insn (gen_blockage ());
2310 move_block_from_reg (local_cum
.regs_used
+ FIRST_ARG_REGNO
, mem
,
2312 emit_insn (gen_blockage ());
2315 pret_size
= regs_to_push
* UNITS_PER_WORD
;
2317 *pretend_size
= pret_size
;
2322 /* Init FPU builtins. */
2324 nios2_init_fpu_builtins (int start_code
)
2327 char builtin_name
[64] = "__builtin_custom_";
2328 unsigned int i
, n
= strlen ("__builtin_custom_");
2330 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
2332 snprintf (builtin_name
+ n
, sizeof (builtin_name
) - n
,
2333 "%s", N2FPU_NAME (i
));
2335 add_builtin_function (builtin_name
, nios2_ftype (N2FPU_FTCODE (i
)),
2336 start_code
+ i
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2337 nios2_register_builtin_fndecl (start_code
+ i
, fndecl
);
2341 /* Helper function for expanding FPU builtins. */
2343 nios2_expand_fpu_builtin (tree exp
, unsigned int code
, rtx target
)
2345 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
2346 enum insn_code icode
= N2FPU_ICODE (code
);
2347 int nargs
, argno
, opno
= 0;
2348 int num_operands
= N2FPU (code
).num_operands
;
2349 enum machine_mode dst_mode
= TYPE_MODE (TREE_TYPE (exp
));
2350 bool has_target_p
= (dst_mode
!= VOIDmode
);
2352 if (N2FPU_N (code
) < 0)
2353 fatal_error ("Cannot call %<__builtin_custom_%s%> without specifying switch"
2354 " %<-mcustom-%s%>", N2FPU_NAME (code
), N2FPU_NAME (code
));
2356 create_output_operand (&ops
[opno
++], target
, dst_mode
);
2358 /* Subtract away the count of the VOID return, mainly for fwrx/fwry. */
2360 nargs
= call_expr_nargs (exp
);
2361 for (argno
= 0; argno
< nargs
; argno
++)
2363 tree arg
= CALL_EXPR_ARG (exp
, argno
);
2364 create_input_operand (&ops
[opno
++], expand_normal (arg
),
2365 TYPE_MODE (TREE_TYPE (arg
)));
2367 if (!maybe_expand_insn (icode
, num_operands
, ops
))
2369 error ("invalid argument to built-in function");
2370 return has_target_p
? gen_reg_rtx (ops
[0].mode
) : const0_rtx
;
2372 return has_target_p
? ops
[0].value
: const0_rtx
;
2375 /* Nios II has custom instruction built-in functions of the forms:
2378 __builtin_custom_nXX
2380 __builtin_custom_XnX
2381 __builtin_custom_XnXX
2383 where each X could be either 'i' (int), 'f' (float), or 'p' (void*).
2384 Therefore with 0-1 return values, and 0-2 arguments, we have a
2385 total of (3 + 1) * (1 + 3 + 9) == 52 custom builtin functions.
2387 #define NUM_CUSTOM_BUILTINS ((3 + 1) * (1 + 3 + 9))
2388 static char custom_builtin_name
[NUM_CUSTOM_BUILTINS
][5];
2391 nios2_init_custom_builtins (int start_code
)
2393 tree builtin_ftype
, ret_type
, fndecl
;
2394 char builtin_name
[32] = "__builtin_custom_";
2395 int n
= strlen ("__builtin_custom_");
2396 int builtin_code
= 0;
2397 int lhs
, rhs1
, rhs2
;
2399 struct { tree type
; const char *c
; } op
[4];
2400 /* z */ op
[0].c
= ""; op
[0].type
= NULL_TREE
;
2401 /* f */ op
[1].c
= "f"; op
[1].type
= float_type_node
;
2402 /* i */ op
[2].c
= "i"; op
[2].type
= integer_type_node
;
2403 /* p */ op
[3].c
= "p"; op
[3].type
= ptr_type_node
;
2405 /* We enumerate through the possible operand types to create all the
2406 __builtin_custom_XnXX function tree types. Note that these may slightly
2407 overlap with the function types created for other fixed builtins. */
2409 for (lhs
= 0; lhs
< 4; lhs
++)
2410 for (rhs1
= 0; rhs1
< 4; rhs1
++)
2411 for (rhs2
= 0; rhs2
< 4; rhs2
++)
2413 if (rhs1
== 0 && rhs2
!= 0)
2415 ret_type
= (op
[lhs
].type
? op
[lhs
].type
: void_type_node
);
2417 = build_function_type_list (ret_type
, integer_type_node
,
2418 op
[rhs1
].type
, op
[rhs2
].type
,
2420 snprintf (builtin_name
+ n
, 32 - n
, "%sn%s%s",
2421 op
[lhs
].c
, op
[rhs1
].c
, op
[rhs2
].c
);
2422 /* Save copy of parameter string into custom_builtin_name[]. */
2423 strncpy (custom_builtin_name
[builtin_code
], builtin_name
+ n
, 5);
2425 add_builtin_function (builtin_name
, builtin_ftype
,
2426 start_code
+ builtin_code
,
2427 BUILT_IN_MD
, NULL
, NULL_TREE
);
2428 nios2_register_builtin_fndecl (start_code
+ builtin_code
, fndecl
);
2433 /* Helper function for expanding custom builtins. */
2435 nios2_expand_custom_builtin (tree exp
, unsigned int index
, rtx target
)
2437 bool has_target_p
= (TREE_TYPE (exp
) != void_type_node
);
2438 enum machine_mode tmode
= VOIDmode
;
2440 rtx value
, insn
, unspec_args
[3];
2446 tmode
= TYPE_MODE (TREE_TYPE (exp
));
2447 if (!target
|| GET_MODE (target
) != tmode
2449 target
= gen_reg_rtx (tmode
);
2452 nargs
= call_expr_nargs (exp
);
2453 for (argno
= 0; argno
< nargs
; argno
++)
2455 arg
= CALL_EXPR_ARG (exp
, argno
);
2456 value
= expand_normal (arg
);
2457 unspec_args
[argno
] = value
;
2460 if (!custom_insn_opcode (value
, VOIDmode
))
2461 error ("custom instruction opcode must be compile time "
2462 "constant in the range 0-255 for __builtin_custom_%s",
2463 custom_builtin_name
[index
]);
2466 /* For other arguments, force into a register. */
2467 unspec_args
[argno
] = force_reg (TYPE_MODE (TREE_TYPE (arg
)),
2468 unspec_args
[argno
]);
2470 /* Fill remaining unspec operands with zero. */
2471 for (; argno
< 3; argno
++)
2472 unspec_args
[argno
] = const0_rtx
;
2474 insn
= (has_target_p
2475 ? gen_rtx_SET (VOIDmode
, target
,
2476 gen_rtx_UNSPEC_VOLATILE (tmode
,
2477 gen_rtvec_v (3, unspec_args
),
2478 UNSPECV_CUSTOM_XNXX
))
2479 : gen_rtx_UNSPEC_VOLATILE (VOIDmode
, gen_rtvec_v (3, unspec_args
),
2480 UNSPECV_CUSTOM_NXX
));
2482 return has_target_p
? target
: const0_rtx
;
2488 /* Main definition of built-in functions. Nios II has a small number of fixed
2489 builtins, plus a large number of FPU insn builtins, and builtins for
2490 generating custom instructions. */
2492 struct nios2_builtin_desc
2494 enum insn_code icode
;
2495 enum nios2_ftcode ftype
;
2499 #define N2_BUILTINS \
2500 N2_BUILTIN_DEF (sync, N2_FTYPE_VOID_VOID) \
2501 N2_BUILTIN_DEF (ldbio, N2_FTYPE_SI_CVPTR) \
2502 N2_BUILTIN_DEF (ldbuio, N2_FTYPE_UI_CVPTR) \
2503 N2_BUILTIN_DEF (ldhio, N2_FTYPE_SI_CVPTR) \
2504 N2_BUILTIN_DEF (ldhuio, N2_FTYPE_UI_CVPTR) \
2505 N2_BUILTIN_DEF (ldwio, N2_FTYPE_SI_CVPTR) \
2506 N2_BUILTIN_DEF (stbio, N2_FTYPE_VOID_VPTR_SI) \
2507 N2_BUILTIN_DEF (sthio, N2_FTYPE_VOID_VPTR_SI) \
2508 N2_BUILTIN_DEF (stwio, N2_FTYPE_VOID_VPTR_SI) \
2509 N2_BUILTIN_DEF (rdctl, N2_FTYPE_SI_SI) \
2510 N2_BUILTIN_DEF (wrctl, N2_FTYPE_VOID_SI_SI)
2512 enum nios2_builtin_code
{
2513 #define N2_BUILTIN_DEF(name, ftype) NIOS2_BUILTIN_ ## name,
2515 #undef N2_BUILTIN_DEF
2516 NUM_FIXED_NIOS2_BUILTINS
2519 static const struct nios2_builtin_desc nios2_builtins
[] = {
2520 #define N2_BUILTIN_DEF(name, ftype) \
2521 { CODE_FOR_ ## name, ftype, "__builtin_" #name },
2523 #undef N2_BUILTIN_DEF
2526 /* Start/ends of FPU/custom insn builtin index ranges. */
2527 static unsigned int nios2_fpu_builtin_base
;
2528 static unsigned int nios2_custom_builtin_base
;
2529 static unsigned int nios2_custom_builtin_end
;
2531 /* Implement TARGET_INIT_BUILTINS. */
2533 nios2_init_builtins (void)
2537 /* Initialize fixed builtins. */
2538 for (i
= 0; i
< ARRAY_SIZE (nios2_builtins
); i
++)
2540 const struct nios2_builtin_desc
*d
= &nios2_builtins
[i
];
2542 add_builtin_function (d
->name
, nios2_ftype (d
->ftype
), i
,
2543 BUILT_IN_MD
, NULL
, NULL
);
2544 nios2_register_builtin_fndecl (i
, fndecl
);
2547 /* Initialize FPU builtins. */
2548 nios2_fpu_builtin_base
= ARRAY_SIZE (nios2_builtins
);
2549 nios2_init_fpu_builtins (nios2_fpu_builtin_base
);
2551 /* Initialize custom insn builtins. */
2552 nios2_custom_builtin_base
2553 = nios2_fpu_builtin_base
+ ARRAY_SIZE (nios2_fpu_insn
);
2554 nios2_custom_builtin_end
2555 = nios2_custom_builtin_base
+ NUM_CUSTOM_BUILTINS
;
2556 nios2_init_custom_builtins (nios2_custom_builtin_base
);
2559 /* Array of fndecls for TARGET_BUILTIN_DECL. */
2560 #define NIOS2_NUM_BUILTINS \
2561 (ARRAY_SIZE (nios2_builtins) + ARRAY_SIZE (nios2_fpu_insn) + NUM_CUSTOM_BUILTINS)
2562 static GTY(()) tree nios2_builtin_decls
[NIOS2_NUM_BUILTINS
];
2565 nios2_register_builtin_fndecl (unsigned code
, tree fndecl
)
2567 nios2_builtin_decls
[code
] = fndecl
;
2570 /* Implement TARGET_BUILTIN_DECL. */
2572 nios2_builtin_decl (unsigned code
, bool initialize_p ATTRIBUTE_UNUSED
)
2574 gcc_assert (nios2_custom_builtin_end
== ARRAY_SIZE (nios2_builtin_decls
));
2576 if (code
>= nios2_custom_builtin_end
)
2577 return error_mark_node
;
2579 if (code
>= nios2_fpu_builtin_base
2580 && code
< nios2_custom_builtin_base
2581 && ! N2FPU_ENABLED_P (code
- nios2_fpu_builtin_base
))
2582 return error_mark_node
;
2584 return nios2_builtin_decls
[code
];
2588 /* Low-level built-in expand routine. */
2590 nios2_expand_builtin_insn (const struct nios2_builtin_desc
*d
, int n
,
2591 struct expand_operand
*ops
, bool has_target_p
)
2593 if (maybe_expand_insn (d
->icode
, n
, ops
))
2594 return has_target_p
? ops
[0].value
: const0_rtx
;
2597 error ("invalid argument to built-in function %s", d
->name
);
2598 return has_target_p
? gen_reg_rtx (ops
[0].mode
) : const0_rtx
;
2602 /* Expand ldio/stio form load-store instruction builtins. */
2604 nios2_expand_ldstio_builtin (tree exp
, rtx target
,
2605 const struct nios2_builtin_desc
*d
)
2609 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
2610 enum machine_mode mode
= insn_data
[d
->icode
].operand
[0].mode
;
2612 addr
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2613 mem
= gen_rtx_MEM (mode
, addr
);
2615 if (insn_data
[d
->icode
].operand
[0].allows_mem
)
2618 val
= expand_normal (CALL_EXPR_ARG (exp
, 1));
2619 if (CONST_INT_P (val
))
2620 val
= force_reg (mode
, gen_int_mode (INTVAL (val
), mode
));
2621 val
= simplify_gen_subreg (mode
, val
, GET_MODE (val
), 0);
2622 create_output_operand (&ops
[0], mem
, mode
);
2623 create_input_operand (&ops
[1], val
, mode
);
2624 has_target_p
= false;
2629 create_output_operand (&ops
[0], target
, mode
);
2630 create_input_operand (&ops
[1], mem
, mode
);
2631 has_target_p
= true;
2633 return nios2_expand_builtin_insn (d
, 2, ops
, has_target_p
);
2636 /* Expand rdctl/wrctl builtins. */
2638 nios2_expand_rdwrctl_builtin (tree exp
, rtx target
,
2639 const struct nios2_builtin_desc
*d
)
2641 bool has_target_p
= (insn_data
[d
->icode
].operand
[0].predicate
2642 == register_operand
);
2643 rtx ctlcode
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2644 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
2645 if (!rdwrctl_operand (ctlcode
, VOIDmode
))
2647 error ("Control register number must be in range 0-31 for %s",
2649 return has_target_p
? gen_reg_rtx (SImode
) : const0_rtx
;
2653 create_output_operand (&ops
[0], target
, SImode
);
2654 create_integer_operand (&ops
[1], INTVAL (ctlcode
));
2658 rtx val
= expand_normal (CALL_EXPR_ARG (exp
, 1));
2659 create_integer_operand (&ops
[0], INTVAL (ctlcode
));
2660 create_input_operand (&ops
[1], val
, SImode
);
2662 return nios2_expand_builtin_insn (d
, 2, ops
, has_target_p
);
2665 /* Implement TARGET_EXPAND_BUILTIN. Expand an expression EXP that calls
2666 a built-in function, with result going to TARGET if that's convenient
2667 (and in mode MODE if that's convenient).
2668 SUBTARGET may be used as the target for computing one of EXP's operands.
2669 IGNORE is nonzero if the value is to be ignored. */
2672 nios2_expand_builtin (tree exp
, rtx target
, rtx subtarget ATTRIBUTE_UNUSED
,
2673 enum machine_mode mode ATTRIBUTE_UNUSED
,
2674 int ignore ATTRIBUTE_UNUSED
)
2676 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
2677 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
2679 if (fcode
< nios2_fpu_builtin_base
)
2681 const struct nios2_builtin_desc
*d
= &nios2_builtins
[fcode
];
2685 case NIOS2_BUILTIN_sync
:
2686 emit_insn (gen_sync ());
2689 case NIOS2_BUILTIN_ldbio
:
2690 case NIOS2_BUILTIN_ldbuio
:
2691 case NIOS2_BUILTIN_ldhio
:
2692 case NIOS2_BUILTIN_ldhuio
:
2693 case NIOS2_BUILTIN_ldwio
:
2694 case NIOS2_BUILTIN_stbio
:
2695 case NIOS2_BUILTIN_sthio
:
2696 case NIOS2_BUILTIN_stwio
:
2697 return nios2_expand_ldstio_builtin (exp
, target
, d
);
2699 case NIOS2_BUILTIN_rdctl
:
2700 case NIOS2_BUILTIN_wrctl
:
2701 return nios2_expand_rdwrctl_builtin (exp
, target
, d
);
2707 else if (fcode
< nios2_custom_builtin_base
)
2708 /* FPU builtin range. */
2709 return nios2_expand_fpu_builtin (exp
, fcode
- nios2_fpu_builtin_base
,
2711 else if (fcode
< nios2_custom_builtin_end
)
2712 /* Custom insn builtin range. */
2713 return nios2_expand_custom_builtin (exp
, fcode
- nios2_custom_builtin_base
,
2719 /* Implement TARGET_INIT_LIBFUNCS. */
2721 nios2_init_libfuncs (void)
2723 /* For Linux, we have access to kernel support for atomic operations. */
2724 if (TARGET_LINUX_ABI
)
2725 init_sync_libfuncs (UNITS_PER_WORD
);
2730 /* Register a custom code use, and signal error if a conflict was found. */
2732 nios2_register_custom_code (unsigned int N
, enum nios2_ccs_code status
,
2735 gcc_assert (N
<= 255);
2737 if (status
== CCS_FPU
)
2739 if (custom_code_status
[N
] == CCS_FPU
&& index
!= custom_code_index
[N
])
2741 custom_code_conflict
= true;
2742 error ("switch %<-mcustom-%s%> conflicts with switch %<-mcustom-%s%>",
2743 N2FPU_NAME (custom_code_index
[N
]), N2FPU_NAME (index
));
2745 else if (custom_code_status
[N
] == CCS_BUILTIN_CALL
)
2747 custom_code_conflict
= true;
2748 error ("call to %<__builtin_custom_%s%> conflicts with switch "
2749 "%<-mcustom-%s%>", custom_builtin_name
[custom_code_index
[N
]],
2750 N2FPU_NAME (index
));
2753 else if (status
== CCS_BUILTIN_CALL
)
2755 if (custom_code_status
[N
] == CCS_FPU
)
2757 custom_code_conflict
= true;
2758 error ("call to %<__builtin_custom_%s%> conflicts with switch "
2759 "%<-mcustom-%s%>", custom_builtin_name
[index
],
2760 N2FPU_NAME (custom_code_index
[N
]));
2764 /* Note that code conflicts between different __builtin_custom_xnxx
2765 calls are not checked. */
2771 custom_code_status
[N
] = status
;
2772 custom_code_index
[N
] = index
;
2775 /* Mark a custom code as not in use. */
2777 nios2_deregister_custom_code (unsigned int N
)
2781 custom_code_status
[N
] = CCS_UNUSED
;
2782 custom_code_index
[N
] = 0;
2786 /* Target attributes can affect per-function option state, so we need to
2787 save/restore the custom code tracking info using the
2788 TARGET_OPTION_SAVE/TARGET_OPTION_RESTORE hooks. */
2791 nios2_option_save (struct cl_target_option
*ptr
,
2792 struct gcc_options
*opts ATTRIBUTE_UNUSED
)
2795 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
2796 ptr
->saved_fpu_custom_code
[i
] = N2FPU_N (i
);
2797 memcpy (ptr
->saved_custom_code_status
, custom_code_status
,
2798 sizeof (custom_code_status
));
2799 memcpy (ptr
->saved_custom_code_index
, custom_code_index
,
2800 sizeof (custom_code_index
));
2804 nios2_option_restore (struct gcc_options
*opts ATTRIBUTE_UNUSED
,
2805 struct cl_target_option
*ptr
)
2808 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
2809 N2FPU_N (i
) = ptr
->saved_fpu_custom_code
[i
];
2810 memcpy (custom_code_status
, ptr
->saved_custom_code_status
,
2811 sizeof (custom_code_status
));
2812 memcpy (custom_code_index
, ptr
->saved_custom_code_index
,
2813 sizeof (custom_code_index
));
2816 /* Inner function to process the attribute((target(...))), take an argument and
2817 set the current options from the argument. If we have a list, recursively
2818 go over the list. */
2821 nios2_valid_target_attribute_rec (tree args
)
2823 if (TREE_CODE (args
) == TREE_LIST
)
2826 for (; args
; args
= TREE_CHAIN (args
))
2827 if (TREE_VALUE (args
)
2828 && !nios2_valid_target_attribute_rec (TREE_VALUE (args
)))
2832 else if (TREE_CODE (args
) == STRING_CST
)
2834 char *argstr
= ASTRDUP (TREE_STRING_POINTER (args
));
2835 while (argstr
&& *argstr
!= '\0')
2837 bool no_opt
= false, end_p
= false;
2838 char *eq
= NULL
, *p
;
2839 while (ISSPACE (*argstr
))
2842 while (*p
!= '\0' && *p
!= ',')
2844 if (!eq
&& *p
== '=')
2854 if (!strncmp (argstr
, "no-", 3))
2859 if (!strncmp (argstr
, "custom-fpu-cfg", 14))
2864 error ("custom-fpu-cfg option does not support %<no-%>");
2869 error ("custom-fpu-cfg option requires configuration"
2873 /* Increment and skip whitespace. */
2874 while (ISSPACE (*(++eq
))) ;
2875 /* Decrement and skip to before any trailing whitespace. */
2876 while (ISSPACE (*(--end_eq
))) ;
2878 nios2_handle_custom_fpu_cfg (eq
, end_eq
+ 1, true);
2880 else if (!strncmp (argstr
, "custom-", 7))
2884 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
2885 if (!strncmp (argstr
+ 7, N2FPU_NAME (i
),
2886 strlen (N2FPU_NAME (i
))))
2898 error ("%<no-custom-%s%> does not accept arguments",
2902 /* Disable option by setting to -1. */
2903 nios2_deregister_custom_code (N2FPU_N (code
));
2904 N2FPU_N (code
) = -1;
2910 while (ISSPACE (*(++eq
))) ;
2913 error ("%<custom-%s=%> requires argument",
2917 for (t
= eq
; t
!= p
; ++t
)
2923 error ("`custom-%s=' argument requires "
2924 "numeric digits", N2FPU_NAME (code
));
2928 /* Set option to argument. */
2929 N2FPU_N (code
) = atoi (eq
);
2930 nios2_handle_custom_fpu_insn_option (code
);
2935 error ("%<custom-%s=%> is not recognised as FPU instruction",
2942 error ("%<%s%> is unknown", argstr
);
2957 /* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. */
2960 nios2_valid_target_attribute_tree (tree args
)
2962 if (!nios2_valid_target_attribute_rec (args
))
2964 nios2_custom_check_insns ();
2965 return build_target_option_node (&global_options
);
2968 /* Hook to validate attribute((target("string"))). */
2971 nios2_valid_target_attribute_p (tree fndecl
, tree
ARG_UNUSED (name
),
2972 tree args
, int ARG_UNUSED (flags
))
2974 struct cl_target_option cur_target
;
2976 tree old_optimize
= build_optimization_node (&global_options
);
2977 tree new_target
, new_optimize
;
2978 tree func_optimize
= DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl
);
2980 /* If the function changed the optimization levels as well as setting target
2981 options, start with the optimizations specified. */
2982 if (func_optimize
&& func_optimize
!= old_optimize
)
2983 cl_optimization_restore (&global_options
,
2984 TREE_OPTIMIZATION (func_optimize
));
2986 /* The target attributes may also change some optimization flags, so update
2987 the optimization options if necessary. */
2988 cl_target_option_save (&cur_target
, &global_options
);
2989 new_target
= nios2_valid_target_attribute_tree (args
);
2990 new_optimize
= build_optimization_node (&global_options
);
2997 DECL_FUNCTION_SPECIFIC_TARGET (fndecl
) = new_target
;
2999 if (old_optimize
!= new_optimize
)
3000 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl
) = new_optimize
;
3003 cl_target_option_restore (&global_options
, &cur_target
);
3005 if (old_optimize
!= new_optimize
)
3006 cl_optimization_restore (&global_options
,
3007 TREE_OPTIMIZATION (old_optimize
));
3011 /* Remember the last target of nios2_set_current_function. */
3012 static GTY(()) tree nios2_previous_fndecl
;
3014 /* Establish appropriate back-end context for processing the function
3015 FNDECL. The argument might be NULL to indicate processing at top
3016 level, outside of any function scope. */
3018 nios2_set_current_function (tree fndecl
)
3020 tree old_tree
= (nios2_previous_fndecl
3021 ? DECL_FUNCTION_SPECIFIC_TARGET (nios2_previous_fndecl
)
3024 tree new_tree
= (fndecl
3025 ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl
)
3028 if (fndecl
&& fndecl
!= nios2_previous_fndecl
)
3030 nios2_previous_fndecl
= fndecl
;
3031 if (old_tree
== new_tree
)
3036 cl_target_option_restore (&global_options
,
3037 TREE_TARGET_OPTION (new_tree
));
3043 struct cl_target_option
*def
3044 = TREE_TARGET_OPTION (target_option_current_node
);
3046 cl_target_option_restore (&global_options
, def
);
3052 /* Hook to validate the current #pragma GCC target and set the FPU custom
3053 code option state. If ARGS is NULL, then POP_TARGET is used to reset
3056 nios2_pragma_target_parse (tree args
, tree pop_target
)
3061 cur_tree
= ((pop_target
)
3063 : target_option_default_node
);
3064 cl_target_option_restore (&global_options
,
3065 TREE_TARGET_OPTION (cur_tree
));
3069 cur_tree
= nios2_valid_target_attribute_tree (args
);
3074 target_option_current_node
= cur_tree
;
3078 /* Implement TARGET_MERGE_DECL_ATTRIBUTES.
3079 We are just using this hook to add some additional error checking to
3080 the default behavior. GCC does not provide a target hook for merging
3081 the target options, and only correctly handles merging empty vs non-empty
3082 option data; see merge_decls() in c-decl.c.
3083 So here we require either that at least one of the decls has empty
3084 target options, or that the target options/data be identical. */
3086 nios2_merge_decl_attributes (tree olddecl
, tree newdecl
)
3088 tree oldopts
= lookup_attribute ("target", DECL_ATTRIBUTES (olddecl
));
3089 tree newopts
= lookup_attribute ("target", DECL_ATTRIBUTES (newdecl
));
3090 if (newopts
&& oldopts
&& newopts
!= oldopts
)
3092 tree oldtree
= DECL_FUNCTION_SPECIFIC_TARGET (olddecl
);
3093 tree newtree
= DECL_FUNCTION_SPECIFIC_TARGET (newdecl
);
3094 if (oldtree
&& newtree
&& oldtree
!= newtree
)
3096 struct cl_target_option
*olddata
= TREE_TARGET_OPTION (oldtree
);
3097 struct cl_target_option
*newdata
= TREE_TARGET_OPTION (newtree
);
3098 if (olddata
!= newdata
3099 && memcmp (olddata
, newdata
, sizeof (struct cl_target_option
)))
3100 error ("%qE redeclared with conflicting %qs attributes",
3101 DECL_NAME (newdecl
), "target");
3104 return merge_attributes (DECL_ATTRIBUTES (olddecl
),
3105 DECL_ATTRIBUTES (newdecl
));
3109 /* Initialize the GCC target structure. */
3110 #undef TARGET_ASM_FUNCTION_PROLOGUE
3111 #define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
3113 #undef TARGET_IN_SMALL_DATA_P
3114 #define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
3116 #undef TARGET_SECTION_TYPE_FLAGS
3117 #define TARGET_SECTION_TYPE_FLAGS nios2_section_type_flags
3119 #undef TARGET_INIT_BUILTINS
3120 #define TARGET_INIT_BUILTINS nios2_init_builtins
3121 #undef TARGET_EXPAND_BUILTIN
3122 #define TARGET_EXPAND_BUILTIN nios2_expand_builtin
3123 #undef TARGET_BUILTIN_DECL
3124 #define TARGET_BUILTIN_DECL nios2_builtin_decl
3126 #undef TARGET_INIT_LIBFUNCS
3127 #define TARGET_INIT_LIBFUNCS nios2_init_libfuncs
3129 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
3130 #define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
3132 #undef TARGET_CAN_ELIMINATE
3133 #define TARGET_CAN_ELIMINATE nios2_can_eliminate
3135 #undef TARGET_FUNCTION_ARG
3136 #define TARGET_FUNCTION_ARG nios2_function_arg
3138 #undef TARGET_FUNCTION_ARG_ADVANCE
3139 #define TARGET_FUNCTION_ARG_ADVANCE nios2_function_arg_advance
3141 #undef TARGET_ARG_PARTIAL_BYTES
3142 #define TARGET_ARG_PARTIAL_BYTES nios2_arg_partial_bytes
3144 #undef TARGET_TRAMPOLINE_INIT
3145 #define TARGET_TRAMPOLINE_INIT nios2_trampoline_init
3147 #undef TARGET_FUNCTION_VALUE
3148 #define TARGET_FUNCTION_VALUE nios2_function_value
3150 #undef TARGET_LIBCALL_VALUE
3151 #define TARGET_LIBCALL_VALUE nios2_libcall_value
3153 #undef TARGET_FUNCTION_VALUE_REGNO_P
3154 #define TARGET_FUNCTION_VALUE_REGNO_P nios2_function_value_regno_p
3156 #undef TARGET_RETURN_IN_MEMORY
3157 #define TARGET_RETURN_IN_MEMORY nios2_return_in_memory
3159 #undef TARGET_PROMOTE_PROTOTYPES
3160 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
3162 #undef TARGET_SETUP_INCOMING_VARARGS
3163 #define TARGET_SETUP_INCOMING_VARARGS nios2_setup_incoming_varargs
3165 #undef TARGET_MUST_PASS_IN_STACK
3166 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
3168 #undef TARGET_LEGITIMATE_CONSTANT_P
3169 #define TARGET_LEGITIMATE_CONSTANT_P nios2_legitimate_constant_p
3171 #undef TARGET_LEGITIMIZE_ADDRESS
3172 #define TARGET_LEGITIMIZE_ADDRESS nios2_legitimize_address
3174 #undef TARGET_LEGITIMATE_ADDRESS_P
3175 #define TARGET_LEGITIMATE_ADDRESS_P nios2_legitimate_address_p
3177 #undef TARGET_PREFERRED_RELOAD_CLASS
3178 #define TARGET_PREFERRED_RELOAD_CLASS nios2_preferred_reload_class
3180 #undef TARGET_RTX_COSTS
3181 #define TARGET_RTX_COSTS nios2_rtx_costs
3183 #undef TARGET_HAVE_TLS
3184 #define TARGET_HAVE_TLS TARGET_LINUX_ABI
3186 #undef TARGET_CANNOT_FORCE_CONST_MEM
3187 #define TARGET_CANNOT_FORCE_CONST_MEM nios2_cannot_force_const_mem
3189 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
3190 #define TARGET_ASM_OUTPUT_DWARF_DTPREL nios2_output_dwarf_dtprel
3192 #undef TARGET_PRINT_OPERAND
3193 #define TARGET_PRINT_OPERAND nios2_print_operand
3195 #undef TARGET_PRINT_OPERAND_ADDRESS
3196 #define TARGET_PRINT_OPERAND_ADDRESS nios2_print_operand_address
3198 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
3199 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA nios2_output_addr_const_extra
3201 #undef TARGET_OPTION_OVERRIDE
3202 #define TARGET_OPTION_OVERRIDE nios2_option_override
3204 #undef TARGET_OPTION_SAVE
3205 #define TARGET_OPTION_SAVE nios2_option_save
3207 #undef TARGET_OPTION_RESTORE
3208 #define TARGET_OPTION_RESTORE nios2_option_restore
3210 #undef TARGET_SET_CURRENT_FUNCTION
3211 #define TARGET_SET_CURRENT_FUNCTION nios2_set_current_function
3213 #undef TARGET_OPTION_VALID_ATTRIBUTE_P
3214 #define TARGET_OPTION_VALID_ATTRIBUTE_P nios2_valid_target_attribute_p
3216 #undef TARGET_OPTION_PRAGMA_PARSE
3217 #define TARGET_OPTION_PRAGMA_PARSE nios2_pragma_target_parse
3219 #undef TARGET_MERGE_DECL_ATTRIBUTES
3220 #define TARGET_MERGE_DECL_ATTRIBUTES nios2_merge_decl_attributes
3222 struct gcc_target targetm
= TARGET_INITIALIZER
;
3224 #include "gt-nios2.h"