1 /* Target machine subroutines for Altera Nios II.
2 Copyright (C) 2012-2015 Free Software Foundation, Inc.
3 Contributed by Jonah Graham (jgraham@altera.com),
4 Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@altera.com).
5 Contributed by Mentor Graphics, Inc.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published
11 by the Free Software Foundation; either version 3, or (at your
12 option) any later version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
25 #include "coretypes.h"
31 #include "double-int.h"
38 #include "fold-const.h"
40 #include "hard-reg-set.h"
41 #include "insn-config.h"
42 #include "conditions.h"
44 #include "insn-attr.h"
49 #include "statistics.h"
51 #include "fixed-value.h"
60 #include "insn-codes.h"
64 #include "dominance.h"
70 #include "cfgcleanup.h"
71 #include "basic-block.h"
72 #include "diagnostic-core.h"
75 #include "target-def.h"
77 #include "langhooks.h"
81 #include "stor-layout.h"
84 /* Forward function declarations. */
85 static bool prologue_saved_reg_p (unsigned);
86 static void nios2_load_pic_register (void);
87 static void nios2_register_custom_code (unsigned int, enum nios2_ccs_code
, int);
88 static const char *nios2_unspec_reloc_name (int);
89 static void nios2_register_builtin_fndecl (unsigned, tree
);
91 /* Threshold for data being put into the small data/bss area, instead
92 of the normal data area (references to the small data/bss area take
93 1 instruction, and use the global pointer, references to the normal
94 data area takes 2 instructions). */
95 unsigned HOST_WIDE_INT nios2_section_threshold
= NIOS2_DEFAULT_GVALUE
;
97 struct GTY (()) machine_function
99 /* Current frame information, to be filled in by nios2_compute_frame_layout
100 with register save masks, and offsets for the current function. */
102 /* Mask of registers to save. */
103 unsigned int save_mask
;
104 /* Number of bytes that the entire frame takes up. */
106 /* Number of bytes that variables take up. */
108 /* Number of bytes that outgoing arguments take up. */
110 /* Number of bytes needed to store registers in frame. */
112 /* Offset from new stack pointer to store registers. */
113 int save_regs_offset
;
114 /* Offset from save_regs_offset to store frame pointer register. */
116 /* != 0 if frame layout already calculated. */
120 /* State to track the assignment of custom codes to FPU/custom builtins. */
121 static enum nios2_ccs_code custom_code_status
[256];
122 static int custom_code_index
[256];
123 /* Set to true if any conflicts (re-use of a code between 0-255) are found. */
124 static bool custom_code_conflict
= false;
127 /* Definition of builtin function types for nios2. */
131 N2_FTYPE(1, (VOID)) \
132 N2_FTYPE(2, (DF, DF)) \
133 N2_FTYPE(3, (DF, DF, DF)) \
134 N2_FTYPE(2, (DF, SF)) \
135 N2_FTYPE(2, (DF, SI)) \
136 N2_FTYPE(2, (DF, UI)) \
137 N2_FTYPE(2, (SF, DF)) \
138 N2_FTYPE(2, (SF, SF)) \
139 N2_FTYPE(3, (SF, SF, SF)) \
140 N2_FTYPE(2, (SF, SI)) \
141 N2_FTYPE(2, (SF, UI)) \
142 N2_FTYPE(2, (SI, CVPTR)) \
143 N2_FTYPE(2, (SI, DF)) \
144 N2_FTYPE(3, (SI, DF, DF)) \
145 N2_FTYPE(2, (SI, SF)) \
146 N2_FTYPE(3, (SI, SF, SF)) \
147 N2_FTYPE(2, (SI, SI)) \
148 N2_FTYPE(2, (UI, CVPTR)) \
149 N2_FTYPE(2, (UI, DF)) \
150 N2_FTYPE(2, (UI, SF)) \
151 N2_FTYPE(2, (VOID, DF)) \
152 N2_FTYPE(2, (VOID, SF)) \
153 N2_FTYPE(3, (VOID, SI, SI)) \
154 N2_FTYPE(3, (VOID, VPTR, SI))
156 #define N2_FTYPE_OP1(R) N2_FTYPE_ ## R ## _VOID
157 #define N2_FTYPE_OP2(R, A1) N2_FTYPE_ ## R ## _ ## A1
158 #define N2_FTYPE_OP3(R, A1, A2) N2_FTYPE_ ## R ## _ ## A1 ## _ ## A2
160 /* Expand ftcode enumeration. */
162 #define N2_FTYPE(N,ARGS) N2_FTYPE_OP ## N ARGS,
168 /* Return the tree function type, based on the ftcode. */
170 nios2_ftype (enum nios2_ftcode ftcode
)
172 static tree types
[(int) N2_FTYPE_MAX
];
174 tree N2_TYPE_SF
= float_type_node
;
175 tree N2_TYPE_DF
= double_type_node
;
176 tree N2_TYPE_SI
= integer_type_node
;
177 tree N2_TYPE_UI
= unsigned_type_node
;
178 tree N2_TYPE_VOID
= void_type_node
;
180 static const_tree N2_TYPE_CVPTR
, N2_TYPE_VPTR
;
183 /* const volatile void *. */
185 = build_pointer_type (build_qualified_type (void_type_node
,
187 | TYPE_QUAL_VOLATILE
)));
188 /* volatile void *. */
190 = build_pointer_type (build_qualified_type (void_type_node
,
191 TYPE_QUAL_VOLATILE
));
193 if (types
[(int) ftcode
] == NULL_TREE
)
196 #define N2_FTYPE_ARGS1(R) N2_TYPE_ ## R
197 #define N2_FTYPE_ARGS2(R,A1) N2_TYPE_ ## R, N2_TYPE_ ## A1
198 #define N2_FTYPE_ARGS3(R,A1,A2) N2_TYPE_ ## R, N2_TYPE_ ## A1, N2_TYPE_ ## A2
199 #define N2_FTYPE(N,ARGS) \
200 case N2_FTYPE_OP ## N ARGS: \
201 types[(int) ftcode] \
202 = build_function_type_list (N2_FTYPE_ARGS ## N ARGS, NULL_TREE); \
206 default: gcc_unreachable ();
208 return types
[(int) ftcode
];
212 /* Definition of FPU instruction descriptions. */
214 struct nios2_fpu_insn_info
217 int num_operands
, *optvar
;
220 #define N2F_DFREQ 0x2
221 #define N2F_UNSAFE 0x4
222 #define N2F_FINITE 0x8
223 #define N2F_NO_ERRNO 0x10
225 enum insn_code icode
;
226 enum nios2_ftcode ftcode
;
229 /* Base macro for defining FPU instructions. */
230 #define N2FPU_INSN_DEF_BASE(insn, nop, flags, icode, args) \
231 { #insn, nop, &nios2_custom_ ## insn, OPT_mcustom_##insn##_, \
232 OPT_mno_custom_##insn, flags, CODE_FOR_ ## icode, \
233 N2_FTYPE_OP ## nop args }
235 /* Arithmetic and math functions; 2 or 3 operand FP operations. */
236 #define N2FPU_OP2(mode) (mode, mode)
237 #define N2FPU_OP3(mode) (mode, mode, mode)
238 #define N2FPU_INSN_DEF(code, icode, nop, flags, m, M) \
239 N2FPU_INSN_DEF_BASE (f ## code ## m, nop, flags, \
240 icode ## m ## f ## nop, N2FPU_OP ## nop (M ## F))
241 #define N2FPU_INSN_SF(code, nop, flags) \
242 N2FPU_INSN_DEF (code, code, nop, flags, s, S)
243 #define N2FPU_INSN_DF(code, nop, flags) \
244 N2FPU_INSN_DEF (code, code, nop, flags | N2F_DF, d, D)
246 /* Compare instructions, 3 operand FP operation with a SI result. */
247 #define N2FPU_CMP_DEF(code, flags, m, M) \
248 N2FPU_INSN_DEF_BASE (fcmp ## code ## m, 3, flags, \
249 nios2_s ## code ## m ## f, (SI, M ## F, M ## F))
250 #define N2FPU_CMP_SF(code) N2FPU_CMP_DEF (code, 0, s, S)
251 #define N2FPU_CMP_DF(code) N2FPU_CMP_DEF (code, N2F_DF, d, D)
253 /* The order of definition needs to be maintained consistent with
254 enum n2fpu_code in nios2-opts.h. */
255 struct nios2_fpu_insn_info nios2_fpu_insn
[] =
257 /* Single precision instructions. */
258 N2FPU_INSN_SF (add
, 3, 0),
259 N2FPU_INSN_SF (sub
, 3, 0),
260 N2FPU_INSN_SF (mul
, 3, 0),
261 N2FPU_INSN_SF (div
, 3, 0),
262 /* Due to textual difference between min/max and smin/smax. */
263 N2FPU_INSN_DEF (min
, smin
, 3, N2F_FINITE
, s
, S
),
264 N2FPU_INSN_DEF (max
, smax
, 3, N2F_FINITE
, s
, S
),
265 N2FPU_INSN_SF (neg
, 2, 0),
266 N2FPU_INSN_SF (abs
, 2, 0),
267 N2FPU_INSN_SF (sqrt
, 2, 0),
268 N2FPU_INSN_SF (sin
, 2, N2F_UNSAFE
),
269 N2FPU_INSN_SF (cos
, 2, N2F_UNSAFE
),
270 N2FPU_INSN_SF (tan
, 2, N2F_UNSAFE
),
271 N2FPU_INSN_SF (atan
, 2, N2F_UNSAFE
),
272 N2FPU_INSN_SF (exp
, 2, N2F_UNSAFE
),
273 N2FPU_INSN_SF (log
, 2, N2F_UNSAFE
),
274 /* Single precision compares. */
275 N2FPU_CMP_SF (eq
), N2FPU_CMP_SF (ne
),
276 N2FPU_CMP_SF (lt
), N2FPU_CMP_SF (le
),
277 N2FPU_CMP_SF (gt
), N2FPU_CMP_SF (ge
),
279 /* Double precision instructions. */
280 N2FPU_INSN_DF (add
, 3, 0),
281 N2FPU_INSN_DF (sub
, 3, 0),
282 N2FPU_INSN_DF (mul
, 3, 0),
283 N2FPU_INSN_DF (div
, 3, 0),
284 /* Due to textual difference between min/max and smin/smax. */
285 N2FPU_INSN_DEF (min
, smin
, 3, N2F_FINITE
, d
, D
),
286 N2FPU_INSN_DEF (max
, smax
, 3, N2F_FINITE
, d
, D
),
287 N2FPU_INSN_DF (neg
, 2, 0),
288 N2FPU_INSN_DF (abs
, 2, 0),
289 N2FPU_INSN_DF (sqrt
, 2, 0),
290 N2FPU_INSN_DF (sin
, 2, N2F_UNSAFE
),
291 N2FPU_INSN_DF (cos
, 2, N2F_UNSAFE
),
292 N2FPU_INSN_DF (tan
, 2, N2F_UNSAFE
),
293 N2FPU_INSN_DF (atan
, 2, N2F_UNSAFE
),
294 N2FPU_INSN_DF (exp
, 2, N2F_UNSAFE
),
295 N2FPU_INSN_DF (log
, 2, N2F_UNSAFE
),
296 /* Double precision compares. */
297 N2FPU_CMP_DF (eq
), N2FPU_CMP_DF (ne
),
298 N2FPU_CMP_DF (lt
), N2FPU_CMP_DF (le
),
299 N2FPU_CMP_DF (gt
), N2FPU_CMP_DF (ge
),
301 /* Conversion instructions. */
302 N2FPU_INSN_DEF_BASE (floatis
, 2, 0, floatsisf2
, (SF
, SI
)),
303 N2FPU_INSN_DEF_BASE (floatus
, 2, 0, floatunssisf2
, (SF
, UI
)),
304 N2FPU_INSN_DEF_BASE (floatid
, 2, 0, floatsidf2
, (DF
, SI
)),
305 N2FPU_INSN_DEF_BASE (floatud
, 2, 0, floatunssidf2
, (DF
, UI
)),
306 N2FPU_INSN_DEF_BASE (round
, 2, N2F_NO_ERRNO
, lroundsfsi2
, (SI
, SF
)),
307 N2FPU_INSN_DEF_BASE (fixsi
, 2, 0, fix_truncsfsi2
, (SI
, SF
)),
308 N2FPU_INSN_DEF_BASE (fixsu
, 2, 0, fixuns_truncsfsi2
, (UI
, SF
)),
309 N2FPU_INSN_DEF_BASE (fixdi
, 2, 0, fix_truncdfsi2
, (SI
, DF
)),
310 N2FPU_INSN_DEF_BASE (fixdu
, 2, 0, fixuns_truncdfsi2
, (UI
, DF
)),
311 N2FPU_INSN_DEF_BASE (fextsd
, 2, 0, extendsfdf2
, (DF
, SF
)),
312 N2FPU_INSN_DEF_BASE (ftruncds
, 2, 0, truncdfsf2
, (SF
, DF
)),
314 /* X, Y access instructions. */
315 N2FPU_INSN_DEF_BASE (fwrx
, 2, N2F_DFREQ
, nios2_fwrx
, (VOID
, DF
)),
316 N2FPU_INSN_DEF_BASE (fwry
, 2, N2F_DFREQ
, nios2_fwry
, (VOID
, SF
)),
317 N2FPU_INSN_DEF_BASE (frdxlo
, 1, N2F_DFREQ
, nios2_frdxlo
, (SF
)),
318 N2FPU_INSN_DEF_BASE (frdxhi
, 1, N2F_DFREQ
, nios2_frdxhi
, (SF
)),
319 N2FPU_INSN_DEF_BASE (frdy
, 1, N2F_DFREQ
, nios2_frdy
, (SF
))
322 /* Some macros for ease of access. */
323 #define N2FPU(code) nios2_fpu_insn[(int) code]
324 #define N2FPU_ENABLED_P(code) (N2FPU_N(code) >= 0)
325 #define N2FPU_N(code) (*N2FPU(code).optvar)
326 #define N2FPU_NAME(code) (N2FPU(code).name)
327 #define N2FPU_ICODE(code) (N2FPU(code).icode)
328 #define N2FPU_FTCODE(code) (N2FPU(code).ftcode)
329 #define N2FPU_FINITE_P(code) (N2FPU(code).flags & N2F_FINITE)
330 #define N2FPU_UNSAFE_P(code) (N2FPU(code).flags & N2F_UNSAFE)
331 #define N2FPU_NO_ERRNO_P(code) (N2FPU(code).flags & N2F_NO_ERRNO)
332 #define N2FPU_DOUBLE_P(code) (N2FPU(code).flags & N2F_DF)
333 #define N2FPU_DOUBLE_REQUIRED_P(code) (N2FPU(code).flags & N2F_DFREQ)
335 /* Same as above, but for cases where using only the op part is shorter. */
336 #define N2FPU_OP(op) N2FPU(n2fpu_ ## op)
337 #define N2FPU_OP_NAME(op) N2FPU_NAME(n2fpu_ ## op)
338 #define N2FPU_OP_ENABLED_P(op) N2FPU_ENABLED_P(n2fpu_ ## op)
340 /* Export the FPU insn enabled predicate to nios2.md. */
342 nios2_fpu_insn_enabled (enum n2fpu_code code
)
344 return N2FPU_ENABLED_P (code
);
347 /* Return true if COND comparison for mode MODE is enabled under current
351 nios2_fpu_compare_enabled (enum rtx_code cond
, machine_mode mode
)
356 case EQ
: return N2FPU_OP_ENABLED_P (fcmpeqs
);
357 case NE
: return N2FPU_OP_ENABLED_P (fcmpnes
);
358 case GT
: return N2FPU_OP_ENABLED_P (fcmpgts
);
359 case GE
: return N2FPU_OP_ENABLED_P (fcmpges
);
360 case LT
: return N2FPU_OP_ENABLED_P (fcmplts
);
361 case LE
: return N2FPU_OP_ENABLED_P (fcmples
);
364 else if (mode
== DFmode
)
367 case EQ
: return N2FPU_OP_ENABLED_P (fcmpeqd
);
368 case NE
: return N2FPU_OP_ENABLED_P (fcmpned
);
369 case GT
: return N2FPU_OP_ENABLED_P (fcmpgtd
);
370 case GE
: return N2FPU_OP_ENABLED_P (fcmpged
);
371 case LT
: return N2FPU_OP_ENABLED_P (fcmpltd
);
372 case LE
: return N2FPU_OP_ENABLED_P (fcmpled
);
378 /* Stack layout and calling conventions. */
380 #define NIOS2_STACK_ALIGN(LOC) \
381 (((LOC) + ((PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) - 1)) \
382 & ~((PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) - 1))
384 /* Return the bytes needed to compute the frame pointer from the current
387 nios2_compute_frame_layout (void)
390 unsigned int save_mask
= 0;
396 if (cfun
->machine
->initialized
)
397 return cfun
->machine
->total_size
;
399 var_size
= NIOS2_STACK_ALIGN (get_frame_size ());
400 out_args_size
= NIOS2_STACK_ALIGN (crtl
->outgoing_args_size
);
401 total_size
= var_size
+ out_args_size
;
403 /* Calculate space needed for gp registers. */
405 for (regno
= 0; regno
<= LAST_GP_REG
; regno
++)
406 if (prologue_saved_reg_p (regno
))
408 save_mask
|= 1 << regno
;
412 /* If we call eh_return, we need to save the EH data registers. */
413 if (crtl
->calls_eh_return
)
418 for (i
= 0; (r
= EH_RETURN_DATA_REGNO (i
)) != INVALID_REGNUM
; i
++)
419 if (!(save_mask
& (1 << r
)))
426 cfun
->machine
->fp_save_offset
= 0;
427 if (save_mask
& (1 << HARD_FRAME_POINTER_REGNUM
))
429 int fp_save_offset
= 0;
430 for (regno
= 0; regno
< HARD_FRAME_POINTER_REGNUM
; regno
++)
431 if (save_mask
& (1 << regno
))
434 cfun
->machine
->fp_save_offset
= fp_save_offset
;
437 save_reg_size
= NIOS2_STACK_ALIGN (save_reg_size
);
438 total_size
+= save_reg_size
;
439 total_size
+= NIOS2_STACK_ALIGN (crtl
->args
.pretend_args_size
);
441 /* Save other computed information. */
442 cfun
->machine
->save_mask
= save_mask
;
443 cfun
->machine
->total_size
= total_size
;
444 cfun
->machine
->var_size
= var_size
;
445 cfun
->machine
->args_size
= out_args_size
;
446 cfun
->machine
->save_reg_size
= save_reg_size
;
447 cfun
->machine
->initialized
= reload_completed
;
448 cfun
->machine
->save_regs_offset
= out_args_size
+ var_size
;
453 /* Generate save/restore of register REGNO at SP + OFFSET. Used by the
454 prologue/epilogue expand routines. */
456 save_reg (int regno
, unsigned offset
)
458 rtx reg
= gen_rtx_REG (SImode
, regno
);
459 rtx addr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
460 gen_int_mode (offset
, Pmode
));
461 rtx insn
= emit_move_insn (gen_frame_mem (Pmode
, addr
), reg
);
462 RTX_FRAME_RELATED_P (insn
) = 1;
466 restore_reg (int regno
, unsigned offset
)
468 rtx reg
= gen_rtx_REG (SImode
, regno
);
469 rtx addr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
470 gen_int_mode (offset
, Pmode
));
471 rtx insn
= emit_move_insn (reg
, gen_frame_mem (Pmode
, addr
));
472 /* Tag epilogue unwind note. */
473 add_reg_note (insn
, REG_CFA_RESTORE
, reg
);
474 RTX_FRAME_RELATED_P (insn
) = 1;
477 /* Emit conditional trap for checking stack limit. */
479 nios2_emit_stack_limit_check (void)
481 if (REG_P (stack_limit_rtx
))
482 emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode
, stack_pointer_rtx
,
484 stack_pointer_rtx
, stack_limit_rtx
, GEN_INT (3)));
486 sorry ("only register based stack limit is supported");
489 /* Temp regno used inside prologue/epilogue. */
490 #define TEMP_REG_NUM 8
493 nios2_expand_prologue (void)
496 int total_frame_size
, save_offset
;
497 int sp_offset
; /* offset from base_reg to final stack value. */
498 int save_regs_base
; /* offset from base_reg to register save area. */
501 total_frame_size
= nios2_compute_frame_layout ();
503 if (flag_stack_usage_info
)
504 current_function_static_stack_size
= total_frame_size
;
506 /* Decrement the stack pointer. */
507 if (!SMALL_INT (total_frame_size
))
509 /* We need an intermediary point, this will point at the spill block. */
511 (gen_add2_insn (stack_pointer_rtx
,
512 gen_int_mode (cfun
->machine
->save_regs_offset
513 - total_frame_size
, Pmode
)));
514 RTX_FRAME_RELATED_P (insn
) = 1;
516 sp_offset
= -cfun
->machine
->save_regs_offset
;
518 else if (total_frame_size
)
520 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
,
521 gen_int_mode (-total_frame_size
,
523 RTX_FRAME_RELATED_P (insn
) = 1;
524 save_regs_base
= cfun
->machine
->save_regs_offset
;
528 save_regs_base
= sp_offset
= 0;
530 if (crtl
->limit_stack
)
531 nios2_emit_stack_limit_check ();
533 save_offset
= save_regs_base
+ cfun
->machine
->save_reg_size
;
535 for (regno
= LAST_GP_REG
; regno
> 0; regno
--)
536 if (cfun
->machine
->save_mask
& (1 << regno
))
539 save_reg (regno
, save_offset
);
542 if (frame_pointer_needed
)
544 int fp_save_offset
= save_regs_base
+ cfun
->machine
->fp_save_offset
;
545 insn
= emit_insn (gen_add3_insn (hard_frame_pointer_rtx
,
547 gen_int_mode (fp_save_offset
, Pmode
)));
548 RTX_FRAME_RELATED_P (insn
) = 1;
554 = gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
555 plus_constant (Pmode
, stack_pointer_rtx
, sp_offset
));
556 if (SMALL_INT (sp_offset
))
557 insn
= emit_insn (sp_adjust
);
560 rtx tmp
= gen_rtx_REG (Pmode
, TEMP_REG_NUM
);
561 emit_move_insn (tmp
, gen_int_mode (sp_offset
, Pmode
));
562 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
, tmp
));
563 /* Attach the sp_adjust as a note indicating what happened. */
564 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
, sp_adjust
);
566 RTX_FRAME_RELATED_P (insn
) = 1;
568 if (crtl
->limit_stack
)
569 nios2_emit_stack_limit_check ();
572 /* Load the PIC register if needed. */
573 if (crtl
->uses_pic_offset_table
)
574 nios2_load_pic_register ();
576 /* If we are profiling, make sure no instructions are scheduled before
577 the call to mcount. */
579 emit_insn (gen_blockage ());
583 nios2_expand_epilogue (bool sibcall_p
)
586 int total_frame_size
;
587 int sp_adjust
, save_offset
;
590 if (!sibcall_p
&& nios2_can_use_return_insn ())
592 emit_jump_insn (gen_return ());
596 emit_insn (gen_blockage ());
598 total_frame_size
= nios2_compute_frame_layout ();
599 if (frame_pointer_needed
)
601 /* Recover the stack pointer. */
602 insn
= emit_insn (gen_add3_insn
603 (stack_pointer_rtx
, hard_frame_pointer_rtx
,
604 gen_int_mode (-cfun
->machine
->fp_save_offset
, Pmode
)));
605 cfa_adj
= plus_constant (Pmode
, stack_pointer_rtx
,
607 - cfun
->machine
->save_regs_offset
));
608 add_reg_note (insn
, REG_CFA_DEF_CFA
, cfa_adj
);
609 RTX_FRAME_RELATED_P (insn
) = 1;
612 sp_adjust
= total_frame_size
- cfun
->machine
->save_regs_offset
;
614 else if (!SMALL_INT (total_frame_size
))
616 rtx tmp
= gen_rtx_REG (Pmode
, TEMP_REG_NUM
);
617 emit_move_insn (tmp
, gen_int_mode (cfun
->machine
->save_regs_offset
,
619 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
, tmp
));
620 cfa_adj
= gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
621 plus_constant (Pmode
, stack_pointer_rtx
,
622 cfun
->machine
->save_regs_offset
));
623 add_reg_note (insn
, REG_CFA_ADJUST_CFA
, cfa_adj
);
624 RTX_FRAME_RELATED_P (insn
) = 1;
626 sp_adjust
= total_frame_size
- cfun
->machine
->save_regs_offset
;
630 save_offset
= cfun
->machine
->save_regs_offset
;
631 sp_adjust
= total_frame_size
;
634 save_offset
+= cfun
->machine
->save_reg_size
;
636 for (regno
= LAST_GP_REG
; regno
> 0; regno
--)
637 if (cfun
->machine
->save_mask
& (1 << regno
))
640 restore_reg (regno
, save_offset
);
645 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
,
646 gen_int_mode (sp_adjust
, Pmode
)));
647 cfa_adj
= gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
648 plus_constant (Pmode
, stack_pointer_rtx
,
650 add_reg_note (insn
, REG_CFA_ADJUST_CFA
, cfa_adj
);
651 RTX_FRAME_RELATED_P (insn
) = 1;
654 /* Add in the __builtin_eh_return stack adjustment. */
655 if (crtl
->calls_eh_return
)
656 emit_insn (gen_add2_insn (stack_pointer_rtx
, EH_RETURN_STACKADJ_RTX
));
659 emit_jump_insn (gen_simple_return ());
662 /* Implement RETURN_ADDR_RTX. Note, we do not support moving
663 back to a previous frame. */
665 nios2_get_return_address (int count
)
670 return get_hard_reg_initial_val (Pmode
, RA_REGNO
);
673 /* Emit code to change the current function's return address to
674 ADDRESS. SCRATCH is available as a scratch register, if needed.
675 ADDRESS and SCRATCH are both word-mode GPRs. */
677 nios2_set_return_address (rtx address
, rtx scratch
)
679 nios2_compute_frame_layout ();
680 if (cfun
->machine
->save_mask
& (1 << RA_REGNO
))
682 unsigned offset
= cfun
->machine
->save_reg_size
- 4;
685 if (frame_pointer_needed
)
686 base
= hard_frame_pointer_rtx
;
689 base
= stack_pointer_rtx
;
690 offset
+= cfun
->machine
->save_regs_offset
;
692 if (!SMALL_INT (offset
))
694 emit_move_insn (scratch
, gen_int_mode (offset
, Pmode
));
695 emit_insn (gen_add2_insn (scratch
, base
));
701 base
= plus_constant (Pmode
, base
, offset
);
702 emit_move_insn (gen_rtx_MEM (Pmode
, base
), address
);
705 emit_move_insn (gen_rtx_REG (Pmode
, RA_REGNO
), address
);
708 /* Implement FUNCTION_PROFILER macro. */
710 nios2_function_profiler (FILE *file
, int labelno ATTRIBUTE_UNUSED
)
712 fprintf (file
, "\tmov\tr8, ra\n");
715 fprintf (file
, "\tnextpc\tr2\n");
716 fprintf (file
, "\t1: movhi\tr3, %%hiadj(_gp_got - 1b)\n");
717 fprintf (file
, "\taddi\tr3, r3, %%lo(_gp_got - 1b)\n");
718 fprintf (file
, "\tadd\tr2, r2, r3\n");
719 fprintf (file
, "\tldw\tr2, %%call(_mcount)(r2)\n");
720 fprintf (file
, "\tcallr\tr2\n");
722 else if (flag_pic
== 2)
724 fprintf (file
, "\tnextpc\tr2\n");
725 fprintf (file
, "\t1: movhi\tr3, %%hiadj(_gp_got - 1b)\n");
726 fprintf (file
, "\taddi\tr3, r3, %%lo(_gp_got - 1b)\n");
727 fprintf (file
, "\tadd\tr2, r2, r3\n");
728 fprintf (file
, "\tmovhi\tr3, %%call_hiadj(_mcount)\n");
729 fprintf (file
, "\taddi\tr3, r3, %%call_lo(_mcount)\n");
730 fprintf (file
, "\tadd\tr3, r2, r3\n");
731 fprintf (file
, "\tldw\tr2, 0(r3)\n");
732 fprintf (file
, "\tcallr\tr2\n");
735 fprintf (file
, "\tcall\t_mcount\n");
736 fprintf (file
, "\tmov\tra, r8\n");
739 /* Dump stack layout. */
741 nios2_dump_frame_layout (FILE *file
)
743 fprintf (file
, "\t%s Current Frame Info\n", ASM_COMMENT_START
);
744 fprintf (file
, "\t%s total_size = %d\n", ASM_COMMENT_START
,
745 cfun
->machine
->total_size
);
746 fprintf (file
, "\t%s var_size = %d\n", ASM_COMMENT_START
,
747 cfun
->machine
->var_size
);
748 fprintf (file
, "\t%s args_size = %d\n", ASM_COMMENT_START
,
749 cfun
->machine
->args_size
);
750 fprintf (file
, "\t%s save_reg_size = %d\n", ASM_COMMENT_START
,
751 cfun
->machine
->save_reg_size
);
752 fprintf (file
, "\t%s initialized = %d\n", ASM_COMMENT_START
,
753 cfun
->machine
->initialized
);
754 fprintf (file
, "\t%s save_regs_offset = %d\n", ASM_COMMENT_START
,
755 cfun
->machine
->save_regs_offset
);
756 fprintf (file
, "\t%s is_leaf = %d\n", ASM_COMMENT_START
,
758 fprintf (file
, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START
,
759 frame_pointer_needed
);
760 fprintf (file
, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START
,
761 crtl
->args
.pretend_args_size
);
764 /* Return true if REGNO should be saved in the prologue. */
766 prologue_saved_reg_p (unsigned regno
)
768 gcc_assert (GP_REG_P (regno
));
770 if (df_regs_ever_live_p (regno
) && !call_used_regs
[regno
])
773 if (regno
== HARD_FRAME_POINTER_REGNUM
&& frame_pointer_needed
)
776 if (regno
== PIC_OFFSET_TABLE_REGNUM
&& crtl
->uses_pic_offset_table
)
779 if (regno
== RA_REGNO
&& df_regs_ever_live_p (RA_REGNO
))
785 /* Implement TARGET_CAN_ELIMINATE. */
787 nios2_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
789 if (to
== STACK_POINTER_REGNUM
)
790 return !frame_pointer_needed
;
794 /* Implement INITIAL_ELIMINATION_OFFSET macro. */
796 nios2_initial_elimination_offset (int from
, int to
)
800 nios2_compute_frame_layout ();
802 /* Set OFFSET to the offset from the stack pointer. */
805 case FRAME_POINTER_REGNUM
:
806 offset
= cfun
->machine
->args_size
;
809 case ARG_POINTER_REGNUM
:
810 offset
= cfun
->machine
->total_size
;
811 offset
-= crtl
->args
.pretend_args_size
;
818 /* If we are asked for the frame pointer offset, then adjust OFFSET
819 by the offset from the frame pointer to the stack pointer. */
820 if (to
== HARD_FRAME_POINTER_REGNUM
)
821 offset
-= (cfun
->machine
->save_regs_offset
822 + cfun
->machine
->fp_save_offset
);
827 /* Return nonzero if this function is known to have a null epilogue.
828 This allows the optimizer to omit jumps to jumps if no stack
831 nios2_can_use_return_insn (void)
833 if (!reload_completed
|| crtl
->profile
)
836 return nios2_compute_frame_layout () == 0;
840 /* Check and signal some warnings/errors on FPU insn options. */
842 nios2_custom_check_insns (void)
847 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
848 if (N2FPU_ENABLED_P (i
) && N2FPU_DOUBLE_P (i
))
850 for (j
= 0; j
< ARRAY_SIZE (nios2_fpu_insn
); j
++)
851 if (N2FPU_DOUBLE_REQUIRED_P (j
) && ! N2FPU_ENABLED_P (j
))
853 error ("switch %<-mcustom-%s%> is required for double "
854 "precision floating point", N2FPU_NAME (j
));
860 /* Warn if the user has certain exotic operations that won't get used
861 without -funsafe-math-optimizations. See expand_builtin () in
863 if (!flag_unsafe_math_optimizations
)
864 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
865 if (N2FPU_ENABLED_P (i
) && N2FPU_UNSAFE_P (i
))
866 warning (0, "switch %<-mcustom-%s%> has no effect unless "
867 "-funsafe-math-optimizations is specified", N2FPU_NAME (i
));
869 /* Warn if the user is trying to use -mcustom-fmins et. al, that won't
870 get used without -ffinite-math-only. See fold_builtin_fmin_fmax ()
872 if (!flag_finite_math_only
)
873 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
874 if (N2FPU_ENABLED_P (i
) && N2FPU_FINITE_P (i
))
875 warning (0, "switch %<-mcustom-%s%> has no effect unless "
876 "-ffinite-math-only is specified", N2FPU_NAME (i
));
878 /* Warn if the user is trying to use a custom rounding instruction
879 that won't get used without -fno-math-errno. See
880 expand_builtin_int_roundingfn_2 () in builtins.c. */
882 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
883 if (N2FPU_ENABLED_P (i
) && N2FPU_NO_ERRNO_P (i
))
884 warning (0, "switch %<-mcustom-%s%> has no effect unless "
885 "-fno-math-errno is specified", N2FPU_NAME (i
));
887 if (errors
|| custom_code_conflict
)
888 fatal_error (input_location
,
889 "conflicting use of -mcustom switches, target attributes, "
890 "and/or __builtin_custom_ functions");
894 nios2_set_fpu_custom_code (enum n2fpu_code code
, int n
, bool override_p
)
896 if (override_p
|| N2FPU_N (code
) == -1)
898 nios2_register_custom_code (n
, CCS_FPU
, (int) code
);
901 /* Type to represent a standard FPU config. */
902 struct nios2_fpu_config
905 bool set_sp_constants
;
906 int code
[n2fpu_code_num
];
909 #define NIOS2_FPU_CONFIG_NUM 3
910 static struct nios2_fpu_config custom_fpu_config
[NIOS2_FPU_CONFIG_NUM
];
913 nios2_init_fpu_configs (void)
915 struct nios2_fpu_config
* cfg
;
917 #define NEXT_FPU_CONFIG \
919 cfg = &custom_fpu_config[i++]; \
920 memset (cfg, -1, sizeof (struct nios2_fpu_config));\
925 cfg
->set_sp_constants
= true;
926 cfg
->code
[n2fpu_fmuls
] = 252;
927 cfg
->code
[n2fpu_fadds
] = 253;
928 cfg
->code
[n2fpu_fsubs
] = 254;
932 cfg
->set_sp_constants
= true;
933 cfg
->code
[n2fpu_fmuls
] = 252;
934 cfg
->code
[n2fpu_fadds
] = 253;
935 cfg
->code
[n2fpu_fsubs
] = 254;
936 cfg
->code
[n2fpu_fdivs
] = 255;
940 cfg
->set_sp_constants
= true;
941 cfg
->code
[n2fpu_floatus
] = 243;
942 cfg
->code
[n2fpu_fixsi
] = 244;
943 cfg
->code
[n2fpu_floatis
] = 245;
944 cfg
->code
[n2fpu_fcmpgts
] = 246;
945 cfg
->code
[n2fpu_fcmples
] = 249;
946 cfg
->code
[n2fpu_fcmpeqs
] = 250;
947 cfg
->code
[n2fpu_fcmpnes
] = 251;
948 cfg
->code
[n2fpu_fmuls
] = 252;
949 cfg
->code
[n2fpu_fadds
] = 253;
950 cfg
->code
[n2fpu_fsubs
] = 254;
951 cfg
->code
[n2fpu_fdivs
] = 255;
953 #undef NEXT_FPU_CONFIG
954 gcc_assert (i
== NIOS2_FPU_CONFIG_NUM
);
957 static struct nios2_fpu_config
*
958 nios2_match_custom_fpu_cfg (const char *cfgname
, const char *endp
)
961 for (i
= 0; i
< NIOS2_FPU_CONFIG_NUM
; i
++)
963 bool match
= !(endp
!= NULL
964 ? strncmp (custom_fpu_config
[i
].name
, cfgname
,
966 : strcmp (custom_fpu_config
[i
].name
, cfgname
));
968 return &custom_fpu_config
[i
];
973 /* Use CFGNAME to lookup FPU config, ENDP if not NULL marks end of string.
974 OVERRIDE is true if loaded config codes should overwrite current state. */
976 nios2_handle_custom_fpu_cfg (const char *cfgname
, const char *endp
,
979 struct nios2_fpu_config
*cfg
= nios2_match_custom_fpu_cfg (cfgname
, endp
);
983 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
984 if (cfg
->code
[i
] >= 0)
985 nios2_set_fpu_custom_code ((enum n2fpu_code
) i
, cfg
->code
[i
],
987 if (cfg
->set_sp_constants
)
988 flag_single_precision_constant
= 1;
991 warning (0, "ignoring unrecognized switch %<-mcustom-fpu-cfg%> "
992 "value %<%s%>", cfgname
);
994 /* Guard against errors in the standard configurations. */
995 nios2_custom_check_insns ();
998 /* Check individual FPU insn options, and register custom code. */
1000 nios2_handle_custom_fpu_insn_option (int fpu_insn_index
)
1002 int param
= N2FPU_N (fpu_insn_index
);
1004 if (0 <= param
&& param
<= 255)
1005 nios2_register_custom_code (param
, CCS_FPU
, fpu_insn_index
);
1007 /* Valid values are 0-255, but also allow -1 so that the
1008 -mno-custom-<opt> switches work. */
1009 else if (param
!= -1)
1010 error ("switch %<-mcustom-%s%> value %d must be between 0 and 255",
1011 N2FPU_NAME (fpu_insn_index
), param
);
1014 /* Allocate a chunk of memory for per-function machine-dependent data. */
1015 static struct machine_function
*
1016 nios2_init_machine_status (void)
1018 return ggc_cleared_alloc
<machine_function
> ();
1021 /* Implement TARGET_OPTION_OVERRIDE. */
1023 nios2_option_override (void)
1027 #ifdef SUBTARGET_OVERRIDE_OPTIONS
1028 SUBTARGET_OVERRIDE_OPTIONS
;
1031 /* Check for unsupported options. */
1032 if (flag_pic
&& !TARGET_LINUX_ABI
)
1033 sorry ("position-independent code requires the Linux ABI");
1035 /* Function to allocate machine-dependent function status. */
1036 init_machine_status
= &nios2_init_machine_status
;
1038 nios2_section_threshold
1039 = (global_options_set
.x_g_switch_value
1040 ? g_switch_value
: NIOS2_DEFAULT_GVALUE
);
1042 if (nios2_gpopt_option
== gpopt_unspecified
)
1044 /* Default to -mgpopt unless -fpic or -fPIC. */
1046 nios2_gpopt_option
= gpopt_none
;
1048 nios2_gpopt_option
= gpopt_local
;
1051 /* If we don't have mul, we don't have mulx either! */
1052 if (!TARGET_HAS_MUL
&& TARGET_HAS_MULX
)
1053 target_flags
&= ~MASK_HAS_MULX
;
1055 /* Initialize default FPU configurations. */
1056 nios2_init_fpu_configs ();
1058 /* Set up default handling for floating point custom instructions.
1060 Putting things in this order means that the -mcustom-fpu-cfg=
1061 switch will always be overridden by individual -mcustom-fadds=
1062 switches, regardless of the order in which they were specified
1063 on the command line.
1065 This behavior of prioritization of individual -mcustom-<insn>=
1066 options before the -mcustom-fpu-cfg= switch is maintained for
1068 if (nios2_custom_fpu_cfg_string
&& *nios2_custom_fpu_cfg_string
)
1069 nios2_handle_custom_fpu_cfg (nios2_custom_fpu_cfg_string
, NULL
, false);
1071 /* Handle options for individual FPU insns. */
1072 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
1073 nios2_handle_custom_fpu_insn_option (i
);
1075 nios2_custom_check_insns ();
1077 /* Save the initial options in case the user does function specific
1079 target_option_default_node
= target_option_current_node
1080 = build_target_option_node (&global_options
);
1084 /* Return true if CST is a constant within range of movi/movui/movhi. */
1086 nios2_simple_const_p (const_rtx cst
)
1088 HOST_WIDE_INT val
= INTVAL (cst
);
1089 return SMALL_INT (val
) || SMALL_INT_UNSIGNED (val
) || UPPER16_INT (val
);
1092 /* Compute a (partial) cost for rtx X. Return true if the complete
1093 cost has been computed, and false if subexpressions should be
1094 scanned. In either case, *TOTAL contains the cost result. */
1096 nios2_rtx_costs (rtx x
, int code
, int outer_code ATTRIBUTE_UNUSED
,
1097 int opno ATTRIBUTE_UNUSED
,
1098 int *total
, bool speed ATTRIBUTE_UNUSED
)
1103 if (INTVAL (x
) == 0)
1105 *total
= COSTS_N_INSNS (0);
1108 else if (nios2_simple_const_p (x
))
1110 *total
= COSTS_N_INSNS (2);
1115 *total
= COSTS_N_INSNS (4);
1124 *total
= COSTS_N_INSNS (4);
1130 /* Recognize 'nor' insn pattern. */
1131 if (GET_CODE (XEXP (x
, 0)) == NOT
1132 && GET_CODE (XEXP (x
, 1)) == NOT
)
1134 *total
= COSTS_N_INSNS (1);
1142 *total
= COSTS_N_INSNS (1);
1147 *total
= COSTS_N_INSNS (3);
1152 *total
= COSTS_N_INSNS (1);
1161 /* Implement TARGET_PREFERRED_RELOAD_CLASS. */
1163 nios2_preferred_reload_class (rtx x ATTRIBUTE_UNUSED
, reg_class_t regclass
)
1165 return regclass
== NO_REGS
? GENERAL_REGS
: regclass
;
1168 /* Emit a call to __tls_get_addr. TI is the argument to this function.
1169 RET is an RTX for the return value location. The entire insn sequence
1171 static GTY(()) rtx nios2_tls_symbol
;
1174 nios2_call_tls_get_addr (rtx ti
)
1176 rtx arg
= gen_rtx_REG (Pmode
, FIRST_ARG_REGNO
);
1177 rtx ret
= gen_rtx_REG (Pmode
, FIRST_RETVAL_REGNO
);
1180 if (!nios2_tls_symbol
)
1181 nios2_tls_symbol
= init_one_libfunc ("__tls_get_addr");
1183 emit_move_insn (arg
, ti
);
1184 fn
= gen_rtx_MEM (QImode
, nios2_tls_symbol
);
1185 insn
= emit_call_insn (gen_call_value (ret
, fn
, const0_rtx
));
1186 RTL_CONST_CALL_P (insn
) = 1;
1187 use_reg (&CALL_INSN_FUNCTION_USAGE (insn
), ret
);
1188 use_reg (&CALL_INSN_FUNCTION_USAGE (insn
), arg
);
1193 /* Return true for large offsets requiring hiadj/lo relocation pairs. */
1195 nios2_large_offset_p (int unspec
)
1197 gcc_assert (nios2_unspec_reloc_name (unspec
) != NULL
);
1200 /* FIXME: TLS GOT offset relocations will eventually also get this
1201 treatment, after binutils support for those are also completed. */
1202 && (unspec
== UNSPEC_PIC_SYM
|| unspec
== UNSPEC_PIC_CALL_SYM
))
1205 /* 'gotoff' offsets are always hiadj/lo. */
1206 if (unspec
== UNSPEC_PIC_GOTOFF_SYM
)
1212 /* Return true for conforming unspec relocations. Also used in
1213 constraints.md and predicates.md. */
1215 nios2_unspec_reloc_p (rtx op
)
1217 return (GET_CODE (op
) == CONST
1218 && GET_CODE (XEXP (op
, 0)) == UNSPEC
1219 && ! nios2_large_offset_p (XINT (XEXP (op
, 0), 1)));
1222 /* Helper to generate unspec constant. */
1224 nios2_unspec_offset (rtx loc
, int unspec
)
1226 return gen_rtx_CONST (Pmode
, gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, loc
),
1230 /* Generate GOT pointer based address with large offset. */
1232 nios2_large_got_address (rtx offset
)
1234 rtx addr
= gen_reg_rtx (Pmode
);
1235 emit_insn (gen_add3_insn (addr
, pic_offset_table_rtx
,
1236 force_reg (Pmode
, offset
)));
1240 /* Generate a GOT pointer based address. */
1242 nios2_got_address (rtx loc
, int unspec
)
1244 rtx offset
= nios2_unspec_offset (loc
, unspec
);
1245 crtl
->uses_pic_offset_table
= 1;
1247 if (nios2_large_offset_p (unspec
))
1248 return nios2_large_got_address (offset
);
1250 return gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, offset
);
1253 /* Generate the code to access LOC, a thread local SYMBOL_REF. The
1254 return value will be a valid address and move_operand (either a REG
1257 nios2_legitimize_tls_address (rtx loc
)
1260 enum tls_model model
= SYMBOL_REF_TLS_MODEL (loc
);
1264 case TLS_MODEL_GLOBAL_DYNAMIC
:
1265 tmp
= gen_reg_rtx (Pmode
);
1266 emit_move_insn (tmp
, nios2_got_address (loc
, UNSPEC_ADD_TLS_GD
));
1267 return nios2_call_tls_get_addr (tmp
);
1269 case TLS_MODEL_LOCAL_DYNAMIC
:
1270 tmp
= gen_reg_rtx (Pmode
);
1271 emit_move_insn (tmp
, nios2_got_address (loc
, UNSPEC_ADD_TLS_LDM
));
1272 return gen_rtx_PLUS (Pmode
, nios2_call_tls_get_addr (tmp
),
1273 nios2_unspec_offset (loc
, UNSPEC_ADD_TLS_LDO
));
1275 case TLS_MODEL_INITIAL_EXEC
:
1276 tmp
= gen_reg_rtx (Pmode
);
1277 mem
= gen_const_mem (Pmode
, nios2_got_address (loc
, UNSPEC_LOAD_TLS_IE
));
1278 emit_move_insn (tmp
, mem
);
1279 tp
= gen_rtx_REG (Pmode
, TP_REGNO
);
1280 return gen_rtx_PLUS (Pmode
, tp
, tmp
);
1282 case TLS_MODEL_LOCAL_EXEC
:
1283 tp
= gen_rtx_REG (Pmode
, TP_REGNO
);
1284 return gen_rtx_PLUS (Pmode
, tp
,
1285 nios2_unspec_offset (loc
, UNSPEC_ADD_TLS_LE
));
1293 If -O3 is used, we want to output a table lookup for
1294 divides between small numbers (both num and den >= 0
1295 and < 0x10). The overhead of this method in the worst
1296 case is 40 bytes in the text section (10 insns) and
1297 256 bytes in the data section. Additional divides do
1298 not incur additional penalties in the data section.
1300 Code speed is improved for small divides by about 5x
1301 when using this method in the worse case (~9 cycles
1302 vs ~45). And in the worst case divides not within the
1303 table are penalized by about 10% (~5 cycles vs ~45).
1304 However in the typical case the penalty is not as bad
1305 because doing the long divide in only 45 cycles is
1308 ??? would be nice to have some benchmarks other
1309 than Dhrystone to back this up.
1311 This bit of expansion is to create this instruction
1318 add $12, $11, divide_table
1324 # continue here with result in $2
1326 ??? Ideally I would like the libcall block to contain all
1327 of this code, but I don't know how to do that. What it
1328 means is that if the divide can be eliminated, it may not
1329 completely disappear.
1331 ??? The __divsi3_table label should ideally be moved out
1332 of this block and into a global. If it is placed into the
1333 sdata section we can save even more cycles by doing things
1336 nios2_emit_expensive_div (rtx
*operands
, machine_mode mode
)
1338 rtx or_result
, shift_left_result
;
1340 rtx_code_label
*lab1
, *lab3
;
1347 /* It may look a little generic, but only SImode is supported for now. */
1348 gcc_assert (mode
== SImode
);
1349 libfunc
= optab_libfunc (sdiv_optab
, SImode
);
1351 lab1
= gen_label_rtx ();
1352 lab3
= gen_label_rtx ();
1354 or_result
= expand_simple_binop (SImode
, IOR
,
1355 operands
[1], operands
[2],
1356 0, 0, OPTAB_LIB_WIDEN
);
1358 emit_cmp_and_jump_insns (or_result
, GEN_INT (15), GTU
, 0,
1359 GET_MODE (or_result
), 0, lab3
);
1360 JUMP_LABEL (get_last_insn ()) = lab3
;
1362 shift_left_result
= expand_simple_binop (SImode
, ASHIFT
,
1363 operands
[1], GEN_INT (4),
1364 0, 0, OPTAB_LIB_WIDEN
);
1366 lookup_value
= expand_simple_binop (SImode
, IOR
,
1367 shift_left_result
, operands
[2],
1368 0, 0, OPTAB_LIB_WIDEN
);
1369 table
= gen_rtx_PLUS (SImode
, lookup_value
,
1370 gen_rtx_SYMBOL_REF (SImode
, "__divsi3_table"));
1371 convert_move (operands
[0], gen_rtx_MEM (QImode
, table
), 1);
1373 tmp
= emit_jump_insn (gen_jump (lab1
));
1374 JUMP_LABEL (tmp
) = lab1
;
1378 LABEL_NUSES (lab3
) = 1;
1381 final_result
= emit_library_call_value (libfunc
, NULL_RTX
,
1382 LCT_CONST
, SImode
, 2,
1383 operands
[1], SImode
,
1384 operands
[2], SImode
);
1386 insns
= get_insns ();
1388 emit_libcall_block (insns
, operands
[0], final_result
,
1389 gen_rtx_DIV (SImode
, operands
[1], operands
[2]));
1392 LABEL_NUSES (lab1
) = 1;
1396 /* Branches and compares. */
1398 /* Return in *ALT_CODE and *ALT_OP, an alternate equivalent constant
1399 comparison, e.g. >= 1 into > 0. */
1401 nios2_alternate_compare_const (enum rtx_code code
, rtx op
,
1402 enum rtx_code
*alt_code
, rtx
*alt_op
,
1405 HOST_WIDE_INT opval
= INTVAL (op
);
1406 enum rtx_code scode
= signed_condition (code
);
1407 bool dec_p
= (scode
== LT
|| scode
== GE
);
1409 if (code
== EQ
|| code
== NE
)
1417 ? gen_int_mode (opval
- 1, mode
)
1418 : gen_int_mode (opval
+ 1, mode
));
1420 /* The required conversion between [>,>=] and [<,<=] is captured
1421 by a reverse + swap of condition codes. */
1422 *alt_code
= reverse_condition (swap_condition (code
));
1425 /* Test if the incremented/decremented value crosses the over/underflow
1426 boundary. Supposedly, such boundary cases should already be transformed
1427 into always-true/false or EQ conditions, so use an assertion here. */
1428 unsigned HOST_WIDE_INT alt_opval
= INTVAL (*alt_op
);
1430 alt_opval
^= (1 << (GET_MODE_BITSIZE (mode
) - 1));
1431 alt_opval
&= GET_MODE_MASK (mode
);
1432 gcc_assert (dec_p
? alt_opval
!= GET_MODE_MASK (mode
) : alt_opval
!= 0);
1436 /* Return true if the constant comparison is supported by nios2. */
1438 nios2_valid_compare_const_p (enum rtx_code code
, rtx op
)
1442 case EQ
: case NE
: case GE
: case LT
:
1443 return SMALL_INT (INTVAL (op
));
1445 return SMALL_INT_UNSIGNED (INTVAL (op
));
1451 /* Checks if the FPU comparison in *CMP, *OP1, and *OP2 can be supported in
1452 the current configuration. Perform modifications if MODIFY_P is true.
1453 Returns true if FPU compare can be done. */
1456 nios2_validate_fpu_compare (machine_mode mode
, rtx
*cmp
, rtx
*op1
, rtx
*op2
,
1460 enum rtx_code code
= GET_CODE (*cmp
);
1462 if (!nios2_fpu_compare_enabled (code
, mode
))
1464 code
= swap_condition (code
);
1465 if (nios2_fpu_compare_enabled (code
, mode
))
1479 *op1
= force_reg (mode
, *op1
);
1480 *op2
= force_reg (mode
, *op2
);
1481 *cmp
= gen_rtx_fmt_ee (code
, mode
, *op1
, *op2
);
1486 /* Checks and modifies the comparison in *CMP, *OP1, and *OP2 into valid
1487 nios2 supported form. Returns true if success. */
1489 nios2_validate_compare (machine_mode mode
, rtx
*cmp
, rtx
*op1
, rtx
*op2
)
1491 enum rtx_code code
= GET_CODE (*cmp
);
1492 enum rtx_code alt_code
;
1495 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
)
1496 return nios2_validate_fpu_compare (mode
, cmp
, op1
, op2
, true);
1498 if (!reg_or_0_operand (*op2
, mode
))
1500 /* Create alternate constant compare. */
1501 nios2_alternate_compare_const (code
, *op2
, &alt_code
, &alt_op2
, mode
);
1503 /* If alterate op2 is zero(0), we can use it directly, possibly
1504 swapping the compare code. */
1505 if (alt_op2
== const0_rtx
)
1509 goto check_rebuild_cmp
;
1512 /* Check if either constant compare can be used. */
1513 if (nios2_valid_compare_const_p (code
, *op2
))
1515 else if (nios2_valid_compare_const_p (alt_code
, alt_op2
))
1522 /* We have to force op2 into a register now. Try to pick one
1523 with a lower cost. */
1524 if (! nios2_simple_const_p (*op2
)
1525 && nios2_simple_const_p (alt_op2
))
1530 *op2
= force_reg (SImode
, *op2
);
1533 if (code
== GT
|| code
== GTU
|| code
== LE
|| code
== LEU
)
1535 rtx t
= *op1
; *op1
= *op2
; *op2
= t
;
1536 code
= swap_condition (code
);
1539 *cmp
= gen_rtx_fmt_ee (code
, mode
, *op1
, *op2
);
1544 /* Addressing Modes. */
1546 /* Implement TARGET_LEGITIMATE_CONSTANT_P. */
1548 nios2_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED
, rtx x
)
1551 split_const (x
, &base
, &offset
);
1552 return GET_CODE (base
) != SYMBOL_REF
|| !SYMBOL_REF_TLS_MODEL (base
);
1555 /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
1557 nios2_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED
, rtx x
)
1559 return nios2_legitimate_constant_p (mode
, x
) == false;
1562 /* Return true if register REGNO is a valid base register.
1563 STRICT_P is true if REG_OK_STRICT is in effect. */
1566 nios2_regno_ok_for_base_p (int regno
, bool strict_p
)
1568 if (!HARD_REGISTER_NUM_P (regno
))
1576 regno
= reg_renumber
[regno
];
1579 /* The fake registers will be eliminated to either the stack or
1580 hard frame pointer, both of which are usually valid base registers.
1581 Reload deals with the cases where the eliminated form isn't valid. */
1582 return (GP_REG_P (regno
)
1583 || regno
== FRAME_POINTER_REGNUM
1584 || regno
== ARG_POINTER_REGNUM
);
1587 /* Return true if the address expression formed by BASE + OFFSET is
1590 nios2_valid_addr_expr_p (rtx base
, rtx offset
, bool strict_p
)
1592 if (!strict_p
&& GET_CODE (base
) == SUBREG
)
1593 base
= SUBREG_REG (base
);
1594 return (REG_P (base
)
1595 && nios2_regno_ok_for_base_p (REGNO (base
), strict_p
)
1596 && (offset
== NULL_RTX
1597 || const_arith_operand (offset
, Pmode
)
1598 || nios2_unspec_reloc_p (offset
)));
1601 /* Implement TARGET_LEGITIMATE_ADDRESS_P. */
1603 nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
1604 rtx operand
, bool strict_p
)
1606 switch (GET_CODE (operand
))
1610 if (SYMBOL_REF_TLS_MODEL (operand
))
1613 if (nios2_symbol_ref_in_small_data_p (operand
))
1616 /* Else, fall through. */
1623 /* Register indirect. */
1625 return nios2_regno_ok_for_base_p (REGNO (operand
), strict_p
);
1627 /* Register indirect with displacement. */
1630 rtx op0
= XEXP (operand
, 0);
1631 rtx op1
= XEXP (operand
, 1);
1633 return (nios2_valid_addr_expr_p (op0
, op1
, strict_p
)
1634 || nios2_valid_addr_expr_p (op1
, op0
, strict_p
));
1643 /* Return true if SECTION is a small section name. */
1645 nios2_small_section_name_p (const char *section
)
1647 return (strcmp (section
, ".sbss") == 0
1648 || strncmp (section
, ".sbss.", 6) == 0
1649 || strcmp (section
, ".sdata") == 0
1650 || strncmp (section
, ".sdata.", 7) == 0);
1653 /* Return true if EXP should be placed in the small data section. */
1655 nios2_in_small_data_p (const_tree exp
)
1657 /* We want to merge strings, so we never consider them small data. */
1658 if (TREE_CODE (exp
) == STRING_CST
)
1661 if (TREE_CODE (exp
) == VAR_DECL
)
1663 if (DECL_SECTION_NAME (exp
))
1665 const char *section
= DECL_SECTION_NAME (exp
);
1666 if (nios2_small_section_name_p (section
))
1671 HOST_WIDE_INT size
= int_size_in_bytes (TREE_TYPE (exp
));
1673 /* If this is an incomplete type with size 0, then we can't put it
1674 in sdata because it might be too big when completed. */
1676 && (unsigned HOST_WIDE_INT
) size
<= nios2_section_threshold
)
1684 /* Return true if symbol is in small data section. */
1687 nios2_symbol_ref_in_small_data_p (rtx sym
)
1691 gcc_assert (GET_CODE (sym
) == SYMBOL_REF
);
1692 decl
= SYMBOL_REF_DECL (sym
);
1694 /* TLS variables are not accessed through the GP. */
1695 if (SYMBOL_REF_TLS_MODEL (sym
) != 0)
1698 /* If the user has explicitly placed the symbol in a small data section
1699 via an attribute, generate gp-relative addressing even if the symbol
1700 is external, weak, or larger than we'd automatically put in the
1701 small data section. OTOH, if the symbol is located in some
1702 non-small-data section, we can't use gp-relative accesses on it
1703 unless the user has requested gpopt_data or gpopt_all. */
1705 switch (nios2_gpopt_option
)
1708 /* Don't generate a gp-relative addressing mode if that's been
1713 /* Use GP-relative addressing for small data symbols that are
1714 not external or weak, plus any symbols that have explicitly
1715 been placed in a small data section. */
1716 if (decl
&& DECL_SECTION_NAME (decl
))
1717 return nios2_small_section_name_p (DECL_SECTION_NAME (decl
));
1718 return (SYMBOL_REF_SMALL_P (sym
)
1719 && !SYMBOL_REF_EXTERNAL_P (sym
)
1720 && !(decl
&& DECL_WEAK (decl
)));
1723 /* Use GP-relative addressing for small data symbols, even if
1724 they are external or weak. Note that SYMBOL_REF_SMALL_P
1725 is also true of symbols that have explicitly been placed
1726 in a small data section. */
1727 return SYMBOL_REF_SMALL_P (sym
);
1730 /* Use GP-relative addressing for all data symbols regardless
1731 of the object size, but not for code symbols. This option
1732 is equivalent to the user asserting that the entire data
1733 section is accessible from the GP. */
1734 return !SYMBOL_REF_FUNCTION_P (sym
);
1737 /* Use GP-relative addressing for everything, including code.
1738 Effectively, the user has asserted that the entire program
1739 fits within the 64K range of the GP offset. */
1743 /* We shouldn't get here. */
1748 /* Implement TARGET_SECTION_TYPE_FLAGS. */
1751 nios2_section_type_flags (tree decl
, const char *name
, int reloc
)
1755 flags
= default_section_type_flags (decl
, name
, reloc
);
1757 if (nios2_small_section_name_p (name
))
1758 flags
|= SECTION_SMALL
;
1763 /* Return true if SYMBOL_REF X binds locally. */
1766 nios2_symbol_binds_local_p (const_rtx x
)
1768 return (SYMBOL_REF_DECL (x
)
1769 ? targetm
.binds_local_p (SYMBOL_REF_DECL (x
))
1770 : SYMBOL_REF_LOCAL_P (x
));
1773 /* Position independent code related. */
1775 /* Emit code to load the PIC register. */
1777 nios2_load_pic_register (void)
1779 rtx tmp
= gen_rtx_REG (Pmode
, TEMP_REG_NUM
);
1781 emit_insn (gen_load_got_register (pic_offset_table_rtx
, tmp
));
1782 emit_insn (gen_add3_insn (pic_offset_table_rtx
, pic_offset_table_rtx
, tmp
));
1785 /* Generate a PIC address as a MEM rtx. */
1787 nios2_load_pic_address (rtx sym
, int unspec
)
1790 && GET_CODE (sym
) == SYMBOL_REF
1791 && nios2_symbol_binds_local_p (sym
))
1792 /* Under -fPIC, generate a GOTOFF address for local symbols. */
1793 return nios2_got_address (sym
, UNSPEC_PIC_GOTOFF_SYM
);
1795 return gen_const_mem (Pmode
, nios2_got_address (sym
, unspec
));
1798 /* Nonzero if the constant value X is a legitimate general operand
1799 when generating PIC code. It is given that flag_pic is on and
1800 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
1802 nios2_legitimate_pic_operand_p (rtx x
)
1804 if (GET_CODE (x
) == CONST
1805 && GET_CODE (XEXP (x
, 0)) == UNSPEC
1806 && nios2_large_offset_p (XINT (XEXP (x
, 0), 1)))
1809 return ! (GET_CODE (x
) == SYMBOL_REF
1810 || GET_CODE (x
) == LABEL_REF
|| GET_CODE (x
) == CONST
);
1813 /* Return TRUE if X is a thread-local symbol. */
1815 nios2_tls_symbol_p (rtx x
)
1817 return (targetm
.have_tls
&& GET_CODE (x
) == SYMBOL_REF
1818 && SYMBOL_REF_TLS_MODEL (x
) != 0);
1821 /* Legitimize addresses that are CONSTANT_P expressions. */
1823 nios2_legitimize_constant_address (rtx addr
)
1826 split_const (addr
, &base
, &offset
);
1828 if (nios2_tls_symbol_p (base
))
1829 base
= nios2_legitimize_tls_address (base
);
1831 base
= nios2_load_pic_address (base
, UNSPEC_PIC_SYM
);
1835 if (offset
!= const0_rtx
)
1837 gcc_assert (can_create_pseudo_p ());
1838 return gen_rtx_PLUS (Pmode
, force_reg (Pmode
, base
),
1839 (CONST_INT_P (offset
)
1840 ? (SMALL_INT (INTVAL (offset
))
1841 ? offset
: force_reg (Pmode
, offset
))
1847 /* Implement TARGET_LEGITIMIZE_ADDRESS. */
1849 nios2_legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
1850 machine_mode mode ATTRIBUTE_UNUSED
)
1853 return nios2_legitimize_constant_address (x
);
1855 /* For the TLS LE (Local Exec) model, the compiler may try to
1856 combine constant offsets with unspec relocs, creating address RTXs
1858 (plus:SI (reg:SI 23 r23)
1861 (unspec:SI [(symbol_ref:SI ("var"))] UNSPEC_ADD_TLS_LE)
1862 (const_int 48 [0x30]))))
1864 This usually happens when 'var' is a thread-local struct variable,
1865 and access of a field in var causes the addend.
1867 We typically want this combining, so transform the above into this
1868 form, which is allowed:
1869 (plus:SI (reg:SI 23 r23)
1873 (plus:SI (symbol_ref:SI ("var"))
1874 (const_int 48 [0x30])))] UNSPEC_ADD_TLS_LE)))
1876 Which will be output as '%tls_le(var+48)(r23)' in assembly. */
1877 if (GET_CODE (x
) == PLUS
1878 && GET_CODE (XEXP (x
, 0)) == REG
1879 && GET_CODE (XEXP (x
, 1)) == CONST
)
1881 rtx unspec
, offset
, reg
= XEXP (x
, 0);
1882 split_const (XEXP (x
, 1), &unspec
, &offset
);
1883 if (GET_CODE (unspec
) == UNSPEC
1884 && !nios2_large_offset_p (XINT (unspec
, 1))
1885 && offset
!= const0_rtx
)
1887 unspec
= copy_rtx (unspec
);
1888 XVECEXP (unspec
, 0, 0)
1889 = plus_constant (Pmode
, XVECEXP (unspec
, 0, 0), INTVAL (offset
));
1890 x
= gen_rtx_PLUS (Pmode
, reg
, gen_rtx_CONST (Pmode
, unspec
));
1898 nios2_delegitimize_address (rtx x
)
1900 x
= delegitimize_mem_from_attrs (x
);
1902 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == UNSPEC
)
1904 switch (XINT (XEXP (x
, 0), 1))
1906 case UNSPEC_PIC_SYM
:
1907 case UNSPEC_PIC_CALL_SYM
:
1908 case UNSPEC_PIC_GOTOFF_SYM
:
1909 case UNSPEC_ADD_TLS_GD
:
1910 case UNSPEC_ADD_TLS_LDM
:
1911 case UNSPEC_LOAD_TLS_IE
:
1912 case UNSPEC_ADD_TLS_LE
:
1913 x
= XVECEXP (XEXP (x
, 0), 0, 0);
1914 gcc_assert (GET_CODE (x
) == SYMBOL_REF
);
1921 /* Main expander function for RTL moves. */
1923 nios2_emit_move_sequence (rtx
*operands
, machine_mode mode
)
1925 rtx to
= operands
[0];
1926 rtx from
= operands
[1];
1928 if (!register_operand (to
, mode
) && !reg_or_0_operand (from
, mode
))
1930 gcc_assert (can_create_pseudo_p ());
1931 from
= copy_to_mode_reg (mode
, from
);
1934 if (GET_CODE (from
) == SYMBOL_REF
|| GET_CODE (from
) == LABEL_REF
1935 || (GET_CODE (from
) == CONST
1936 && GET_CODE (XEXP (from
, 0)) != UNSPEC
))
1937 from
= nios2_legitimize_constant_address (from
);
1944 /* The function with address *ADDR is being called. If the address
1945 needs to be loaded from the GOT, emit the instruction to do so and
1946 update *ADDR to point to the rtx for the loaded value. */
1948 nios2_adjust_call_address (rtx
*call_op
)
1951 gcc_assert (MEM_P (*call_op
));
1952 addr
= XEXP (*call_op
, 0);
1953 if (flag_pic
&& CONSTANT_P (addr
))
1955 rtx reg
= gen_reg_rtx (Pmode
);
1956 emit_move_insn (reg
, nios2_load_pic_address (addr
, UNSPEC_PIC_CALL_SYM
));
1957 XEXP (*call_op
, 0) = reg
;
1962 /* Output assembly language related definitions. */
1964 /* Print the operand OP to file stream FILE modified by LETTER.
1965 LETTER can be one of:
1967 i: print "i" if OP is an immediate, except 0
1968 o: print "io" if OP is volatile
1969 z: for const0_rtx print $0 instead of 0
1972 U: for upper half of 32 bit value
1973 D: for the upper 32-bits of a 64-bit double value
1974 R: prints reverse condition.
1977 nios2_print_operand (FILE *file
, rtx op
, int letter
)
1983 if (CONSTANT_P (op
) && op
!= const0_rtx
)
1984 fprintf (file
, "i");
1988 if (GET_CODE (op
) == MEM
1989 && ((MEM_VOLATILE_P (op
) && TARGET_BYPASS_CACHE_VOLATILE
)
1990 || TARGET_BYPASS_CACHE
))
1991 fprintf (file
, "io");
1998 if (comparison_operator (op
, VOIDmode
))
2000 enum rtx_code cond
= GET_CODE (op
);
2003 fprintf (file
, "%s", GET_RTX_NAME (cond
));
2008 fprintf (file
, "%s", GET_RTX_NAME (reverse_condition (cond
)));
2013 switch (GET_CODE (op
))
2016 if (letter
== 0 || letter
== 'z')
2018 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
2021 else if (letter
== 'D')
2023 fprintf (file
, "%s", reg_names
[REGNO (op
)+1]);
2029 if (INTVAL (op
) == 0 && letter
== 'z')
2031 fprintf (file
, "zero");
2037 HOST_WIDE_INT val
= INTVAL (op
);
2038 val
= (val
>> 16) & 0xFFFF;
2039 output_addr_const (file
, gen_int_mode (val
, SImode
));
2042 /* Else, fall through. */
2048 if (letter
== 0 || letter
== 'z')
2050 output_addr_const (file
, op
);
2053 else if (letter
== 'H' || letter
== 'L')
2055 fprintf (file
, "%%");
2056 if (GET_CODE (op
) == CONST
2057 && GET_CODE (XEXP (op
, 0)) == UNSPEC
)
2059 rtx unspec
= XEXP (op
, 0);
2060 int unspec_reloc
= XINT (unspec
, 1);
2061 gcc_assert (nios2_large_offset_p (unspec_reloc
));
2062 fprintf (file
, "%s_", nios2_unspec_reloc_name (unspec_reloc
));
2063 op
= XVECEXP (unspec
, 0, 0);
2065 fprintf (file
, letter
== 'H' ? "hiadj(" : "lo(");
2066 output_addr_const (file
, op
);
2067 fprintf (file
, ")");
2076 output_address (op
);
2084 output_addr_const (file
, op
);
2093 output_operand_lossage ("Unsupported operand for code '%c'", letter
);
2097 /* Return true if this is a GP-relative accessible reference. */
2099 gprel_constant_p (rtx op
)
2101 if (GET_CODE (op
) == SYMBOL_REF
2102 && nios2_symbol_ref_in_small_data_p (op
))
2104 else if (GET_CODE (op
) == CONST
2105 && GET_CODE (XEXP (op
, 0)) == PLUS
)
2106 return gprel_constant_p (XEXP (XEXP (op
, 0), 0));
2111 /* Return the name string for a supported unspec reloc offset. */
2113 nios2_unspec_reloc_name (int unspec
)
2117 case UNSPEC_PIC_SYM
:
2119 case UNSPEC_PIC_CALL_SYM
:
2121 case UNSPEC_PIC_GOTOFF_SYM
:
2123 case UNSPEC_LOAD_TLS_IE
:
2125 case UNSPEC_ADD_TLS_LE
:
2127 case UNSPEC_ADD_TLS_GD
:
2129 case UNSPEC_ADD_TLS_LDM
:
2131 case UNSPEC_ADD_TLS_LDO
:
2138 /* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */
2140 nios2_output_addr_const_extra (FILE *file
, rtx op
)
2143 gcc_assert (GET_CODE (op
) == UNSPEC
);
2145 /* Support for printing out const unspec relocations. */
2146 name
= nios2_unspec_reloc_name (XINT (op
, 1));
2149 fprintf (file
, "%%%s(", name
);
2150 output_addr_const (file
, XVECEXP (op
, 0, 0));
2151 fprintf (file
, ")");
2157 /* Implement TARGET_PRINT_OPERAND_ADDRESS. */
2159 nios2_print_operand_address (FILE *file
, rtx op
)
2161 switch (GET_CODE (op
))
2168 if (gprel_constant_p (op
))
2170 fprintf (file
, "%%gprel(");
2171 output_addr_const (file
, op
);
2172 fprintf (file
, ")(%s)", reg_names
[GP_REGNO
]);
2180 rtx op0
= XEXP (op
, 0);
2181 rtx op1
= XEXP (op
, 1);
2183 if (REG_P (op0
) && CONSTANT_P (op1
))
2185 output_addr_const (file
, op1
);
2186 fprintf (file
, "(%s)", reg_names
[REGNO (op0
)]);
2189 else if (REG_P (op1
) && CONSTANT_P (op0
))
2191 output_addr_const (file
, op0
);
2192 fprintf (file
, "(%s)", reg_names
[REGNO (op1
)]);
2199 fprintf (file
, "0(%s)", reg_names
[REGNO (op
)]);
2204 rtx base
= XEXP (op
, 0);
2205 nios2_print_operand_address (file
, base
);
2212 fprintf (stderr
, "Missing way to print address\n");
2217 /* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL. */
2219 nios2_output_dwarf_dtprel (FILE *file
, int size
, rtx x
)
2221 gcc_assert (size
== 4);
2222 fprintf (file
, "\t.4byte\t%%tls_ldo(");
2223 output_addr_const (file
, x
);
2224 fprintf (file
, ")");
2227 /* Implemet TARGET_ASM_FILE_END. */
2230 nios2_asm_file_end (void)
2232 /* The Nios II Linux stack is mapped non-executable by default, so add a
2233 .note.GNU-stack section for switching to executable stacks only when
2234 trampolines are generated. */
2235 if (TARGET_LINUX_ABI
&& trampolines_created
)
2236 file_end_indicate_exec_stack ();
2239 /* Implement TARGET_ASM_FUNCTION_PROLOGUE. */
2241 nios2_asm_function_prologue (FILE *file
, HOST_WIDE_INT size ATTRIBUTE_UNUSED
)
2243 if (flag_verbose_asm
|| flag_debug_asm
)
2245 nios2_compute_frame_layout ();
2246 nios2_dump_frame_layout (file
);
2250 /* Emit assembly of custom FPU instructions. */
2252 nios2_fpu_insn_asm (enum n2fpu_code code
)
2254 static char buf
[256];
2255 const char *op1
, *op2
, *op3
;
2256 int ln
= 256, n
= 0;
2258 int N
= N2FPU_N (code
);
2259 int num_operands
= N2FPU (code
).num_operands
;
2260 const char *insn_name
= N2FPU_NAME (code
);
2261 tree ftype
= nios2_ftype (N2FPU_FTCODE (code
));
2262 machine_mode dst_mode
= TYPE_MODE (TREE_TYPE (ftype
));
2263 machine_mode src_mode
= TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (ftype
)));
2265 /* Prepare X register for DF input operands. */
2266 if (GET_MODE_SIZE (src_mode
) == 8 && num_operands
== 3)
2267 n
= snprintf (buf
, ln
, "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t",
2268 N2FPU_N (n2fpu_fwrx
));
2270 if (src_mode
== SFmode
)
2272 if (dst_mode
== VOIDmode
)
2274 /* The fwry case. */
2281 op1
= (dst_mode
== DFmode
? "%D0" : "%0");
2283 op3
= (num_operands
== 2 ? "zero" : "%2");
2286 else if (src_mode
== DFmode
)
2288 if (dst_mode
== VOIDmode
)
2290 /* The fwrx case. */
2298 op1
= (dst_mode
== DFmode
? "%D0" : "%0");
2299 op2
= (num_operands
== 2 ? "%1" : "%2");
2300 op3
= (num_operands
== 2 ? "%D1" : "%D2");
2303 else if (src_mode
== VOIDmode
)
2305 /* frdxlo, frdxhi, frdy cases. */
2306 gcc_assert (dst_mode
== SFmode
);
2310 else if (src_mode
== SImode
)
2312 /* Conversion operators. */
2313 gcc_assert (num_operands
== 2);
2314 op1
= (dst_mode
== DFmode
? "%D0" : "%0");
2321 /* Main instruction string. */
2322 n
+= snprintf (buf
+ n
, ln
- n
, "custom\t%d, %s, %s, %s # %s %%0%s%s",
2323 N
, op1
, op2
, op3
, insn_name
,
2324 (num_operands
>= 2 ? ", %1" : ""),
2325 (num_operands
== 3 ? ", %2" : ""));
2327 /* Extraction of Y register for DF results. */
2328 if (dst_mode
== DFmode
)
2329 snprintf (buf
+ n
, ln
- n
, "\n\tcustom\t%d, %%0, zero, zero # frdy %%0",
2330 N2FPU_N (n2fpu_frdy
));
2336 /* Function argument related. */
2338 /* Define where to put the arguments to a function. Value is zero to
2339 push the argument on the stack, or a hard register in which to
2342 MODE is the argument's machine mode.
2343 TYPE is the data type of the argument (as a tree).
2344 This is null for libcalls where that information may
2346 CUM is a variable of type CUMULATIVE_ARGS which gives info about
2347 the preceding args and about the function being called.
2348 NAMED is nonzero if this argument is a named parameter
2349 (otherwise it is an extra parameter matching an ellipsis). */
2352 nios2_function_arg (cumulative_args_t cum_v
, machine_mode mode
,
2353 const_tree type ATTRIBUTE_UNUSED
,
2354 bool named ATTRIBUTE_UNUSED
)
2356 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2357 rtx return_rtx
= NULL_RTX
;
2359 if (cum
->regs_used
< NUM_ARG_REGS
)
2360 return_rtx
= gen_rtx_REG (mode
, FIRST_ARG_REGNO
+ cum
->regs_used
);
2365 /* Return number of bytes, at the beginning of the argument, that must be
2366 put in registers. 0 is the argument is entirely in registers or entirely
2370 nios2_arg_partial_bytes (cumulative_args_t cum_v
,
2371 machine_mode mode
, tree type ATTRIBUTE_UNUSED
,
2372 bool named ATTRIBUTE_UNUSED
)
2374 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2375 HOST_WIDE_INT param_size
;
2377 if (mode
== BLKmode
)
2379 param_size
= int_size_in_bytes (type
);
2380 gcc_assert (param_size
>= 0);
2383 param_size
= GET_MODE_SIZE (mode
);
2385 /* Convert to words (round up). */
2386 param_size
= (UNITS_PER_WORD
- 1 + param_size
) / UNITS_PER_WORD
;
2388 if (cum
->regs_used
< NUM_ARG_REGS
2389 && cum
->regs_used
+ param_size
> NUM_ARG_REGS
)
2390 return (NUM_ARG_REGS
- cum
->regs_used
) * UNITS_PER_WORD
;
2395 /* Update the data in CUM to advance over an argument of mode MODE
2396 and data type TYPE; TYPE is null for libcalls where that information
2397 may not be available. */
2400 nios2_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
,
2401 const_tree type ATTRIBUTE_UNUSED
,
2402 bool named ATTRIBUTE_UNUSED
)
2404 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2405 HOST_WIDE_INT param_size
;
2407 if (mode
== BLKmode
)
2409 param_size
= int_size_in_bytes (type
);
2410 gcc_assert (param_size
>= 0);
2413 param_size
= GET_MODE_SIZE (mode
);
2415 /* Convert to words (round up). */
2416 param_size
= (UNITS_PER_WORD
- 1 + param_size
) / UNITS_PER_WORD
;
2418 if (cum
->regs_used
+ param_size
> NUM_ARG_REGS
)
2419 cum
->regs_used
= NUM_ARG_REGS
;
2421 cum
->regs_used
+= param_size
;
2425 nios2_function_arg_padding (machine_mode mode
, const_tree type
)
2427 /* On little-endian targets, the first byte of every stack argument
2428 is passed in the first byte of the stack slot. */
2429 if (!BYTES_BIG_ENDIAN
)
2432 /* Otherwise, integral types are padded downward: the last byte of a
2433 stack argument is passed in the last byte of the stack slot. */
2435 ? INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
)
2436 : GET_MODE_CLASS (mode
) == MODE_INT
)
2439 /* Arguments smaller than a stack slot are padded downward. */
2440 if (mode
!= BLKmode
)
2441 return (GET_MODE_BITSIZE (mode
) >= PARM_BOUNDARY
) ? upward
: downward
;
2443 return ((int_size_in_bytes (type
) >= (PARM_BOUNDARY
/ BITS_PER_UNIT
))
2444 ? upward
: downward
);
2448 nios2_block_reg_padding (machine_mode mode
, tree type
,
2449 int first ATTRIBUTE_UNUSED
)
2451 return nios2_function_arg_padding (mode
, type
);
2454 /* Emit RTL insns to initialize the variable parts of a trampoline.
2455 FNADDR is an RTX for the address of the function's pure code.
2456 CXT is an RTX for the static chain value for the function.
2457 On Nios II, we handle this by a library call. */
2459 nios2_trampoline_init (rtx m_tramp
, tree fndecl
, rtx cxt
)
2461 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2462 rtx ctx_reg
= force_reg (Pmode
, cxt
);
2463 rtx addr
= force_reg (Pmode
, XEXP (m_tramp
, 0));
2465 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "__trampoline_setup"),
2466 LCT_NORMAL
, VOIDmode
, 3, addr
, Pmode
, fnaddr
, Pmode
,
2470 /* Implement TARGET_FUNCTION_VALUE. */
2472 nios2_function_value (const_tree ret_type
, const_tree fn ATTRIBUTE_UNUSED
,
2473 bool outgoing ATTRIBUTE_UNUSED
)
2475 return gen_rtx_REG (TYPE_MODE (ret_type
), FIRST_RETVAL_REGNO
);
2478 /* Implement TARGET_LIBCALL_VALUE. */
2480 nios2_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
2482 return gen_rtx_REG (mode
, FIRST_RETVAL_REGNO
);
2485 /* Implement TARGET_FUNCTION_VALUE_REGNO_P. */
2487 nios2_function_value_regno_p (const unsigned int regno
)
2489 return regno
== FIRST_RETVAL_REGNO
;
2492 /* Implement TARGET_RETURN_IN_MEMORY. */
2494 nios2_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
2496 return (int_size_in_bytes (type
) > (2 * UNITS_PER_WORD
)
2497 || int_size_in_bytes (type
) == -1);
2500 /* TODO: It may be possible to eliminate the copyback and implement
2503 nios2_setup_incoming_varargs (cumulative_args_t cum_v
,
2504 machine_mode mode
, tree type
,
2505 int *pretend_size
, int second_time
)
2507 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2508 CUMULATIVE_ARGS local_cum
;
2509 cumulative_args_t local_cum_v
= pack_cumulative_args (&local_cum
);
2514 nios2_function_arg_advance (local_cum_v
, mode
, type
, 1);
2516 regs_to_push
= NUM_ARG_REGS
- local_cum
.regs_used
;
2518 if (!second_time
&& regs_to_push
> 0)
2520 rtx ptr
= virtual_incoming_args_rtx
;
2521 rtx mem
= gen_rtx_MEM (BLKmode
, ptr
);
2522 emit_insn (gen_blockage ());
2523 move_block_from_reg (local_cum
.regs_used
+ FIRST_ARG_REGNO
, mem
,
2525 emit_insn (gen_blockage ());
2528 pret_size
= regs_to_push
* UNITS_PER_WORD
;
2530 *pretend_size
= pret_size
;
2535 /* Init FPU builtins. */
2537 nios2_init_fpu_builtins (int start_code
)
2540 char builtin_name
[64] = "__builtin_custom_";
2541 unsigned int i
, n
= strlen ("__builtin_custom_");
2543 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
2545 snprintf (builtin_name
+ n
, sizeof (builtin_name
) - n
,
2546 "%s", N2FPU_NAME (i
));
2548 add_builtin_function (builtin_name
, nios2_ftype (N2FPU_FTCODE (i
)),
2549 start_code
+ i
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2550 nios2_register_builtin_fndecl (start_code
+ i
, fndecl
);
2554 /* Helper function for expanding FPU builtins. */
2556 nios2_expand_fpu_builtin (tree exp
, unsigned int code
, rtx target
)
2558 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
2559 enum insn_code icode
= N2FPU_ICODE (code
);
2560 int nargs
, argno
, opno
= 0;
2561 int num_operands
= N2FPU (code
).num_operands
;
2562 machine_mode dst_mode
= TYPE_MODE (TREE_TYPE (exp
));
2563 bool has_target_p
= (dst_mode
!= VOIDmode
);
2565 if (N2FPU_N (code
) < 0)
2566 fatal_error (input_location
,
2567 "Cannot call %<__builtin_custom_%s%> without specifying switch"
2568 " %<-mcustom-%s%>", N2FPU_NAME (code
), N2FPU_NAME (code
));
2570 create_output_operand (&ops
[opno
++], target
, dst_mode
);
2572 /* Subtract away the count of the VOID return, mainly for fwrx/fwry. */
2574 nargs
= call_expr_nargs (exp
);
2575 for (argno
= 0; argno
< nargs
; argno
++)
2577 tree arg
= CALL_EXPR_ARG (exp
, argno
);
2578 create_input_operand (&ops
[opno
++], expand_normal (arg
),
2579 TYPE_MODE (TREE_TYPE (arg
)));
2581 if (!maybe_expand_insn (icode
, num_operands
, ops
))
2583 error ("invalid argument to built-in function");
2584 return has_target_p
? gen_reg_rtx (ops
[0].mode
) : const0_rtx
;
2586 return has_target_p
? ops
[0].value
: const0_rtx
;
2589 /* Nios II has custom instruction built-in functions of the forms:
2592 __builtin_custom_nXX
2594 __builtin_custom_XnX
2595 __builtin_custom_XnXX
2597 where each X could be either 'i' (int), 'f' (float), or 'p' (void*).
2598 Therefore with 0-1 return values, and 0-2 arguments, we have a
2599 total of (3 + 1) * (1 + 3 + 9) == 52 custom builtin functions.
2601 #define NUM_CUSTOM_BUILTINS ((3 + 1) * (1 + 3 + 9))
2602 static char custom_builtin_name
[NUM_CUSTOM_BUILTINS
][5];
2605 nios2_init_custom_builtins (int start_code
)
2607 tree builtin_ftype
, ret_type
, fndecl
;
2608 char builtin_name
[32] = "__builtin_custom_";
2609 int n
= strlen ("__builtin_custom_");
2610 int builtin_code
= 0;
2611 int lhs
, rhs1
, rhs2
;
2613 struct { tree type
; const char *c
; } op
[4];
2614 /* z */ op
[0].c
= ""; op
[0].type
= NULL_TREE
;
2615 /* f */ op
[1].c
= "f"; op
[1].type
= float_type_node
;
2616 /* i */ op
[2].c
= "i"; op
[2].type
= integer_type_node
;
2617 /* p */ op
[3].c
= "p"; op
[3].type
= ptr_type_node
;
2619 /* We enumerate through the possible operand types to create all the
2620 __builtin_custom_XnXX function tree types. Note that these may slightly
2621 overlap with the function types created for other fixed builtins. */
2623 for (lhs
= 0; lhs
< 4; lhs
++)
2624 for (rhs1
= 0; rhs1
< 4; rhs1
++)
2625 for (rhs2
= 0; rhs2
< 4; rhs2
++)
2627 if (rhs1
== 0 && rhs2
!= 0)
2629 ret_type
= (op
[lhs
].type
? op
[lhs
].type
: void_type_node
);
2631 = build_function_type_list (ret_type
, integer_type_node
,
2632 op
[rhs1
].type
, op
[rhs2
].type
,
2634 snprintf (builtin_name
+ n
, 32 - n
, "%sn%s%s",
2635 op
[lhs
].c
, op
[rhs1
].c
, op
[rhs2
].c
);
2636 /* Save copy of parameter string into custom_builtin_name[]. */
2637 strncpy (custom_builtin_name
[builtin_code
], builtin_name
+ n
, 5);
2639 add_builtin_function (builtin_name
, builtin_ftype
,
2640 start_code
+ builtin_code
,
2641 BUILT_IN_MD
, NULL
, NULL_TREE
);
2642 nios2_register_builtin_fndecl (start_code
+ builtin_code
, fndecl
);
2647 /* Helper function for expanding custom builtins. */
2649 nios2_expand_custom_builtin (tree exp
, unsigned int index
, rtx target
)
2651 bool has_target_p
= (TREE_TYPE (exp
) != void_type_node
);
2652 machine_mode tmode
= VOIDmode
;
2654 rtx value
, insn
, unspec_args
[3];
2660 tmode
= TYPE_MODE (TREE_TYPE (exp
));
2661 if (!target
|| GET_MODE (target
) != tmode
2663 target
= gen_reg_rtx (tmode
);
2666 nargs
= call_expr_nargs (exp
);
2667 for (argno
= 0; argno
< nargs
; argno
++)
2669 arg
= CALL_EXPR_ARG (exp
, argno
);
2670 value
= expand_normal (arg
);
2671 unspec_args
[argno
] = value
;
2674 if (!custom_insn_opcode (value
, VOIDmode
))
2675 error ("custom instruction opcode must be compile time "
2676 "constant in the range 0-255 for __builtin_custom_%s",
2677 custom_builtin_name
[index
]);
2680 /* For other arguments, force into a register. */
2681 unspec_args
[argno
] = force_reg (TYPE_MODE (TREE_TYPE (arg
)),
2682 unspec_args
[argno
]);
2684 /* Fill remaining unspec operands with zero. */
2685 for (; argno
< 3; argno
++)
2686 unspec_args
[argno
] = const0_rtx
;
2688 insn
= (has_target_p
2689 ? gen_rtx_SET (VOIDmode
, target
,
2690 gen_rtx_UNSPEC_VOLATILE (tmode
,
2691 gen_rtvec_v (3, unspec_args
),
2692 UNSPECV_CUSTOM_XNXX
))
2693 : gen_rtx_UNSPEC_VOLATILE (VOIDmode
, gen_rtvec_v (3, unspec_args
),
2694 UNSPECV_CUSTOM_NXX
));
2696 return has_target_p
? target
: const0_rtx
;
2702 /* Main definition of built-in functions. Nios II has a small number of fixed
2703 builtins, plus a large number of FPU insn builtins, and builtins for
2704 generating custom instructions. */
2706 struct nios2_builtin_desc
2708 enum insn_code icode
;
2709 enum nios2_ftcode ftype
;
2713 #define N2_BUILTINS \
2714 N2_BUILTIN_DEF (sync, N2_FTYPE_VOID_VOID) \
2715 N2_BUILTIN_DEF (ldbio, N2_FTYPE_SI_CVPTR) \
2716 N2_BUILTIN_DEF (ldbuio, N2_FTYPE_UI_CVPTR) \
2717 N2_BUILTIN_DEF (ldhio, N2_FTYPE_SI_CVPTR) \
2718 N2_BUILTIN_DEF (ldhuio, N2_FTYPE_UI_CVPTR) \
2719 N2_BUILTIN_DEF (ldwio, N2_FTYPE_SI_CVPTR) \
2720 N2_BUILTIN_DEF (stbio, N2_FTYPE_VOID_VPTR_SI) \
2721 N2_BUILTIN_DEF (sthio, N2_FTYPE_VOID_VPTR_SI) \
2722 N2_BUILTIN_DEF (stwio, N2_FTYPE_VOID_VPTR_SI) \
2723 N2_BUILTIN_DEF (rdctl, N2_FTYPE_SI_SI) \
2724 N2_BUILTIN_DEF (wrctl, N2_FTYPE_VOID_SI_SI)
2726 enum nios2_builtin_code
{
2727 #define N2_BUILTIN_DEF(name, ftype) NIOS2_BUILTIN_ ## name,
2729 #undef N2_BUILTIN_DEF
2730 NUM_FIXED_NIOS2_BUILTINS
2733 static const struct nios2_builtin_desc nios2_builtins
[] = {
2734 #define N2_BUILTIN_DEF(name, ftype) \
2735 { CODE_FOR_ ## name, ftype, "__builtin_" #name },
2737 #undef N2_BUILTIN_DEF
2740 /* Start/ends of FPU/custom insn builtin index ranges. */
2741 static unsigned int nios2_fpu_builtin_base
;
2742 static unsigned int nios2_custom_builtin_base
;
2743 static unsigned int nios2_custom_builtin_end
;
2745 /* Implement TARGET_INIT_BUILTINS. */
2747 nios2_init_builtins (void)
2751 /* Initialize fixed builtins. */
2752 for (i
= 0; i
< ARRAY_SIZE (nios2_builtins
); i
++)
2754 const struct nios2_builtin_desc
*d
= &nios2_builtins
[i
];
2756 add_builtin_function (d
->name
, nios2_ftype (d
->ftype
), i
,
2757 BUILT_IN_MD
, NULL
, NULL
);
2758 nios2_register_builtin_fndecl (i
, fndecl
);
2761 /* Initialize FPU builtins. */
2762 nios2_fpu_builtin_base
= ARRAY_SIZE (nios2_builtins
);
2763 nios2_init_fpu_builtins (nios2_fpu_builtin_base
);
2765 /* Initialize custom insn builtins. */
2766 nios2_custom_builtin_base
2767 = nios2_fpu_builtin_base
+ ARRAY_SIZE (nios2_fpu_insn
);
2768 nios2_custom_builtin_end
2769 = nios2_custom_builtin_base
+ NUM_CUSTOM_BUILTINS
;
2770 nios2_init_custom_builtins (nios2_custom_builtin_base
);
2773 /* Array of fndecls for TARGET_BUILTIN_DECL. */
2774 #define NIOS2_NUM_BUILTINS \
2775 (ARRAY_SIZE (nios2_builtins) + ARRAY_SIZE (nios2_fpu_insn) + NUM_CUSTOM_BUILTINS)
2776 static GTY(()) tree nios2_builtin_decls
[NIOS2_NUM_BUILTINS
];
2779 nios2_register_builtin_fndecl (unsigned code
, tree fndecl
)
2781 nios2_builtin_decls
[code
] = fndecl
;
2784 /* Implement TARGET_BUILTIN_DECL. */
2786 nios2_builtin_decl (unsigned code
, bool initialize_p ATTRIBUTE_UNUSED
)
2788 gcc_assert (nios2_custom_builtin_end
== ARRAY_SIZE (nios2_builtin_decls
));
2790 if (code
>= nios2_custom_builtin_end
)
2791 return error_mark_node
;
2793 if (code
>= nios2_fpu_builtin_base
2794 && code
< nios2_custom_builtin_base
2795 && ! N2FPU_ENABLED_P (code
- nios2_fpu_builtin_base
))
2796 return error_mark_node
;
2798 return nios2_builtin_decls
[code
];
2802 /* Low-level built-in expand routine. */
2804 nios2_expand_builtin_insn (const struct nios2_builtin_desc
*d
, int n
,
2805 struct expand_operand
*ops
, bool has_target_p
)
2807 if (maybe_expand_insn (d
->icode
, n
, ops
))
2808 return has_target_p
? ops
[0].value
: const0_rtx
;
2811 error ("invalid argument to built-in function %s", d
->name
);
2812 return has_target_p
? gen_reg_rtx (ops
[0].mode
) : const0_rtx
;
2816 /* Expand ldio/stio form load-store instruction builtins. */
2818 nios2_expand_ldstio_builtin (tree exp
, rtx target
,
2819 const struct nios2_builtin_desc
*d
)
2823 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
2824 machine_mode mode
= insn_data
[d
->icode
].operand
[0].mode
;
2826 addr
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2827 mem
= gen_rtx_MEM (mode
, addr
);
2829 if (insn_data
[d
->icode
].operand
[0].allows_mem
)
2832 val
= expand_normal (CALL_EXPR_ARG (exp
, 1));
2833 if (CONST_INT_P (val
))
2834 val
= force_reg (mode
, gen_int_mode (INTVAL (val
), mode
));
2835 val
= simplify_gen_subreg (mode
, val
, GET_MODE (val
), 0);
2836 create_output_operand (&ops
[0], mem
, mode
);
2837 create_input_operand (&ops
[1], val
, mode
);
2838 has_target_p
= false;
2843 create_output_operand (&ops
[0], target
, mode
);
2844 create_input_operand (&ops
[1], mem
, mode
);
2845 has_target_p
= true;
2847 return nios2_expand_builtin_insn (d
, 2, ops
, has_target_p
);
2850 /* Expand rdctl/wrctl builtins. */
2852 nios2_expand_rdwrctl_builtin (tree exp
, rtx target
,
2853 const struct nios2_builtin_desc
*d
)
2855 bool has_target_p
= (insn_data
[d
->icode
].operand
[0].predicate
2856 == register_operand
);
2857 rtx ctlcode
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2858 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
2859 if (!rdwrctl_operand (ctlcode
, VOIDmode
))
2861 error ("Control register number must be in range 0-31 for %s",
2863 return has_target_p
? gen_reg_rtx (SImode
) : const0_rtx
;
2867 create_output_operand (&ops
[0], target
, SImode
);
2868 create_integer_operand (&ops
[1], INTVAL (ctlcode
));
2872 rtx val
= expand_normal (CALL_EXPR_ARG (exp
, 1));
2873 create_integer_operand (&ops
[0], INTVAL (ctlcode
));
2874 create_input_operand (&ops
[1], val
, SImode
);
2876 return nios2_expand_builtin_insn (d
, 2, ops
, has_target_p
);
2879 /* Implement TARGET_EXPAND_BUILTIN. Expand an expression EXP that calls
2880 a built-in function, with result going to TARGET if that's convenient
2881 (and in mode MODE if that's convenient).
2882 SUBTARGET may be used as the target for computing one of EXP's operands.
2883 IGNORE is nonzero if the value is to be ignored. */
2886 nios2_expand_builtin (tree exp
, rtx target
, rtx subtarget ATTRIBUTE_UNUSED
,
2887 machine_mode mode ATTRIBUTE_UNUSED
,
2888 int ignore ATTRIBUTE_UNUSED
)
2890 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
2891 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
2893 if (fcode
< nios2_fpu_builtin_base
)
2895 const struct nios2_builtin_desc
*d
= &nios2_builtins
[fcode
];
2899 case NIOS2_BUILTIN_sync
:
2900 emit_insn (gen_sync ());
2903 case NIOS2_BUILTIN_ldbio
:
2904 case NIOS2_BUILTIN_ldbuio
:
2905 case NIOS2_BUILTIN_ldhio
:
2906 case NIOS2_BUILTIN_ldhuio
:
2907 case NIOS2_BUILTIN_ldwio
:
2908 case NIOS2_BUILTIN_stbio
:
2909 case NIOS2_BUILTIN_sthio
:
2910 case NIOS2_BUILTIN_stwio
:
2911 return nios2_expand_ldstio_builtin (exp
, target
, d
);
2913 case NIOS2_BUILTIN_rdctl
:
2914 case NIOS2_BUILTIN_wrctl
:
2915 return nios2_expand_rdwrctl_builtin (exp
, target
, d
);
2921 else if (fcode
< nios2_custom_builtin_base
)
2922 /* FPU builtin range. */
2923 return nios2_expand_fpu_builtin (exp
, fcode
- nios2_fpu_builtin_base
,
2925 else if (fcode
< nios2_custom_builtin_end
)
2926 /* Custom insn builtin range. */
2927 return nios2_expand_custom_builtin (exp
, fcode
- nios2_custom_builtin_base
,
2933 /* Implement TARGET_INIT_LIBFUNCS. */
2935 nios2_init_libfuncs (void)
2937 /* For Linux, we have access to kernel support for atomic operations. */
2938 if (TARGET_LINUX_ABI
)
2939 init_sync_libfuncs (UNITS_PER_WORD
);
2944 /* Register a custom code use, and signal error if a conflict was found. */
2946 nios2_register_custom_code (unsigned int N
, enum nios2_ccs_code status
,
2949 gcc_assert (N
<= 255);
2951 if (status
== CCS_FPU
)
2953 if (custom_code_status
[N
] == CCS_FPU
&& index
!= custom_code_index
[N
])
2955 custom_code_conflict
= true;
2956 error ("switch %<-mcustom-%s%> conflicts with switch %<-mcustom-%s%>",
2957 N2FPU_NAME (custom_code_index
[N
]), N2FPU_NAME (index
));
2959 else if (custom_code_status
[N
] == CCS_BUILTIN_CALL
)
2961 custom_code_conflict
= true;
2962 error ("call to %<__builtin_custom_%s%> conflicts with switch "
2963 "%<-mcustom-%s%>", custom_builtin_name
[custom_code_index
[N
]],
2964 N2FPU_NAME (index
));
2967 else if (status
== CCS_BUILTIN_CALL
)
2969 if (custom_code_status
[N
] == CCS_FPU
)
2971 custom_code_conflict
= true;
2972 error ("call to %<__builtin_custom_%s%> conflicts with switch "
2973 "%<-mcustom-%s%>", custom_builtin_name
[index
],
2974 N2FPU_NAME (custom_code_index
[N
]));
2978 /* Note that code conflicts between different __builtin_custom_xnxx
2979 calls are not checked. */
2985 custom_code_status
[N
] = status
;
2986 custom_code_index
[N
] = index
;
2989 /* Mark a custom code as not in use. */
2991 nios2_deregister_custom_code (unsigned int N
)
2995 custom_code_status
[N
] = CCS_UNUSED
;
2996 custom_code_index
[N
] = 0;
3000 /* Target attributes can affect per-function option state, so we need to
3001 save/restore the custom code tracking info using the
3002 TARGET_OPTION_SAVE/TARGET_OPTION_RESTORE hooks. */
3005 nios2_option_save (struct cl_target_option
*ptr
,
3006 struct gcc_options
*opts ATTRIBUTE_UNUSED
)
3009 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
3010 ptr
->saved_fpu_custom_code
[i
] = N2FPU_N (i
);
3011 memcpy (ptr
->saved_custom_code_status
, custom_code_status
,
3012 sizeof (custom_code_status
));
3013 memcpy (ptr
->saved_custom_code_index
, custom_code_index
,
3014 sizeof (custom_code_index
));
3018 nios2_option_restore (struct gcc_options
*opts ATTRIBUTE_UNUSED
,
3019 struct cl_target_option
*ptr
)
3022 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
3023 N2FPU_N (i
) = ptr
->saved_fpu_custom_code
[i
];
3024 memcpy (custom_code_status
, ptr
->saved_custom_code_status
,
3025 sizeof (custom_code_status
));
3026 memcpy (custom_code_index
, ptr
->saved_custom_code_index
,
3027 sizeof (custom_code_index
));
3030 /* Inner function to process the attribute((target(...))), take an argument and
3031 set the current options from the argument. If we have a list, recursively
3032 go over the list. */
3035 nios2_valid_target_attribute_rec (tree args
)
3037 if (TREE_CODE (args
) == TREE_LIST
)
3040 for (; args
; args
= TREE_CHAIN (args
))
3041 if (TREE_VALUE (args
)
3042 && !nios2_valid_target_attribute_rec (TREE_VALUE (args
)))
3046 else if (TREE_CODE (args
) == STRING_CST
)
3048 char *argstr
= ASTRDUP (TREE_STRING_POINTER (args
));
3049 while (argstr
&& *argstr
!= '\0')
3051 bool no_opt
= false, end_p
= false;
3052 char *eq
= NULL
, *p
;
3053 while (ISSPACE (*argstr
))
3056 while (*p
!= '\0' && *p
!= ',')
3058 if (!eq
&& *p
== '=')
3068 if (!strncmp (argstr
, "no-", 3))
3073 if (!strncmp (argstr
, "custom-fpu-cfg", 14))
3078 error ("custom-fpu-cfg option does not support %<no-%>");
3083 error ("custom-fpu-cfg option requires configuration"
3087 /* Increment and skip whitespace. */
3088 while (ISSPACE (*(++eq
))) ;
3089 /* Decrement and skip to before any trailing whitespace. */
3090 while (ISSPACE (*(--end_eq
))) ;
3092 nios2_handle_custom_fpu_cfg (eq
, end_eq
+ 1, true);
3094 else if (!strncmp (argstr
, "custom-", 7))
3098 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
3099 if (!strncmp (argstr
+ 7, N2FPU_NAME (i
),
3100 strlen (N2FPU_NAME (i
))))
3112 error ("%<no-custom-%s%> does not accept arguments",
3116 /* Disable option by setting to -1. */
3117 nios2_deregister_custom_code (N2FPU_N (code
));
3118 N2FPU_N (code
) = -1;
3124 while (ISSPACE (*(++eq
))) ;
3127 error ("%<custom-%s=%> requires argument",
3131 for (t
= eq
; t
!= p
; ++t
)
3137 error ("`custom-%s=' argument requires "
3138 "numeric digits", N2FPU_NAME (code
));
3142 /* Set option to argument. */
3143 N2FPU_N (code
) = atoi (eq
);
3144 nios2_handle_custom_fpu_insn_option (code
);
3149 error ("%<custom-%s=%> is not recognised as FPU instruction",
3156 error ("%<%s%> is unknown", argstr
);
3171 /* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. */
3174 nios2_valid_target_attribute_tree (tree args
)
3176 if (!nios2_valid_target_attribute_rec (args
))
3178 nios2_custom_check_insns ();
3179 return build_target_option_node (&global_options
);
3182 /* Hook to validate attribute((target("string"))). */
3185 nios2_valid_target_attribute_p (tree fndecl
, tree
ARG_UNUSED (name
),
3186 tree args
, int ARG_UNUSED (flags
))
3188 struct cl_target_option cur_target
;
3190 tree old_optimize
= build_optimization_node (&global_options
);
3191 tree new_target
, new_optimize
;
3192 tree func_optimize
= DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl
);
3194 /* If the function changed the optimization levels as well as setting target
3195 options, start with the optimizations specified. */
3196 if (func_optimize
&& func_optimize
!= old_optimize
)
3197 cl_optimization_restore (&global_options
,
3198 TREE_OPTIMIZATION (func_optimize
));
3200 /* The target attributes may also change some optimization flags, so update
3201 the optimization options if necessary. */
3202 cl_target_option_save (&cur_target
, &global_options
);
3203 new_target
= nios2_valid_target_attribute_tree (args
);
3204 new_optimize
= build_optimization_node (&global_options
);
3211 DECL_FUNCTION_SPECIFIC_TARGET (fndecl
) = new_target
;
3213 if (old_optimize
!= new_optimize
)
3214 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl
) = new_optimize
;
3217 cl_target_option_restore (&global_options
, &cur_target
);
3219 if (old_optimize
!= new_optimize
)
3220 cl_optimization_restore (&global_options
,
3221 TREE_OPTIMIZATION (old_optimize
));
3225 /* Remember the last target of nios2_set_current_function. */
3226 static GTY(()) tree nios2_previous_fndecl
;
3228 /* Establish appropriate back-end context for processing the function
3229 FNDECL. The argument might be NULL to indicate processing at top
3230 level, outside of any function scope. */
3232 nios2_set_current_function (tree fndecl
)
3234 tree old_tree
= (nios2_previous_fndecl
3235 ? DECL_FUNCTION_SPECIFIC_TARGET (nios2_previous_fndecl
)
3238 tree new_tree
= (fndecl
3239 ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl
)
3242 if (fndecl
&& fndecl
!= nios2_previous_fndecl
)
3244 nios2_previous_fndecl
= fndecl
;
3245 if (old_tree
== new_tree
)
3250 cl_target_option_restore (&global_options
,
3251 TREE_TARGET_OPTION (new_tree
));
3257 struct cl_target_option
*def
3258 = TREE_TARGET_OPTION (target_option_current_node
);
3260 cl_target_option_restore (&global_options
, def
);
3266 /* Hook to validate the current #pragma GCC target and set the FPU custom
3267 code option state. If ARGS is NULL, then POP_TARGET is used to reset
3270 nios2_pragma_target_parse (tree args
, tree pop_target
)
3275 cur_tree
= ((pop_target
)
3277 : target_option_default_node
);
3278 cl_target_option_restore (&global_options
,
3279 TREE_TARGET_OPTION (cur_tree
));
3283 cur_tree
= nios2_valid_target_attribute_tree (args
);
3288 target_option_current_node
= cur_tree
;
3292 /* Implement TARGET_MERGE_DECL_ATTRIBUTES.
3293 We are just using this hook to add some additional error checking to
3294 the default behavior. GCC does not provide a target hook for merging
3295 the target options, and only correctly handles merging empty vs non-empty
3296 option data; see merge_decls() in c-decl.c.
3297 So here we require either that at least one of the decls has empty
3298 target options, or that the target options/data be identical. */
3300 nios2_merge_decl_attributes (tree olddecl
, tree newdecl
)
3302 tree oldopts
= lookup_attribute ("target", DECL_ATTRIBUTES (olddecl
));
3303 tree newopts
= lookup_attribute ("target", DECL_ATTRIBUTES (newdecl
));
3304 if (newopts
&& oldopts
&& newopts
!= oldopts
)
3306 tree oldtree
= DECL_FUNCTION_SPECIFIC_TARGET (olddecl
);
3307 tree newtree
= DECL_FUNCTION_SPECIFIC_TARGET (newdecl
);
3308 if (oldtree
&& newtree
&& oldtree
!= newtree
)
3310 struct cl_target_option
*olddata
= TREE_TARGET_OPTION (oldtree
);
3311 struct cl_target_option
*newdata
= TREE_TARGET_OPTION (newtree
);
3312 if (olddata
!= newdata
3313 && memcmp (olddata
, newdata
, sizeof (struct cl_target_option
)))
3314 error ("%qE redeclared with conflicting %qs attributes",
3315 DECL_NAME (newdecl
), "target");
3318 return merge_attributes (DECL_ATTRIBUTES (olddecl
),
3319 DECL_ATTRIBUTES (newdecl
));
3323 /* Initialize the GCC target structure. */
3324 #undef TARGET_ASM_FUNCTION_PROLOGUE
3325 #define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
3327 #undef TARGET_IN_SMALL_DATA_P
3328 #define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
3330 #undef TARGET_SECTION_TYPE_FLAGS
3331 #define TARGET_SECTION_TYPE_FLAGS nios2_section_type_flags
3333 #undef TARGET_INIT_BUILTINS
3334 #define TARGET_INIT_BUILTINS nios2_init_builtins
3335 #undef TARGET_EXPAND_BUILTIN
3336 #define TARGET_EXPAND_BUILTIN nios2_expand_builtin
3337 #undef TARGET_BUILTIN_DECL
3338 #define TARGET_BUILTIN_DECL nios2_builtin_decl
3340 #undef TARGET_INIT_LIBFUNCS
3341 #define TARGET_INIT_LIBFUNCS nios2_init_libfuncs
3343 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
3344 #define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
3346 #undef TARGET_CAN_ELIMINATE
3347 #define TARGET_CAN_ELIMINATE nios2_can_eliminate
3349 #undef TARGET_FUNCTION_ARG
3350 #define TARGET_FUNCTION_ARG nios2_function_arg
3352 #undef TARGET_FUNCTION_ARG_ADVANCE
3353 #define TARGET_FUNCTION_ARG_ADVANCE nios2_function_arg_advance
3355 #undef TARGET_ARG_PARTIAL_BYTES
3356 #define TARGET_ARG_PARTIAL_BYTES nios2_arg_partial_bytes
3358 #undef TARGET_TRAMPOLINE_INIT
3359 #define TARGET_TRAMPOLINE_INIT nios2_trampoline_init
3361 #undef TARGET_FUNCTION_VALUE
3362 #define TARGET_FUNCTION_VALUE nios2_function_value
3364 #undef TARGET_LIBCALL_VALUE
3365 #define TARGET_LIBCALL_VALUE nios2_libcall_value
3367 #undef TARGET_FUNCTION_VALUE_REGNO_P
3368 #define TARGET_FUNCTION_VALUE_REGNO_P nios2_function_value_regno_p
3370 #undef TARGET_RETURN_IN_MEMORY
3371 #define TARGET_RETURN_IN_MEMORY nios2_return_in_memory
3373 #undef TARGET_PROMOTE_PROTOTYPES
3374 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
3376 #undef TARGET_SETUP_INCOMING_VARARGS
3377 #define TARGET_SETUP_INCOMING_VARARGS nios2_setup_incoming_varargs
3379 #undef TARGET_MUST_PASS_IN_STACK
3380 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
3382 #undef TARGET_LEGITIMATE_CONSTANT_P
3383 #define TARGET_LEGITIMATE_CONSTANT_P nios2_legitimate_constant_p
3385 #undef TARGET_LEGITIMIZE_ADDRESS
3386 #define TARGET_LEGITIMIZE_ADDRESS nios2_legitimize_address
3388 #undef TARGET_DELEGITIMIZE_ADDRESS
3389 #define TARGET_DELEGITIMIZE_ADDRESS nios2_delegitimize_address
3391 #undef TARGET_LEGITIMATE_ADDRESS_P
3392 #define TARGET_LEGITIMATE_ADDRESS_P nios2_legitimate_address_p
3394 #undef TARGET_PREFERRED_RELOAD_CLASS
3395 #define TARGET_PREFERRED_RELOAD_CLASS nios2_preferred_reload_class
3397 #undef TARGET_RTX_COSTS
3398 #define TARGET_RTX_COSTS nios2_rtx_costs
3400 #undef TARGET_HAVE_TLS
3401 #define TARGET_HAVE_TLS TARGET_LINUX_ABI
3403 #undef TARGET_CANNOT_FORCE_CONST_MEM
3404 #define TARGET_CANNOT_FORCE_CONST_MEM nios2_cannot_force_const_mem
3406 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
3407 #define TARGET_ASM_OUTPUT_DWARF_DTPREL nios2_output_dwarf_dtprel
3409 #undef TARGET_PRINT_OPERAND
3410 #define TARGET_PRINT_OPERAND nios2_print_operand
3412 #undef TARGET_PRINT_OPERAND_ADDRESS
3413 #define TARGET_PRINT_OPERAND_ADDRESS nios2_print_operand_address
3415 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
3416 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA nios2_output_addr_const_extra
3418 #undef TARGET_ASM_FILE_END
3419 #define TARGET_ASM_FILE_END nios2_asm_file_end
3421 #undef TARGET_OPTION_OVERRIDE
3422 #define TARGET_OPTION_OVERRIDE nios2_option_override
3424 #undef TARGET_OPTION_SAVE
3425 #define TARGET_OPTION_SAVE nios2_option_save
3427 #undef TARGET_OPTION_RESTORE
3428 #define TARGET_OPTION_RESTORE nios2_option_restore
3430 #undef TARGET_SET_CURRENT_FUNCTION
3431 #define TARGET_SET_CURRENT_FUNCTION nios2_set_current_function
3433 #undef TARGET_OPTION_VALID_ATTRIBUTE_P
3434 #define TARGET_OPTION_VALID_ATTRIBUTE_P nios2_valid_target_attribute_p
3436 #undef TARGET_OPTION_PRAGMA_PARSE
3437 #define TARGET_OPTION_PRAGMA_PARSE nios2_pragma_target_parse
3439 #undef TARGET_MERGE_DECL_ATTRIBUTES
3440 #define TARGET_MERGE_DECL_ATTRIBUTES nios2_merge_decl_attributes
3442 struct gcc_target targetm
= TARGET_INITIALIZER
;
3444 #include "gt-nios2.h"