1 /* Target machine subroutines for Altera Nios II.
2 Copyright (C) 2012-2022 Free Software Foundation, Inc.
3 Contributed by Jonah Graham (jgraham@altera.com),
4 Will Reece (wreece@altera.com), and Jeff DaSilva (jdasilva@altera.com).
5 Contributed by Mentor Graphics, Inc.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published
11 by the Free Software Foundation; either version 3, or (at your
12 option) any later version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 #define IN_TARGET_CODE 1
27 #include "coretypes.h"
32 #include "stringpool.h"
41 #include "diagnostic-core.h"
43 #include "insn-attr.h"
50 #include "langhooks.h"
51 #include "stor-layout.h"
53 #include "tree-pass.h"
57 /* This file should be included last. */
58 #include "target-def.h"
60 /* Forward function declarations. */
61 static bool nios2_symbolic_constant_p (rtx
);
62 static bool prologue_saved_reg_p (unsigned);
63 static void nios2_load_pic_register (void);
64 static void nios2_register_custom_code (unsigned int, enum nios2_ccs_code
, int);
65 static const char *nios2_unspec_reloc_name (int);
66 static void nios2_register_builtin_fndecl (unsigned, tree
);
67 static rtx
nios2_ldst_parallel (bool, bool, bool, rtx
, int,
68 unsigned HOST_WIDE_INT
, bool);
69 static int nios2_address_cost (rtx
, machine_mode
, addr_space_t
, bool);
71 /* Threshold for data being put into the small data/bss area, instead
72 of the normal data area (references to the small data/bss area take
73 1 instruction, and use the global pointer, references to the normal
74 data area takes 2 instructions). */
75 unsigned HOST_WIDE_INT nios2_section_threshold
= NIOS2_DEFAULT_GVALUE
;
77 struct GTY (()) machine_function
79 /* Current frame information, to be filled in by nios2_compute_frame_layout
80 with register save masks, and offsets for the current function. */
82 /* Mask of registers to save. */
83 unsigned int save_mask
;
84 /* Number of bytes that the entire frame takes up. */
86 /* Number of bytes that variables take up. */
88 /* Number of bytes that outgoing arguments take up. */
90 /* Number of bytes needed to store registers in frame. */
92 /* Number of bytes used to store callee-saved registers. */
93 int callee_save_reg_size
;
94 /* Offset from new stack pointer to store registers. */
96 /* Offset from save_regs_offset to store frame pointer register. */
98 /* != 0 if function has a variable argument list. */
99 int uses_anonymous_args
;
100 /* != 0 if frame layout already calculated. */
104 /* State to track the assignment of custom codes to FPU/custom builtins. */
105 static enum nios2_ccs_code custom_code_status
[256];
106 static int custom_code_index
[256];
107 /* Set to true if any conflicts (re-use of a code between 0-255) are found. */
108 static bool custom_code_conflict
= false;
110 /* State for command-line options. */
111 regex_t nios2_gprel_sec_regex
;
112 regex_t nios2_r0rel_sec_regex
;
115 /* Definition of builtin function types for nios2. */
119 N2_FTYPE(1, (VOID)) \
120 N2_FTYPE(2, (DF, DF)) \
121 N2_FTYPE(3, (DF, DF, DF)) \
122 N2_FTYPE(2, (DF, SF)) \
123 N2_FTYPE(2, (DF, SI)) \
124 N2_FTYPE(2, (DF, UI)) \
125 N2_FTYPE(2, (SF, DF)) \
126 N2_FTYPE(2, (SF, SF)) \
127 N2_FTYPE(3, (SF, SF, SF)) \
128 N2_FTYPE(2, (SF, SI)) \
129 N2_FTYPE(2, (SF, UI)) \
130 N2_FTYPE(2, (SI, CVPTR)) \
131 N2_FTYPE(2, (SI, DF)) \
132 N2_FTYPE(3, (SI, DF, DF)) \
133 N2_FTYPE(2, (SI, SF)) \
134 N2_FTYPE(3, (SI, SF, SF)) \
135 N2_FTYPE(2, (SI, SI)) \
136 N2_FTYPE(3, (SI, SI, SI)) \
137 N2_FTYPE(3, (SI, VPTR, SI)) \
138 N2_FTYPE(2, (UI, CVPTR)) \
139 N2_FTYPE(2, (UI, DF)) \
140 N2_FTYPE(2, (UI, SF)) \
141 N2_FTYPE(2, (VOID, DF)) \
142 N2_FTYPE(2, (VOID, SF)) \
143 N2_FTYPE(2, (VOID, SI)) \
144 N2_FTYPE(3, (VOID, SI, SI)) \
145 N2_FTYPE(2, (VOID, VPTR)) \
146 N2_FTYPE(3, (VOID, VPTR, SI))
148 #define N2_FTYPE_OP1(R) N2_FTYPE_ ## R ## _VOID
149 #define N2_FTYPE_OP2(R, A1) N2_FTYPE_ ## R ## _ ## A1
150 #define N2_FTYPE_OP3(R, A1, A2) N2_FTYPE_ ## R ## _ ## A1 ## _ ## A2
152 /* Expand ftcode enumeration. */
154 #define N2_FTYPE(N,ARGS) N2_FTYPE_OP ## N ARGS,
160 /* Return the tree function type, based on the ftcode. */
162 nios2_ftype (enum nios2_ftcode ftcode
)
164 static tree types
[(int) N2_FTYPE_MAX
];
166 tree N2_TYPE_SF
= float_type_node
;
167 tree N2_TYPE_DF
= double_type_node
;
168 tree N2_TYPE_SI
= integer_type_node
;
169 tree N2_TYPE_UI
= unsigned_type_node
;
170 tree N2_TYPE_VOID
= void_type_node
;
172 static const_tree N2_TYPE_CVPTR
, N2_TYPE_VPTR
;
175 /* const volatile void *. */
177 = build_pointer_type (build_qualified_type (void_type_node
,
179 | TYPE_QUAL_VOLATILE
)));
180 /* volatile void *. */
182 = build_pointer_type (build_qualified_type (void_type_node
,
183 TYPE_QUAL_VOLATILE
));
185 if (types
[(int) ftcode
] == NULL_TREE
)
188 #define N2_FTYPE_ARGS1(R) N2_TYPE_ ## R
189 #define N2_FTYPE_ARGS2(R,A1) N2_TYPE_ ## R, N2_TYPE_ ## A1
190 #define N2_FTYPE_ARGS3(R,A1,A2) N2_TYPE_ ## R, N2_TYPE_ ## A1, N2_TYPE_ ## A2
191 #define N2_FTYPE(N,ARGS) \
192 case N2_FTYPE_OP ## N ARGS: \
193 types[(int) ftcode] \
194 = build_function_type_list (N2_FTYPE_ARGS ## N ARGS, NULL_TREE); \
198 default: gcc_unreachable ();
200 return types
[(int) ftcode
];
204 /* Definition of FPU instruction descriptions. */
206 struct nios2_fpu_insn_info
209 int num_operands
, *optvar
;
212 #define N2F_DFREQ 0x2
213 #define N2F_UNSAFE 0x4
214 #define N2F_FINITE 0x8
215 #define N2F_NO_ERRNO 0x10
217 enum insn_code icode
;
218 enum nios2_ftcode ftcode
;
221 /* Base macro for defining FPU instructions. */
222 #define N2FPU_INSN_DEF_BASE(insn, nop, flags, icode, args) \
223 { #insn, nop, &nios2_custom_ ## insn, OPT_mcustom_##insn##_, \
224 OPT_mno_custom_##insn, flags, CODE_FOR_ ## icode, \
225 N2_FTYPE_OP ## nop args }
227 /* Arithmetic and math functions; 2 or 3 operand FP operations. */
228 #define N2FPU_OP2(mode) (mode, mode)
229 #define N2FPU_OP3(mode) (mode, mode, mode)
230 #define N2FPU_INSN_DEF(code, icode, nop, flags, m, M) \
231 N2FPU_INSN_DEF_BASE (f ## code ## m, nop, flags, \
232 icode ## m ## f ## nop, N2FPU_OP ## nop (M ## F))
233 #define N2FPU_INSN_SF(code, nop, flags) \
234 N2FPU_INSN_DEF (code, code, nop, flags, s, S)
235 #define N2FPU_INSN_DF(code, nop, flags) \
236 N2FPU_INSN_DEF (code, code, nop, flags | N2F_DF, d, D)
238 /* Compare instructions, 3 operand FP operation with a SI result. */
239 #define N2FPU_CMP_DEF(code, flags, m, M) \
240 N2FPU_INSN_DEF_BASE (fcmp ## code ## m, 3, flags, \
241 nios2_s ## code ## m ## f, (SI, M ## F, M ## F))
242 #define N2FPU_CMP_SF(code) N2FPU_CMP_DEF (code, 0, s, S)
243 #define N2FPU_CMP_DF(code) N2FPU_CMP_DEF (code, N2F_DF, d, D)
245 /* The order of definition needs to be maintained consistent with
246 enum n2fpu_code in nios2-opts.h. */
247 struct nios2_fpu_insn_info nios2_fpu_insn
[] =
249 /* Single precision instructions. */
250 N2FPU_INSN_SF (add
, 3, 0),
251 N2FPU_INSN_SF (sub
, 3, 0),
252 N2FPU_INSN_SF (mul
, 3, 0),
253 N2FPU_INSN_SF (div
, 3, 0),
254 /* Due to textual difference between min/max and smin/smax. */
255 N2FPU_INSN_DEF (min
, smin
, 3, N2F_FINITE
, s
, S
),
256 N2FPU_INSN_DEF (max
, smax
, 3, N2F_FINITE
, s
, S
),
257 N2FPU_INSN_SF (neg
, 2, 0),
258 N2FPU_INSN_SF (abs
, 2, 0),
259 N2FPU_INSN_SF (sqrt
, 2, 0),
260 N2FPU_INSN_SF (sin
, 2, N2F_UNSAFE
),
261 N2FPU_INSN_SF (cos
, 2, N2F_UNSAFE
),
262 N2FPU_INSN_SF (tan
, 2, N2F_UNSAFE
),
263 N2FPU_INSN_SF (atan
, 2, N2F_UNSAFE
),
264 N2FPU_INSN_SF (exp
, 2, N2F_UNSAFE
),
265 N2FPU_INSN_SF (log
, 2, N2F_UNSAFE
),
266 /* Single precision compares. */
267 N2FPU_CMP_SF (eq
), N2FPU_CMP_SF (ne
),
268 N2FPU_CMP_SF (lt
), N2FPU_CMP_SF (le
),
269 N2FPU_CMP_SF (gt
), N2FPU_CMP_SF (ge
),
271 /* Double precision instructions. */
272 N2FPU_INSN_DF (add
, 3, 0),
273 N2FPU_INSN_DF (sub
, 3, 0),
274 N2FPU_INSN_DF (mul
, 3, 0),
275 N2FPU_INSN_DF (div
, 3, 0),
276 /* Due to textual difference between min/max and smin/smax. */
277 N2FPU_INSN_DEF (min
, smin
, 3, N2F_FINITE
, d
, D
),
278 N2FPU_INSN_DEF (max
, smax
, 3, N2F_FINITE
, d
, D
),
279 N2FPU_INSN_DF (neg
, 2, 0),
280 N2FPU_INSN_DF (abs
, 2, 0),
281 N2FPU_INSN_DF (sqrt
, 2, 0),
282 N2FPU_INSN_DF (sin
, 2, N2F_UNSAFE
),
283 N2FPU_INSN_DF (cos
, 2, N2F_UNSAFE
),
284 N2FPU_INSN_DF (tan
, 2, N2F_UNSAFE
),
285 N2FPU_INSN_DF (atan
, 2, N2F_UNSAFE
),
286 N2FPU_INSN_DF (exp
, 2, N2F_UNSAFE
),
287 N2FPU_INSN_DF (log
, 2, N2F_UNSAFE
),
288 /* Double precision compares. */
289 N2FPU_CMP_DF (eq
), N2FPU_CMP_DF (ne
),
290 N2FPU_CMP_DF (lt
), N2FPU_CMP_DF (le
),
291 N2FPU_CMP_DF (gt
), N2FPU_CMP_DF (ge
),
293 /* Conversion instructions. */
294 N2FPU_INSN_DEF_BASE (floatis
, 2, 0, floatsisf2
, (SF
, SI
)),
295 N2FPU_INSN_DEF_BASE (floatus
, 2, 0, floatunssisf2
, (SF
, UI
)),
296 N2FPU_INSN_DEF_BASE (floatid
, 2, 0, floatsidf2
, (DF
, SI
)),
297 N2FPU_INSN_DEF_BASE (floatud
, 2, 0, floatunssidf2
, (DF
, UI
)),
298 N2FPU_INSN_DEF_BASE (round
, 2, N2F_NO_ERRNO
, lroundsfsi2
, (SI
, SF
)),
299 N2FPU_INSN_DEF_BASE (fixsi
, 2, 0, fix_truncsfsi2
, (SI
, SF
)),
300 N2FPU_INSN_DEF_BASE (fixsu
, 2, 0, fixuns_truncsfsi2
, (UI
, SF
)),
301 N2FPU_INSN_DEF_BASE (fixdi
, 2, 0, fix_truncdfsi2
, (SI
, DF
)),
302 N2FPU_INSN_DEF_BASE (fixdu
, 2, 0, fixuns_truncdfsi2
, (UI
, DF
)),
303 N2FPU_INSN_DEF_BASE (fextsd
, 2, 0, extendsfdf2
, (DF
, SF
)),
304 N2FPU_INSN_DEF_BASE (ftruncds
, 2, 0, truncdfsf2
, (SF
, DF
)),
306 /* X, Y access instructions. */
307 N2FPU_INSN_DEF_BASE (fwrx
, 2, N2F_DFREQ
, nios2_fwrx
, (VOID
, DF
)),
308 N2FPU_INSN_DEF_BASE (fwry
, 2, N2F_DFREQ
, nios2_fwry
, (VOID
, SF
)),
309 N2FPU_INSN_DEF_BASE (frdxlo
, 1, N2F_DFREQ
, nios2_frdxlo
, (SF
)),
310 N2FPU_INSN_DEF_BASE (frdxhi
, 1, N2F_DFREQ
, nios2_frdxhi
, (SF
)),
311 N2FPU_INSN_DEF_BASE (frdy
, 1, N2F_DFREQ
, nios2_frdy
, (SF
))
314 /* Some macros for ease of access. */
315 #define N2FPU(code) nios2_fpu_insn[(int) code]
316 #define N2FPU_ENABLED_P(code) (N2FPU_N(code) >= 0)
317 #define N2FPU_N(code) (*N2FPU(code).optvar)
318 #define N2FPU_NAME(code) (N2FPU(code).name)
319 #define N2FPU_ICODE(code) (N2FPU(code).icode)
320 #define N2FPU_FTCODE(code) (N2FPU(code).ftcode)
321 #define N2FPU_FINITE_P(code) (N2FPU(code).flags & N2F_FINITE)
322 #define N2FPU_UNSAFE_P(code) (N2FPU(code).flags & N2F_UNSAFE)
323 #define N2FPU_NO_ERRNO_P(code) (N2FPU(code).flags & N2F_NO_ERRNO)
324 #define N2FPU_DOUBLE_P(code) (N2FPU(code).flags & N2F_DF)
325 #define N2FPU_DOUBLE_REQUIRED_P(code) (N2FPU(code).flags & N2F_DFREQ)
327 /* Same as above, but for cases where using only the op part is shorter. */
328 #define N2FPU_OP(op) N2FPU(n2fpu_ ## op)
329 #define N2FPU_OP_NAME(op) N2FPU_NAME(n2fpu_ ## op)
330 #define N2FPU_OP_ENABLED_P(op) N2FPU_ENABLED_P(n2fpu_ ## op)
332 /* Export the FPU insn enabled predicate to nios2.md. */
334 nios2_fpu_insn_enabled (enum n2fpu_code code
)
336 return N2FPU_ENABLED_P (code
);
339 /* Return true if COND comparison for mode MODE is enabled under current
343 nios2_fpu_compare_enabled (enum rtx_code cond
, machine_mode mode
)
348 case EQ
: return N2FPU_OP_ENABLED_P (fcmpeqs
);
349 case NE
: return N2FPU_OP_ENABLED_P (fcmpnes
);
350 case GT
: return N2FPU_OP_ENABLED_P (fcmpgts
);
351 case GE
: return N2FPU_OP_ENABLED_P (fcmpges
);
352 case LT
: return N2FPU_OP_ENABLED_P (fcmplts
);
353 case LE
: return N2FPU_OP_ENABLED_P (fcmples
);
356 else if (mode
== DFmode
)
359 case EQ
: return N2FPU_OP_ENABLED_P (fcmpeqd
);
360 case NE
: return N2FPU_OP_ENABLED_P (fcmpned
);
361 case GT
: return N2FPU_OP_ENABLED_P (fcmpgtd
);
362 case GE
: return N2FPU_OP_ENABLED_P (fcmpged
);
363 case LT
: return N2FPU_OP_ENABLED_P (fcmpltd
);
364 case LE
: return N2FPU_OP_ENABLED_P (fcmpled
);
370 /* Stack layout and calling conventions. */
372 #define NIOS2_STACK_ALIGN(LOC) \
373 (((LOC) + ((PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) - 1)) \
374 & ~((PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) - 1))
376 /* Return the bytes needed to compute the frame pointer from the current
379 nios2_compute_frame_layout (void)
382 unsigned int save_mask
= 0;
387 int callee_save_reg_size
;
389 if (cfun
->machine
->initialized
)
390 return cfun
->machine
->total_size
;
392 /* Calculate space needed for gp registers. */
394 for (regno
= 0; regno
<= LAST_GP_REG
; regno
++)
395 if (prologue_saved_reg_p (regno
))
397 save_mask
|= 1 << regno
;
401 /* If we are saving any callee-save register, then assume
402 push.n/pop.n should be used. Make sure RA is saved, and
403 contiguous registers starting from r16-- are all saved. */
404 if (TARGET_HAS_CDX
&& save_reg_size
!= 0)
406 if ((save_mask
& (1 << RA_REGNO
)) == 0)
408 save_mask
|= 1 << RA_REGNO
;
412 for (regno
= 23; regno
>= 16; regno
--)
413 if ((save_mask
& (1 << regno
)) != 0)
415 /* Starting from highest numbered callee-saved
416 register that is used, make sure all regs down
417 to r16 is saved, to maintain contiguous range
420 for (i
= regno
- 1; i
>= 16; i
--)
421 if ((save_mask
& (1 << i
)) == 0)
430 callee_save_reg_size
= save_reg_size
;
432 /* If we call eh_return, we need to save the EH data registers. */
433 if (crtl
->calls_eh_return
)
438 for (i
= 0; (r
= EH_RETURN_DATA_REGNO (i
)) != INVALID_REGNUM
; i
++)
439 if (!(save_mask
& (1 << r
)))
446 cfun
->machine
->fp_save_offset
= 0;
447 if (save_mask
& (1 << HARD_FRAME_POINTER_REGNUM
))
449 int fp_save_offset
= 0;
450 for (regno
= 0; regno
< HARD_FRAME_POINTER_REGNUM
; regno
++)
451 if (save_mask
& (1 << regno
))
454 cfun
->machine
->fp_save_offset
= fp_save_offset
;
457 var_size
= NIOS2_STACK_ALIGN (get_frame_size ());
458 out_args_size
= NIOS2_STACK_ALIGN (crtl
->outgoing_args_size
);
459 total_size
= var_size
+ out_args_size
;
461 save_reg_size
= NIOS2_STACK_ALIGN (save_reg_size
);
462 total_size
+= save_reg_size
;
463 total_size
+= NIOS2_STACK_ALIGN (crtl
->args
.pretend_args_size
);
465 /* Save other computed information. */
466 cfun
->machine
->save_mask
= save_mask
;
467 cfun
->machine
->total_size
= total_size
;
468 cfun
->machine
->var_size
= var_size
;
469 cfun
->machine
->args_size
= out_args_size
;
470 cfun
->machine
->save_reg_size
= save_reg_size
;
471 cfun
->machine
->callee_save_reg_size
= callee_save_reg_size
;
472 cfun
->machine
->initialized
= reload_completed
;
473 cfun
->machine
->save_regs_offset
= out_args_size
+ var_size
;
478 /* Generate save/restore of register REGNO at SP + OFFSET. Used by the
479 prologue/epilogue expand routines. */
481 save_reg (int regno
, unsigned offset
)
483 rtx reg
= gen_rtx_REG (SImode
, regno
);
484 rtx addr
= plus_constant (Pmode
, stack_pointer_rtx
, offset
, false);
485 rtx_insn
*insn
= emit_move_insn (gen_frame_mem (Pmode
, addr
), reg
);
486 RTX_FRAME_RELATED_P (insn
) = 1;
490 restore_reg (int regno
, unsigned offset
)
492 rtx reg
= gen_rtx_REG (SImode
, regno
);
493 rtx addr
= plus_constant (Pmode
, stack_pointer_rtx
, offset
, false);
494 rtx_insn
*insn
= emit_move_insn (reg
, gen_frame_mem (Pmode
, addr
));
495 /* Tag epilogue unwind note. */
496 add_reg_note (insn
, REG_CFA_RESTORE
, reg
);
497 RTX_FRAME_RELATED_P (insn
) = 1;
500 /* This routine tests for the base register update SET in load/store
501 multiple RTL insns, used in pop_operation_p and ldstwm_operation_p. */
503 base_reg_adjustment_p (rtx set
, rtx
*base_reg
, rtx
*offset
)
505 if (GET_CODE (set
) == SET
506 && REG_P (SET_DEST (set
))
507 && GET_CODE (SET_SRC (set
)) == PLUS
508 && REG_P (XEXP (SET_SRC (set
), 0))
509 && rtx_equal_p (SET_DEST (set
), XEXP (SET_SRC (set
), 0))
510 && CONST_INT_P (XEXP (SET_SRC (set
), 1)))
512 *base_reg
= XEXP (SET_SRC (set
), 0);
513 *offset
= XEXP (SET_SRC (set
), 1);
519 /* Does the CFA note work for push/pop prologue/epilogue instructions. */
521 nios2_create_cfa_notes (rtx_insn
*insn
, bool epilogue_p
)
524 rtx base_reg
, offset
, elt
, pat
= PATTERN (insn
);
527 elt
= XVECEXP (pat
, 0, 0);
528 if (GET_CODE (elt
) == RETURN
)
530 elt
= XVECEXP (pat
, 0, i
);
531 if (base_reg_adjustment_p (elt
, &base_reg
, &offset
))
533 add_reg_note (insn
, REG_CFA_ADJUST_CFA
, copy_rtx (elt
));
536 for (; i
< XVECLEN (pat
, 0); i
++)
538 elt
= SET_DEST (XVECEXP (pat
, 0, i
));
539 gcc_assert (REG_P (elt
));
540 add_reg_note (insn
, REG_CFA_RESTORE
, elt
);
545 /* Tag each of the prologue sets. */
546 for (i
= 0; i
< XVECLEN (pat
, 0); i
++)
547 RTX_FRAME_RELATED_P (XVECEXP (pat
, 0, i
)) = 1;
551 /* Temp regno used inside prologue/epilogue. */
552 #define TEMP_REG_NUM 8
554 /* Emit conditional trap for checking stack limit. SIZE is the number of
555 additional bytes required.
557 GDB prologue analysis depends on this generating a direct comparison
558 to the SP register, so the adjustment to add SIZE needs to be done on
559 the other operand to the comparison. Use TEMP_REG_NUM as a temporary,
562 nios2_emit_stack_limit_check (int size
)
566 if (GET_CODE (stack_limit_rtx
) == SYMBOL_REF
)
568 /* This generates a %hiadj/%lo pair with the constant size
569 add handled by the relocations. */
570 sum
= gen_rtx_REG (Pmode
, TEMP_REG_NUM
);
571 emit_move_insn (sum
, plus_constant (Pmode
, stack_limit_rtx
, size
));
573 else if (!REG_P (stack_limit_rtx
))
574 sorry ("Unknown form for stack limit expression");
576 sum
= stack_limit_rtx
;
577 else if (SMALL_INT (size
))
579 sum
= gen_rtx_REG (Pmode
, TEMP_REG_NUM
);
580 emit_move_insn (sum
, plus_constant (Pmode
, stack_limit_rtx
, size
));
584 sum
= gen_rtx_REG (Pmode
, TEMP_REG_NUM
);
585 emit_move_insn (sum
, gen_int_mode (size
, Pmode
));
586 emit_insn (gen_add2_insn (sum
, stack_limit_rtx
));
589 emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode
, stack_pointer_rtx
, sum
),
590 stack_pointer_rtx
, sum
, GEN_INT (3)));
594 nios2_emit_add_constant (rtx reg
, HOST_WIDE_INT immed
)
597 if (SMALL_INT (immed
))
598 insn
= emit_insn (gen_add2_insn (reg
, gen_int_mode (immed
, Pmode
)));
601 rtx tmp
= gen_rtx_REG (Pmode
, TEMP_REG_NUM
);
602 emit_move_insn (tmp
, gen_int_mode (immed
, Pmode
));
603 insn
= emit_insn (gen_add2_insn (reg
, tmp
));
609 nios2_adjust_stack (int sp_adjust
, bool epilogue_p
)
611 enum reg_note note_kind
= REG_NOTE_MAX
;
612 rtx_insn
*insn
= NULL
;
615 if (SMALL_INT (sp_adjust
))
616 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
,
617 gen_int_mode (sp_adjust
, Pmode
)));
620 rtx tmp
= gen_rtx_REG (Pmode
, TEMP_REG_NUM
);
621 emit_move_insn (tmp
, gen_int_mode (sp_adjust
, Pmode
));
622 insn
= emit_insn (gen_add2_insn (stack_pointer_rtx
, tmp
));
623 /* Attach a note indicating what happened. */
625 note_kind
= REG_FRAME_RELATED_EXPR
;
628 note_kind
= REG_CFA_ADJUST_CFA
;
629 if (note_kind
!= REG_NOTE_MAX
)
631 rtx cfa_adj
= gen_rtx_SET (stack_pointer_rtx
,
632 plus_constant (Pmode
, stack_pointer_rtx
,
634 add_reg_note (insn
, note_kind
, cfa_adj
);
636 RTX_FRAME_RELATED_P (insn
) = 1;
642 nios2_expand_prologue (void)
645 int total_frame_size
, save_offset
;
646 int sp_offset
; /* offset from base_reg to final stack value. */
647 int save_regs_base
; /* offset from base_reg to register save area. */
650 total_frame_size
= nios2_compute_frame_layout ();
652 if (flag_stack_usage_info
)
653 current_function_static_stack_size
= total_frame_size
;
655 /* When R2 CDX push.n/stwm is available, arrange for stack frame to be built
658 && (cfun
->machine
->save_reg_size
!= 0
659 || cfun
->machine
->uses_anonymous_args
))
661 unsigned int regmask
= cfun
->machine
->save_mask
;
662 unsigned int callee_save_regs
= regmask
& 0xffff0000;
663 unsigned int caller_save_regs
= regmask
& 0x0000ffff;
665 int pretend_args_size
= NIOS2_STACK_ALIGN (crtl
->args
.pretend_args_size
);
667 gen_frame_mem (SImode
, plus_constant (Pmode
, stack_pointer_rtx
, -4));
669 /* Check that there is room for the entire stack frame before doing
670 any SP adjustments or pushes. */
671 if (crtl
->limit_stack
)
672 nios2_emit_stack_limit_check (total_frame_size
);
674 if (pretend_args_size
)
676 if (cfun
->machine
->uses_anonymous_args
)
678 /* Emit a stwm to push copy of argument registers onto
679 the stack for va_arg processing. */
680 unsigned int r
, mask
= 0, n
= pretend_args_size
/ 4;
681 for (r
= LAST_ARG_REGNO
- n
+ 1; r
<= LAST_ARG_REGNO
; r
++)
683 insn
= emit_insn (nios2_ldst_parallel
684 (false, false, false, stack_mem
,
685 -pretend_args_size
, mask
, false));
686 /* Tag first SP adjustment as frame-related. */
687 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn
), 0, 0)) = 1;
688 RTX_FRAME_RELATED_P (insn
) = 1;
691 nios2_adjust_stack (-pretend_args_size
, false);
693 if (callee_save_regs
)
695 /* Emit a push.n to save registers and optionally allocate
696 push_immed extra bytes on the stack. */
698 if (caller_save_regs
)
699 /* Can't allocate extra stack space yet. */
701 else if (cfun
->machine
->save_regs_offset
<= 60)
702 /* Stack adjustment fits entirely in the push.n. */
703 push_immed
= cfun
->machine
->save_regs_offset
;
704 else if (frame_pointer_needed
705 && cfun
->machine
->fp_save_offset
== 0)
706 /* Deferring the entire stack adjustment until later
707 allows us to use a mov.n instead of a 32-bit addi
708 instruction to set the frame pointer. */
711 /* Splitting the stack adjustment between the push.n
712 and an explicit adjustment makes it more likely that
713 we can use spdeci.n for the explicit part. */
715 sp_adjust
= -(cfun
->machine
->callee_save_reg_size
+ push_immed
);
716 insn
= emit_insn (nios2_ldst_parallel (false, false, false,
717 stack_mem
, sp_adjust
,
718 callee_save_regs
, false));
719 nios2_create_cfa_notes (insn
, false);
720 RTX_FRAME_RELATED_P (insn
) = 1;
723 if (caller_save_regs
)
725 /* Emit a stwm to save the EH data regs, r4-r7. */
726 int caller_save_size
= (cfun
->machine
->save_reg_size
727 - cfun
->machine
->callee_save_reg_size
);
728 gcc_assert ((caller_save_regs
& ~0xf0) == 0);
729 insn
= emit_insn (nios2_ldst_parallel
730 (false, false, false, stack_mem
,
731 -caller_save_size
, caller_save_regs
, false));
732 nios2_create_cfa_notes (insn
, false);
733 RTX_FRAME_RELATED_P (insn
) = 1;
736 save_regs_base
= push_immed
;
737 sp_offset
= -(cfun
->machine
->save_regs_offset
- push_immed
);
739 /* The non-CDX cases decrement the stack pointer, to prepare for individual
740 register saves to the stack. */
741 else if (!SMALL_INT (total_frame_size
))
743 /* We need an intermediary point, this will point at the spill block. */
744 nios2_adjust_stack (cfun
->machine
->save_regs_offset
- total_frame_size
,
747 sp_offset
= -cfun
->machine
->save_regs_offset
;
748 if (crtl
->limit_stack
)
749 nios2_emit_stack_limit_check (cfun
->machine
->save_regs_offset
);
751 else if (total_frame_size
)
753 nios2_adjust_stack (-total_frame_size
, false);
754 save_regs_base
= cfun
->machine
->save_regs_offset
;
756 if (crtl
->limit_stack
)
757 nios2_emit_stack_limit_check (0);
760 save_regs_base
= sp_offset
= 0;
762 /* Save the registers individually in the non-CDX case. */
765 save_offset
= save_regs_base
+ cfun
->machine
->save_reg_size
;
767 for (regno
= LAST_GP_REG
; regno
> 0; regno
--)
768 if (cfun
->machine
->save_mask
& (1 << regno
))
771 save_reg (regno
, save_offset
);
775 /* Set the hard frame pointer. */
776 if (frame_pointer_needed
)
778 int fp_save_offset
= save_regs_base
+ cfun
->machine
->fp_save_offset
;
781 ? emit_move_insn (hard_frame_pointer_rtx
, stack_pointer_rtx
)
782 : emit_insn (gen_add3_insn (hard_frame_pointer_rtx
,
784 gen_int_mode (fp_save_offset
, Pmode
))));
785 RTX_FRAME_RELATED_P (insn
) = 1;
788 /* Allocate sp_offset more bytes in the stack frame. */
789 nios2_adjust_stack (sp_offset
, false);
791 /* Load the PIC register if needed. */
792 if (crtl
->uses_pic_offset_table
)
793 nios2_load_pic_register ();
795 /* If we are profiling, make sure no instructions are scheduled before
796 the call to mcount. */
798 emit_insn (gen_blockage ());
802 nios2_expand_epilogue (bool sibcall_p
)
806 int total_frame_size
;
807 int sp_adjust
, save_offset
;
810 if (!sibcall_p
&& nios2_can_use_return_insn ())
812 emit_jump_insn (gen_return ());
816 emit_insn (gen_blockage ());
818 total_frame_size
= nios2_compute_frame_layout ();
819 if (frame_pointer_needed
)
821 /* Recover the stack pointer. */
823 (cfun
->machine
->fp_save_offset
== 0
824 ? emit_move_insn (stack_pointer_rtx
, hard_frame_pointer_rtx
)
825 : emit_insn (gen_add3_insn
826 (stack_pointer_rtx
, hard_frame_pointer_rtx
,
827 gen_int_mode (-cfun
->machine
->fp_save_offset
, Pmode
))));
828 cfa_adj
= plus_constant (Pmode
, stack_pointer_rtx
,
830 - cfun
->machine
->save_regs_offset
));
831 add_reg_note (insn
, REG_CFA_DEF_CFA
, cfa_adj
);
832 RTX_FRAME_RELATED_P (insn
) = 1;
835 sp_adjust
= total_frame_size
- cfun
->machine
->save_regs_offset
;
837 else if (!SMALL_INT (total_frame_size
))
839 nios2_adjust_stack (cfun
->machine
->save_regs_offset
, true);
841 sp_adjust
= total_frame_size
- cfun
->machine
->save_regs_offset
;
845 save_offset
= cfun
->machine
->save_regs_offset
;
846 sp_adjust
= total_frame_size
;
851 /* Generate individual register restores. */
852 save_offset
+= cfun
->machine
->save_reg_size
;
854 for (regno
= LAST_GP_REG
; regno
> 0; regno
--)
855 if (cfun
->machine
->save_mask
& (1 << regno
))
858 restore_reg (regno
, save_offset
);
860 nios2_adjust_stack (sp_adjust
, true);
862 else if (cfun
->machine
->save_reg_size
== 0)
864 /* Nothing to restore, just recover the stack position. */
865 nios2_adjust_stack (sp_adjust
, true);
869 /* Emit CDX pop.n/ldwm to restore registers and optionally return. */
870 unsigned int regmask
= cfun
->machine
->save_mask
;
871 unsigned int callee_save_regs
= regmask
& 0xffff0000;
872 unsigned int caller_save_regs
= regmask
& 0x0000ffff;
873 int callee_save_size
= cfun
->machine
->callee_save_reg_size
;
874 int caller_save_size
= cfun
->machine
->save_reg_size
- callee_save_size
;
875 int pretend_args_size
= NIOS2_STACK_ALIGN (crtl
->args
.pretend_args_size
);
876 bool ret_p
= (!pretend_args_size
&& !crtl
->calls_eh_return
879 if (!ret_p
|| caller_save_size
> 0)
880 sp_adjust
= save_offset
;
882 sp_adjust
= (save_offset
> 60 ? save_offset
- 60 : 0);
884 save_offset
-= sp_adjust
;
886 nios2_adjust_stack (sp_adjust
, true);
888 if (caller_save_regs
)
890 /* Emit a ldwm to restore EH data regs. */
891 rtx stack_mem
= gen_frame_mem (SImode
, stack_pointer_rtx
);
892 insn
= emit_insn (nios2_ldst_parallel
893 (true, true, true, stack_mem
,
894 caller_save_size
, caller_save_regs
, false));
895 RTX_FRAME_RELATED_P (insn
) = 1;
896 nios2_create_cfa_notes (insn
, true);
899 if (callee_save_regs
)
901 int sp_adjust
= save_offset
+ callee_save_size
;
905 /* Emit a pop.n to restore regs and return. */
907 gen_frame_mem (SImode
,
908 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
909 gen_int_mode (sp_adjust
- 4,
912 emit_jump_insn (nios2_ldst_parallel (true, false, false,
913 stack_mem
, sp_adjust
,
914 callee_save_regs
, ret_p
));
915 RTX_FRAME_RELATED_P (insn
) = 1;
916 /* No need to attach CFA notes since we cannot step over
922 /* If no return, we have to use the ldwm form. */
923 stack_mem
= gen_frame_mem (SImode
, stack_pointer_rtx
);
925 emit_insn (nios2_ldst_parallel (true, true, true,
926 stack_mem
, sp_adjust
,
927 callee_save_regs
, ret_p
));
928 RTX_FRAME_RELATED_P (insn
) = 1;
929 nios2_create_cfa_notes (insn
, true);
933 if (pretend_args_size
)
934 nios2_adjust_stack (pretend_args_size
, true);
937 /* Add in the __builtin_eh_return stack adjustment. */
938 if (crtl
->calls_eh_return
)
939 emit_insn (gen_add2_insn (stack_pointer_rtx
, EH_RETURN_STACKADJ_RTX
));
942 emit_jump_insn (gen_simple_return ());
946 nios2_expand_return (void)
948 /* If CDX is available, generate a pop.n instruction to do both
949 the stack pop and return. */
952 int total_frame_size
= nios2_compute_frame_layout ();
953 int sp_adjust
= (cfun
->machine
->save_regs_offset
954 + cfun
->machine
->callee_save_reg_size
);
955 gcc_assert (sp_adjust
== total_frame_size
);
959 gen_frame_mem (SImode
,
960 plus_constant (Pmode
, stack_pointer_rtx
,
961 sp_adjust
- 4, false));
963 emit_jump_insn (nios2_ldst_parallel (true, false, false,
965 cfun
->machine
->save_mask
,
967 RTX_FRAME_RELATED_P (insn
) = 1;
968 /* No need to create CFA notes since we can't step over
976 /* Implement RETURN_ADDR_RTX. Note, we do not support moving
977 back to a previous frame. */
979 nios2_get_return_address (int count
)
984 return get_hard_reg_initial_val (Pmode
, RA_REGNO
);
987 /* Emit code to change the current function's return address to
988 ADDRESS. SCRATCH is available as a scratch register, if needed.
989 ADDRESS and SCRATCH are both word-mode GPRs. */
991 nios2_set_return_address (rtx address
, rtx scratch
)
993 nios2_compute_frame_layout ();
994 if (cfun
->machine
->save_mask
& (1 << RA_REGNO
))
996 unsigned offset
= cfun
->machine
->save_reg_size
- 4;
999 if (frame_pointer_needed
)
1000 base
= hard_frame_pointer_rtx
;
1003 base
= stack_pointer_rtx
;
1004 offset
+= cfun
->machine
->save_regs_offset
;
1006 if (!SMALL_INT (offset
))
1008 emit_move_insn (scratch
, gen_int_mode (offset
, Pmode
));
1009 emit_insn (gen_add2_insn (scratch
, base
));
1015 base
= plus_constant (Pmode
, base
, offset
);
1016 emit_move_insn (gen_rtx_MEM (Pmode
, base
), address
);
1019 emit_move_insn (gen_rtx_REG (Pmode
, RA_REGNO
), address
);
1022 /* Implement FUNCTION_PROFILER macro. */
1024 nios2_function_profiler (FILE *file
, int labelno ATTRIBUTE_UNUSED
)
1026 fprintf (file
, "\tmov\tr8, ra\n");
1029 fprintf (file
, "\tnextpc\tr2\n");
1030 fprintf (file
, "\t1: movhi\tr3, %%hiadj(_gp_got - 1b)\n");
1031 fprintf (file
, "\taddi\tr3, r3, %%lo(_gp_got - 1b)\n");
1032 fprintf (file
, "\tadd\tr2, r2, r3\n");
1033 fprintf (file
, "\tldw\tr2, %%call(_mcount)(r2)\n");
1034 fprintf (file
, "\tcallr\tr2\n");
1036 else if (flag_pic
== 2)
1038 fprintf (file
, "\tnextpc\tr2\n");
1039 fprintf (file
, "\t1: movhi\tr3, %%hiadj(_gp_got - 1b)\n");
1040 fprintf (file
, "\taddi\tr3, r3, %%lo(_gp_got - 1b)\n");
1041 fprintf (file
, "\tadd\tr2, r2, r3\n");
1042 fprintf (file
, "\tmovhi\tr3, %%call_hiadj(_mcount)\n");
1043 fprintf (file
, "\taddi\tr3, r3, %%call_lo(_mcount)\n");
1044 fprintf (file
, "\tadd\tr3, r2, r3\n");
1045 fprintf (file
, "\tldw\tr2, 0(r3)\n");
1046 fprintf (file
, "\tcallr\tr2\n");
1049 fprintf (file
, "\tcall\t_mcount\n");
1050 fprintf (file
, "\tmov\tra, r8\n");
1053 /* Dump stack layout. */
1055 nios2_dump_frame_layout (FILE *file
)
1057 fprintf (file
, "\t%s Current Frame Info\n", ASM_COMMENT_START
);
1058 fprintf (file
, "\t%s total_size = %d\n", ASM_COMMENT_START
,
1059 cfun
->machine
->total_size
);
1060 fprintf (file
, "\t%s var_size = %d\n", ASM_COMMENT_START
,
1061 cfun
->machine
->var_size
);
1062 fprintf (file
, "\t%s args_size = %d\n", ASM_COMMENT_START
,
1063 cfun
->machine
->args_size
);
1064 fprintf (file
, "\t%s save_reg_size = %d\n", ASM_COMMENT_START
,
1065 cfun
->machine
->save_reg_size
);
1066 fprintf (file
, "\t%s initialized = %d\n", ASM_COMMENT_START
,
1067 cfun
->machine
->initialized
);
1068 fprintf (file
, "\t%s save_regs_offset = %d\n", ASM_COMMENT_START
,
1069 cfun
->machine
->save_regs_offset
);
1070 fprintf (file
, "\t%s is_leaf = %d\n", ASM_COMMENT_START
,
1072 fprintf (file
, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START
,
1073 frame_pointer_needed
);
1074 fprintf (file
, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START
,
1075 crtl
->args
.pretend_args_size
);
1078 /* Return true if REGNO should be saved in the prologue. */
1080 prologue_saved_reg_p (unsigned regno
)
1082 gcc_assert (GP_REG_P (regno
));
1084 if (df_regs_ever_live_p (regno
) && !call_used_or_fixed_reg_p (regno
))
1087 if (regno
== HARD_FRAME_POINTER_REGNUM
&& frame_pointer_needed
)
1090 if (regno
== PIC_OFFSET_TABLE_REGNUM
&& crtl
->uses_pic_offset_table
)
1093 if (regno
== RA_REGNO
&& df_regs_ever_live_p (RA_REGNO
))
1099 /* Implement TARGET_CAN_ELIMINATE. */
1101 nios2_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
1103 if (to
== STACK_POINTER_REGNUM
)
1104 return !frame_pointer_needed
;
1108 /* Implement INITIAL_ELIMINATION_OFFSET macro. */
1110 nios2_initial_elimination_offset (int from
, int to
)
1114 nios2_compute_frame_layout ();
1116 /* Set OFFSET to the offset from the stack pointer. */
1119 case FRAME_POINTER_REGNUM
:
1120 /* This is the high end of the local variable storage, not the
1121 hard frame pointer. */
1122 offset
= cfun
->machine
->args_size
+ cfun
->machine
->var_size
;
1125 case ARG_POINTER_REGNUM
:
1126 offset
= cfun
->machine
->total_size
;
1127 offset
-= crtl
->args
.pretend_args_size
;
1134 /* If we are asked for the frame pointer offset, then adjust OFFSET
1135 by the offset from the frame pointer to the stack pointer. */
1136 if (to
== HARD_FRAME_POINTER_REGNUM
)
1137 offset
-= (cfun
->machine
->save_regs_offset
1138 + cfun
->machine
->fp_save_offset
);
1143 /* Return nonzero if this function is known to have a null epilogue.
1144 This allows the optimizer to omit jumps to jumps if no stack
1147 nios2_can_use_return_insn (void)
1149 int total_frame_size
;
1151 if (!reload_completed
|| crtl
->profile
)
1154 total_frame_size
= nios2_compute_frame_layout ();
1156 /* If CDX is available, check if we can return using a
1157 single pop.n instruction. */
1159 && !frame_pointer_needed
1160 && cfun
->machine
->save_regs_offset
<= 60
1161 && (cfun
->machine
->save_mask
& 0x80000000) != 0
1162 && (cfun
->machine
->save_mask
& 0xffff) == 0
1163 && crtl
->args
.pretend_args_size
== 0)
1166 return total_frame_size
== 0;
1170 /* Check and signal some warnings/errors on FPU insn options. */
1172 nios2_custom_check_insns (void)
1175 bool errors
= false;
1177 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
1178 if (N2FPU_ENABLED_P (i
) && N2FPU_DOUBLE_P (i
))
1180 for (j
= 0; j
< ARRAY_SIZE (nios2_fpu_insn
); j
++)
1181 if (N2FPU_DOUBLE_REQUIRED_P (j
) && ! N2FPU_ENABLED_P (j
))
1183 error ("switch %<-mcustom-%s%> is required for "
1184 "double-precision floating-point", N2FPU_NAME (j
));
1190 if (errors
|| custom_code_conflict
)
1191 fatal_error (input_location
,
1192 "conflicting use of %<-mcustom%> switches, "
1193 "target attributes, "
1194 "and/or %<__builtin_custom_%> functions");
1198 nios2_set_fpu_custom_code (enum n2fpu_code code
, int n
, bool override_p
)
1200 if (override_p
|| N2FPU_N (code
) == -1)
1202 nios2_register_custom_code (n
, CCS_FPU
, (int) code
);
1205 /* Type to represent a standard FPU config. */
1206 struct nios2_fpu_config
1209 bool set_sp_constants
;
1210 int code
[n2fpu_code_num
];
1213 #define NIOS2_FPU_CONFIG_NUM 4
1214 static struct nios2_fpu_config custom_fpu_config
[NIOS2_FPU_CONFIG_NUM
];
1217 nios2_init_fpu_configs (void)
1219 struct nios2_fpu_config
* cfg
;
1221 #define NEXT_FPU_CONFIG \
1223 cfg = &custom_fpu_config[i++]; \
1224 memset (cfg, -1, sizeof (struct nios2_fpu_config));\
1229 cfg
->set_sp_constants
= true;
1230 cfg
->code
[n2fpu_fmuls
] = 252;
1231 cfg
->code
[n2fpu_fadds
] = 253;
1232 cfg
->code
[n2fpu_fsubs
] = 254;
1236 cfg
->set_sp_constants
= true;
1237 cfg
->code
[n2fpu_fmuls
] = 252;
1238 cfg
->code
[n2fpu_fadds
] = 253;
1239 cfg
->code
[n2fpu_fsubs
] = 254;
1240 cfg
->code
[n2fpu_fdivs
] = 255;
1244 cfg
->set_sp_constants
= true;
1245 cfg
->code
[n2fpu_floatus
] = 243;
1246 cfg
->code
[n2fpu_fixsi
] = 244;
1247 cfg
->code
[n2fpu_floatis
] = 245;
1248 cfg
->code
[n2fpu_fcmpgts
] = 246;
1249 cfg
->code
[n2fpu_fcmples
] = 249;
1250 cfg
->code
[n2fpu_fcmpeqs
] = 250;
1251 cfg
->code
[n2fpu_fcmpnes
] = 251;
1252 cfg
->code
[n2fpu_fmuls
] = 252;
1253 cfg
->code
[n2fpu_fadds
] = 253;
1254 cfg
->code
[n2fpu_fsubs
] = 254;
1255 cfg
->code
[n2fpu_fdivs
] = 255;
1259 cfg
->code
[n2fpu_fabss
] = 224;
1260 cfg
->code
[n2fpu_fnegs
] = 225;
1261 cfg
->code
[n2fpu_fcmpnes
] = 226;
1262 cfg
->code
[n2fpu_fcmpeqs
] = 227;
1263 cfg
->code
[n2fpu_fcmpges
] = 228;
1264 cfg
->code
[n2fpu_fcmpgts
] = 229;
1265 cfg
->code
[n2fpu_fcmples
] = 230;
1266 cfg
->code
[n2fpu_fcmplts
] = 231;
1267 cfg
->code
[n2fpu_fmaxs
] = 232;
1268 cfg
->code
[n2fpu_fmins
] = 233;
1269 cfg
->code
[n2fpu_round
] = 248;
1270 cfg
->code
[n2fpu_fixsi
] = 249;
1271 cfg
->code
[n2fpu_floatis
] = 250;
1272 cfg
->code
[n2fpu_fsqrts
] = 251;
1273 cfg
->code
[n2fpu_fmuls
] = 252;
1274 cfg
->code
[n2fpu_fadds
] = 253;
1275 cfg
->code
[n2fpu_fsubs
] = 254;
1276 cfg
->code
[n2fpu_fdivs
] = 255;
1278 #undef NEXT_FPU_CONFIG
1279 gcc_assert (i
== NIOS2_FPU_CONFIG_NUM
);
1282 static struct nios2_fpu_config
*
1283 nios2_match_custom_fpu_cfg (const char *cfgname
, const char *endp
)
1286 for (i
= 0; i
< NIOS2_FPU_CONFIG_NUM
; i
++)
1288 bool match
= !(endp
!= NULL
1289 ? strncmp (custom_fpu_config
[i
].name
, cfgname
,
1291 : strcmp (custom_fpu_config
[i
].name
, cfgname
));
1293 return &custom_fpu_config
[i
];
1298 /* Use CFGNAME to lookup FPU config, ENDP if not NULL marks end of string.
1299 OVERRIDE is true if loaded config codes should overwrite current state. */
1301 nios2_handle_custom_fpu_cfg (const char *cfgname
, const char *endp
,
1304 struct nios2_fpu_config
*cfg
= nios2_match_custom_fpu_cfg (cfgname
, endp
);
1308 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
1309 if (cfg
->code
[i
] >= 0)
1310 nios2_set_fpu_custom_code ((enum n2fpu_code
) i
, cfg
->code
[i
],
1312 if (cfg
->set_sp_constants
)
1313 flag_single_precision_constant
= 1;
1316 warning (0, "ignoring unrecognized switch %<-mcustom-fpu-cfg%> "
1317 "value %<%s%>", cfgname
);
1319 /* Guard against errors in the standard configurations. */
1320 nios2_custom_check_insns ();
1323 /* Check individual FPU insn options, and register custom code. */
1325 nios2_handle_custom_fpu_insn_option (int fpu_insn_index
)
1327 int param
= N2FPU_N (fpu_insn_index
);
1329 if (param
>= 0 && param
<= 255)
1330 nios2_register_custom_code (param
, CCS_FPU
, fpu_insn_index
);
1332 /* Valid values are 0-255, but also allow -1 so that the
1333 -mno-custom-<opt> switches work. */
1334 else if (param
!= -1)
1335 error ("switch %<-mcustom-%s%> value %d must be between 0 and 255",
1336 N2FPU_NAME (fpu_insn_index
), param
);
1339 /* Allocate a chunk of memory for per-function machine-dependent data. */
1340 static struct machine_function
*
1341 nios2_init_machine_status (void)
1343 return ggc_cleared_alloc
<machine_function
> ();
1346 /* Implement TARGET_OPTION_OVERRIDE. */
1348 nios2_option_override (void)
1352 #ifdef SUBTARGET_OVERRIDE_OPTIONS
1353 SUBTARGET_OVERRIDE_OPTIONS
;
1356 /* Check for unsupported options. */
1357 if (flag_pic
&& !TARGET_LINUX_ABI
)
1358 sorry ("position-independent code requires the Linux ABI");
1359 if (flag_pic
&& stack_limit_rtx
1360 && GET_CODE (stack_limit_rtx
) == SYMBOL_REF
)
1361 sorry ("PIC support for %<-fstack-limit-symbol%>");
1363 /* Function to allocate machine-dependent function status. */
1364 init_machine_status
= &nios2_init_machine_status
;
1366 nios2_section_threshold
1367 = (OPTION_SET_P (g_switch_value
)
1368 ? g_switch_value
: NIOS2_DEFAULT_GVALUE
);
1370 if (nios2_gpopt_option
== gpopt_unspecified
)
1372 /* Default to -mgpopt unless -fpic or -fPIC. */
1374 nios2_gpopt_option
= gpopt_none
;
1376 nios2_gpopt_option
= gpopt_local
;
1379 /* GP-relative and r0-relative addressing don't make sense for PIC. */
1382 if (nios2_gpopt_option
!= gpopt_none
)
1383 error ("%<-mgpopt%> not supported with PIC");
1384 if (nios2_gprel_sec
)
1385 error ("%<-mgprel-sec=%> not supported with PIC");
1386 if (nios2_r0rel_sec
)
1387 error ("%<-mr0rel-sec=%> not supported with PIC");
1390 /* Process -mgprel-sec= and -m0rel-sec=. */
1391 if (nios2_gprel_sec
)
1393 if (regcomp (&nios2_gprel_sec_regex
, nios2_gprel_sec
,
1394 REG_EXTENDED
| REG_NOSUB
))
1395 error ("%<-mgprel-sec=%> argument is not a valid regular expression");
1397 if (nios2_r0rel_sec
)
1399 if (regcomp (&nios2_r0rel_sec_regex
, nios2_r0rel_sec
,
1400 REG_EXTENDED
| REG_NOSUB
))
1401 error ("%<-mr0rel-sec=%> argument is not a valid regular expression");
1404 /* If we don't have mul, we don't have mulx either! */
1405 if (!TARGET_HAS_MUL
&& TARGET_HAS_MULX
)
1406 target_flags
&= ~MASK_HAS_MULX
;
1408 /* Optional BMX and CDX instructions only make sense for R2. */
1409 if (!TARGET_ARCH_R2
)
1412 error ("BMX instructions are only supported with R2 architecture");
1414 error ("CDX instructions are only supported with R2 architecture");
1417 /* R2 is little-endian only. */
1418 if (TARGET_ARCH_R2
&& TARGET_BIG_ENDIAN
)
1419 error ("R2 architecture is little-endian only");
1421 /* Initialize default FPU configurations. */
1422 nios2_init_fpu_configs ();
1424 /* Set up default handling for floating point custom instructions.
1426 Putting things in this order means that the -mcustom-fpu-cfg=
1427 switch will always be overridden by individual -mcustom-fadds=
1428 switches, regardless of the order in which they were specified
1429 on the command line.
1431 This behavior of prioritization of individual -mcustom-<insn>=
1432 options before the -mcustom-fpu-cfg= switch is maintained for
1434 if (nios2_custom_fpu_cfg_string
&& *nios2_custom_fpu_cfg_string
)
1435 nios2_handle_custom_fpu_cfg (nios2_custom_fpu_cfg_string
, NULL
, false);
1437 /* Handle options for individual FPU insns. */
1438 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
1439 nios2_handle_custom_fpu_insn_option (i
);
1441 nios2_custom_check_insns ();
1443 /* Save the initial options in case the user does function specific
1445 target_option_default_node
= target_option_current_node
1446 = build_target_option_node (&global_options
, &global_options_set
);
1450 /* Return true if CST is a constant within range of movi/movui/movhi. */
1452 nios2_simple_const_p (const_rtx cst
)
1454 if (!CONST_INT_P (cst
))
1456 HOST_WIDE_INT val
= INTVAL (cst
);
1457 return SMALL_INT (val
) || SMALL_INT_UNSIGNED (val
) || UPPER16_INT (val
);
1460 /* Compute a (partial) cost for rtx X. Return true if the complete
1461 cost has been computed, and false if subexpressions should be
1462 scanned. In either case, *TOTAL contains the cost result. */
1464 nios2_rtx_costs (rtx x
, machine_mode mode
,
1467 int *total
, bool speed
)
1469 int code
= GET_CODE (x
);
1474 if (INTVAL (x
) == 0 || nios2_simple_const_p (x
))
1476 *total
= COSTS_N_INSNS (0);
1481 /* High + lo_sum. */
1482 *total
= COSTS_N_INSNS (1);
1490 if (gprel_constant_p (x
) || r0rel_constant_p (x
))
1492 *total
= COSTS_N_INSNS (1);
1497 /* High + lo_sum. */
1498 *total
= COSTS_N_INSNS (1);
1504 /* This is essentially a constant. */
1505 *total
= COSTS_N_INSNS (0);
1511 *total
= COSTS_N_INSNS (0);
1517 /* Recognize 'nor' insn pattern. */
1518 if (GET_CODE (XEXP (x
, 0)) == NOT
1519 && GET_CODE (XEXP (x
, 1)) == NOT
)
1521 *total
= COSTS_N_INSNS (1);
1527 /* For insns that have an execution latency (3 cycles), don't
1528 penalize by the full amount since we can often schedule
1532 if (!TARGET_HAS_MUL
)
1533 *total
= COSTS_N_INSNS (5); /* Guess? */
1535 *total
= COSTS_N_INSNS (2); /* Latency adjustment. */
1537 *total
= COSTS_N_INSNS (1);
1538 if (TARGET_HAS_MULX
&& GET_MODE (x
) == DImode
)
1540 enum rtx_code c0
= GET_CODE (XEXP (x
, 0));
1541 enum rtx_code c1
= GET_CODE (XEXP (x
, 1));
1542 if ((c0
== SIGN_EXTEND
&& c1
== SIGN_EXTEND
)
1543 || (c0
== ZERO_EXTEND
&& c1
== ZERO_EXTEND
))
1544 /* This is the <mul>sidi3 pattern, which expands into 4 insns,
1545 2 multiplies and 2 moves. */
1547 *total
= *total
* 2 + COSTS_N_INSNS (2);
1556 if (!TARGET_HAS_DIV
)
1557 *total
= COSTS_N_INSNS (5); /* Guess? */
1559 *total
= COSTS_N_INSNS (2); /* Latency adjustment. */
1561 *total
= COSTS_N_INSNS (1);
1571 *total
= COSTS_N_INSNS (1);
1573 *total
= COSTS_N_INSNS (2); /* Latency adjustment. */
1580 *total
= COSTS_N_INSNS (1);
1587 if (MEM_P (XEXP (x
, 0)))
1588 *total
= COSTS_N_INSNS (1);
1590 *total
= COSTS_N_INSNS (3);
1596 rtx addr
= XEXP (x
, 0);
1598 /* Account for cost of different addressing modes. */
1599 *total
= nios2_address_cost (addr
, mode
, ADDR_SPACE_GENERIC
, speed
);
1601 if (outer_code
== SET
&& opno
== 0)
1602 /* Stores execute in 1 cycle accounted for by
1605 else if (outer_code
== SET
|| outer_code
== SIGN_EXTEND
1606 || outer_code
== ZERO_EXTEND
)
1607 /* Latency adjustment. */
1610 *total
+= COSTS_N_INSNS (1);
1613 /* This is going to have to be split into a load. */
1614 *total
+= COSTS_N_INSNS (speed
? 2 : 1);
1623 /* Implement TARGET_PREFERRED_RELOAD_CLASS. */
1625 nios2_preferred_reload_class (rtx x ATTRIBUTE_UNUSED
, reg_class_t regclass
)
1627 return regclass
== NO_REGS
? GENERAL_REGS
: regclass
;
1630 /* Emit a call to __tls_get_addr. TI is the argument to this function.
1631 RET is an RTX for the return value location. The entire insn sequence
1633 static GTY(()) rtx nios2_tls_symbol
;
1636 nios2_call_tls_get_addr (rtx ti
)
1638 rtx arg
= gen_rtx_REG (Pmode
, FIRST_ARG_REGNO
);
1639 rtx ret
= gen_rtx_REG (Pmode
, FIRST_RETVAL_REGNO
);
1643 if (!nios2_tls_symbol
)
1644 nios2_tls_symbol
= init_one_libfunc ("__tls_get_addr");
1646 emit_move_insn (arg
, ti
);
1647 fn
= gen_rtx_MEM (QImode
, nios2_tls_symbol
);
1648 insn
= emit_call_insn (gen_call_value (ret
, fn
, const0_rtx
));
1649 RTL_CONST_CALL_P (insn
) = 1;
1650 use_reg (&CALL_INSN_FUNCTION_USAGE (insn
), ret
);
1651 use_reg (&CALL_INSN_FUNCTION_USAGE (insn
), arg
);
1656 /* Return true for large offsets requiring hiadj/lo relocation pairs. */
1658 nios2_large_offset_p (int unspec
)
1660 gcc_assert (nios2_unspec_reloc_name (unspec
) != NULL
);
1663 /* FIXME: TLS GOT offset relocations will eventually also get this
1664 treatment, after binutils support for those are also completed. */
1665 && (unspec
== UNSPEC_PIC_SYM
|| unspec
== UNSPEC_PIC_CALL_SYM
))
1668 /* 'gotoff' offsets are always hiadj/lo. */
1669 if (unspec
== UNSPEC_PIC_GOTOFF_SYM
)
1675 /* Return true for conforming unspec relocations. Also used in
1676 constraints.md and predicates.md. */
1678 nios2_unspec_reloc_p (rtx op
)
1680 return (GET_CODE (op
) == CONST
1681 && GET_CODE (XEXP (op
, 0)) == UNSPEC
1682 && ! nios2_large_offset_p (XINT (XEXP (op
, 0), 1)));
1686 nios2_large_unspec_reloc_p (rtx op
)
1688 return (GET_CODE (op
) == CONST
1689 && GET_CODE (XEXP (op
, 0)) == UNSPEC
1690 && nios2_large_offset_p (XINT (XEXP (op
, 0), 1)));
1693 /* Helper to generate unspec constant. */
1695 nios2_unspec_offset (rtx loc
, int unspec
)
1697 return gen_rtx_CONST (Pmode
, gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, loc
),
1701 /* Generate GOT pointer based address with large offset. */
1703 nios2_large_got_address (rtx offset
, rtx tmp
)
1706 tmp
= gen_reg_rtx (Pmode
);
1707 emit_move_insn (tmp
, offset
);
1708 return gen_rtx_PLUS (Pmode
, tmp
, pic_offset_table_rtx
);
1711 /* Generate a GOT pointer based address. */
1713 nios2_got_address (rtx loc
, int unspec
)
1715 rtx offset
= nios2_unspec_offset (loc
, unspec
);
1716 crtl
->uses_pic_offset_table
= 1;
1718 if (nios2_large_offset_p (unspec
))
1719 return force_reg (Pmode
, nios2_large_got_address (offset
, NULL_RTX
));
1721 return gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, offset
);
1724 /* Generate the code to access LOC, a thread local SYMBOL_REF. The
1725 return value will be a valid address and move_operand (either a REG
1728 nios2_legitimize_tls_address (rtx loc
)
1731 enum tls_model model
= SYMBOL_REF_TLS_MODEL (loc
);
1735 case TLS_MODEL_GLOBAL_DYNAMIC
:
1736 tmp
= gen_reg_rtx (Pmode
);
1737 emit_move_insn (tmp
, nios2_got_address (loc
, UNSPEC_ADD_TLS_GD
));
1738 return nios2_call_tls_get_addr (tmp
);
1740 case TLS_MODEL_LOCAL_DYNAMIC
:
1741 tmp
= gen_reg_rtx (Pmode
);
1742 emit_move_insn (tmp
, nios2_got_address (loc
, UNSPEC_ADD_TLS_LDM
));
1743 return gen_rtx_PLUS (Pmode
, nios2_call_tls_get_addr (tmp
),
1744 nios2_unspec_offset (loc
, UNSPEC_ADD_TLS_LDO
));
1746 case TLS_MODEL_INITIAL_EXEC
:
1747 tmp
= gen_reg_rtx (Pmode
);
1748 mem
= gen_const_mem (Pmode
, nios2_got_address (loc
, UNSPEC_LOAD_TLS_IE
));
1749 emit_move_insn (tmp
, mem
);
1750 tp
= gen_rtx_REG (Pmode
, TP_REGNO
);
1751 return gen_rtx_PLUS (Pmode
, tp
, tmp
);
1753 case TLS_MODEL_LOCAL_EXEC
:
1754 tp
= gen_rtx_REG (Pmode
, TP_REGNO
);
1755 return gen_rtx_PLUS (Pmode
, tp
,
1756 nios2_unspec_offset (loc
, UNSPEC_ADD_TLS_LE
));
1764 If -O3 is used, we want to output a table lookup for
1765 divides between small numbers (both num and den >= 0
1766 and < 0x10). The overhead of this method in the worst
1767 case is 40 bytes in the text section (10 insns) and
1768 256 bytes in the data section. Additional divides do
1769 not incur additional penalties in the data section.
1771 Code speed is improved for small divides by about 5x
1772 when using this method in the worse case (~9 cycles
1773 vs ~45). And in the worst case divides not within the
1774 table are penalized by about 10% (~5 cycles vs ~45).
1775 However in the typical case the penalty is not as bad
1776 because doing the long divide in only 45 cycles is
1779 ??? would be nice to have some benchmarks other
1780 than Dhrystone to back this up.
1782 This bit of expansion is to create this instruction
1789 add $12, $11, divide_table
1795 # continue here with result in $2
1797 ??? Ideally I would like the libcall block to contain all
1798 of this code, but I don't know how to do that. What it
1799 means is that if the divide can be eliminated, it may not
1800 completely disappear.
1802 ??? The __divsi3_table label should ideally be moved out
1803 of this block and into a global. If it is placed into the
1804 sdata section we can save even more cycles by doing things
1807 nios2_emit_expensive_div (rtx
*operands
, machine_mode mode
)
1809 rtx or_result
, shift_left_result
;
1811 rtx_code_label
*lab1
, *lab3
;
1818 /* It may look a little generic, but only SImode is supported for now. */
1819 gcc_assert (mode
== SImode
);
1820 libfunc
= optab_libfunc (sdiv_optab
, SImode
);
1822 lab1
= gen_label_rtx ();
1823 lab3
= gen_label_rtx ();
1825 or_result
= expand_simple_binop (SImode
, IOR
,
1826 operands
[1], operands
[2],
1827 0, 0, OPTAB_LIB_WIDEN
);
1829 emit_cmp_and_jump_insns (or_result
, GEN_INT (15), GTU
, 0,
1830 GET_MODE (or_result
), 0, lab3
);
1831 JUMP_LABEL (get_last_insn ()) = lab3
;
1833 shift_left_result
= expand_simple_binop (SImode
, ASHIFT
,
1834 operands
[1], GEN_INT (4),
1835 0, 0, OPTAB_LIB_WIDEN
);
1837 lookup_value
= expand_simple_binop (SImode
, IOR
,
1838 shift_left_result
, operands
[2],
1839 0, 0, OPTAB_LIB_WIDEN
);
1840 table
= gen_rtx_PLUS (SImode
, lookup_value
,
1841 gen_rtx_SYMBOL_REF (SImode
, "__divsi3_table"));
1842 convert_move (operands
[0], gen_rtx_MEM (QImode
, table
), 1);
1844 tmp
= emit_jump_insn (gen_jump (lab1
));
1845 JUMP_LABEL (tmp
) = lab1
;
1849 LABEL_NUSES (lab3
) = 1;
1852 final_result
= emit_library_call_value (libfunc
, NULL_RTX
,
1854 operands
[1], SImode
,
1855 operands
[2], SImode
);
1857 insns
= get_insns ();
1859 emit_libcall_block (insns
, operands
[0], final_result
,
1860 gen_rtx_DIV (SImode
, operands
[1], operands
[2]));
1863 LABEL_NUSES (lab1
) = 1;
1867 /* Branches and compares. */
1869 /* Return in *ALT_CODE and *ALT_OP, an alternate equivalent constant
1870 comparison, e.g. >= 1 into > 0. */
1872 nios2_alternate_compare_const (enum rtx_code code
, rtx op
,
1873 enum rtx_code
*alt_code
, rtx
*alt_op
,
1876 gcc_assert (CONST_INT_P (op
));
1878 HOST_WIDE_INT opval
= INTVAL (op
);
1879 enum rtx_code scode
= signed_condition (code
);
1880 bool dec_p
= (scode
== LT
|| scode
== GE
);
1882 if (code
== EQ
|| code
== NE
)
1890 ? gen_int_mode (opval
- 1, mode
)
1891 : gen_int_mode (opval
+ 1, mode
));
1893 /* The required conversion between [>,>=] and [<,<=] is captured
1894 by a reverse + swap of condition codes. */
1895 *alt_code
= reverse_condition (swap_condition (code
));
1898 /* Test if the incremented/decremented value crosses the over/underflow
1899 boundary. Supposedly, such boundary cases should already be transformed
1900 into always-true/false or EQ conditions, so use an assertion here. */
1901 unsigned HOST_WIDE_INT alt_opval
= INTVAL (*alt_op
);
1903 alt_opval
^= (1 << (GET_MODE_BITSIZE (mode
) - 1));
1904 alt_opval
&= GET_MODE_MASK (mode
);
1905 gcc_assert (dec_p
? alt_opval
!= GET_MODE_MASK (mode
) : alt_opval
!= 0);
1909 /* Return true if the constant comparison is supported by nios2. */
1911 nios2_valid_compare_const_p (enum rtx_code code
, rtx op
)
1913 gcc_assert (CONST_INT_P (op
));
1916 case EQ
: case NE
: case GE
: case LT
:
1917 return SMALL_INT (INTVAL (op
));
1919 return SMALL_INT_UNSIGNED (INTVAL (op
));
1925 /* Checks if the FPU comparison in *CMP, *OP1, and *OP2 can be supported in
1926 the current configuration. Perform modifications if MODIFY_P is true.
1927 Returns true if FPU compare can be done. */
1930 nios2_validate_fpu_compare (machine_mode mode
, rtx
*cmp
, rtx
*op1
, rtx
*op2
,
1934 enum rtx_code code
= GET_CODE (*cmp
);
1936 if (!nios2_fpu_compare_enabled (code
, mode
))
1938 code
= swap_condition (code
);
1939 if (nios2_fpu_compare_enabled (code
, mode
))
1953 *op1
= force_reg (mode
, *op1
);
1954 *op2
= force_reg (mode
, *op2
);
1955 *cmp
= gen_rtx_fmt_ee (code
, mode
, *op1
, *op2
);
1960 /* Checks and modifies the comparison in *CMP, *OP1, and *OP2 into valid
1961 nios2 supported form. Returns true if success. */
1963 nios2_validate_compare (machine_mode mode
, rtx
*cmp
, rtx
*op1
, rtx
*op2
)
1965 enum rtx_code code
= GET_CODE (*cmp
);
1966 enum rtx_code alt_code
;
1969 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
)
1970 return nios2_validate_fpu_compare (mode
, cmp
, op1
, op2
, true);
1972 if (CONST_INT_P (*op2
) && *op2
!= const0_rtx
)
1974 /* Create alternate constant compare. */
1975 nios2_alternate_compare_const (code
, *op2
, &alt_code
, &alt_op2
, mode
);
1977 /* If alterate op2 is zero(0), we can use it directly, possibly
1978 swapping the compare code. */
1979 if (alt_op2
== const0_rtx
)
1983 goto check_rebuild_cmp
;
1986 /* Check if either constant compare can be used. */
1987 if (nios2_valid_compare_const_p (code
, *op2
))
1989 else if (nios2_valid_compare_const_p (alt_code
, alt_op2
))
1996 /* We have to force op2 into a register now. Try to pick one
1997 with a lower cost. */
1998 if (! nios2_simple_const_p (*op2
)
1999 && nios2_simple_const_p (alt_op2
))
2004 *op2
= force_reg (mode
, *op2
);
2006 else if (!reg_or_0_operand (*op2
, mode
))
2007 *op2
= force_reg (mode
, *op2
);
2010 if (code
== GT
|| code
== GTU
|| code
== LE
|| code
== LEU
)
2012 rtx t
= *op1
; *op1
= *op2
; *op2
= t
;
2013 code
= swap_condition (code
);
2016 *cmp
= gen_rtx_fmt_ee (code
, mode
, *op1
, *op2
);
2021 /* Addressing modes and constants. */
2023 /* Symbol references and other 32-bit constants are split into
2024 high/lo_sum pairs during the split1 pass. After that, they are not
2025 considered legitimate addresses.
2026 This function returns true if in a pre-split context where these
2027 constants are allowed. */
2029 nios2_large_constant_allowed (void)
2031 /* The reload_completed check is for the benefit of
2032 nios2_asm_output_mi_thunk and perhaps other places that try to
2033 emulate a post-reload pass. */
2034 return !(cfun
->curr_properties
& PROP_rtl_split_insns
) && !reload_completed
;
2037 /* Return true if X is constant expression with a reference to an
2038 "ordinary" symbol; not GOT-relative, not GP-relative, not TLS. */
2040 nios2_symbolic_constant_p (rtx x
)
2046 if (GET_CODE (x
) == LABEL_REF
)
2048 else if (CONSTANT_P (x
))
2050 split_const (x
, &base
, &offset
);
2051 return (SYMBOL_REF_P (base
)
2052 && !SYMBOL_REF_TLS_MODEL (base
)
2053 && !gprel_constant_p (base
)
2054 && !r0rel_constant_p (base
)
2055 && SMALL_INT (INTVAL (offset
)));
2060 /* Return true if X is an expression of the form
2061 (PLUS reg large_constant). */
2063 nios2_plus_large_constant_p (rtx x
)
2065 return (GET_CODE (x
) == PLUS
2066 && REG_P (XEXP (x
, 0))
2067 && nios2_large_constant_p (XEXP (x
, 1)));
2070 /* Implement TARGET_LEGITIMATE_CONSTANT_P. */
2072 nios2_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED
, rtx x
)
2075 split_const (x
, &base
, &offset
);
2076 return GET_CODE (base
) != SYMBOL_REF
|| !SYMBOL_REF_TLS_MODEL (base
);
2079 /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
2081 nios2_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED
, rtx x
)
2083 return nios2_legitimate_constant_p (mode
, x
) == false;
2086 /* Return true if register REGNO is a valid base register.
2087 STRICT_P is true if REG_OK_STRICT is in effect. */
2090 nios2_regno_ok_for_base_p (int regno
, bool strict_p
)
2092 if (!HARD_REGISTER_NUM_P (regno
))
2100 regno
= reg_renumber
[regno
];
2103 /* The fake registers will be eliminated to either the stack or
2104 hard frame pointer, both of which are usually valid base registers.
2105 Reload deals with the cases where the eliminated form isn't valid. */
2106 return (GP_REG_P (regno
)
2107 || regno
== FRAME_POINTER_REGNUM
2108 || regno
== ARG_POINTER_REGNUM
);
2111 /* Return true if OFFSET is permitted in a load/store address expression.
2112 Normally any 16-bit value is permitted, but on R2 if we may be emitting
2113 the IO forms of these instructions we must restrict the offset to fit
2114 in a 12-bit field instead. */
2117 nios2_valid_addr_offset_p (rtx offset
)
2119 return (CONST_INT_P (offset
)
2120 && ((TARGET_ARCH_R2
&& (TARGET_BYPASS_CACHE
2121 || TARGET_BYPASS_CACHE_VOLATILE
))
2122 ? SMALL_INT12 (INTVAL (offset
))
2123 : SMALL_INT (INTVAL (offset
))));
2126 /* Return true if the address expression formed by BASE + OFFSET is
2129 nios2_valid_addr_expr_p (rtx base
, rtx offset
, bool strict_p
)
2131 if (!strict_p
&& GET_CODE (base
) == SUBREG
)
2132 base
= SUBREG_REG (base
);
2133 return (REG_P (base
)
2134 && nios2_regno_ok_for_base_p (REGNO (base
), strict_p
)
2135 && (offset
== NULL_RTX
2136 || nios2_valid_addr_offset_p (offset
)
2137 || (nios2_large_constant_allowed ()
2138 && nios2_symbolic_constant_p (offset
))
2139 || nios2_unspec_reloc_p (offset
)));
2142 /* Implement TARGET_LEGITIMATE_ADDRESS_P. */
2144 nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
2145 rtx operand
, bool strict_p
)
2147 switch (GET_CODE (operand
))
2151 if (SYMBOL_REF_TLS_MODEL (operand
))
2154 /* Else, fall through. */
2156 if (gprel_constant_p (operand
) || r0rel_constant_p (operand
))
2159 /* Else, fall through. */
2161 if (nios2_large_constant_allowed ()
2162 && nios2_symbolic_constant_p (operand
))
2167 if (r0rel_constant_p (operand
))
2169 return nios2_large_constant_allowed ();
2174 /* Register indirect. */
2176 return nios2_regno_ok_for_base_p (REGNO (operand
), strict_p
);
2178 /* Register indirect with displacement. */
2181 rtx op0
= XEXP (operand
, 0);
2182 rtx op1
= XEXP (operand
, 1);
2184 if (nios2_valid_addr_expr_p (op0
, op1
, strict_p
)
2185 || nios2_valid_addr_expr_p (op1
, op0
, strict_p
))
2190 /* %lo(constant)(reg)
2191 This requires a 16-bit relocation and isn't valid with R2
2192 io-variant load/stores. */
2195 && (TARGET_BYPASS_CACHE
|| TARGET_BYPASS_CACHE_VOLATILE
))
2199 rtx op0
= XEXP (operand
, 0);
2200 rtx op1
= XEXP (operand
, 1);
2203 && nios2_regno_ok_for_base_p (REGNO (op0
), strict_p
)
2204 && nios2_large_constant_p (op1
));
2213 /* Implement TARGET_ADDRESS_COST.
2214 Experimentation has shown that we get better code by penalizing the
2215 the (plus reg symbolic_constant) and (plus reg (const ...)) forms
2216 but giving (plus reg symbol_ref) address modes the same cost as those
2217 that don't require splitting. Also, from a theoretical point of view:
2218 - This is in line with the recommendation in the GCC internals
2219 documentation to make address forms involving multiple
2220 registers more expensive than single-register forms.
2221 - OTOH it still encourages fwprop1 to propagate constants into
2222 address expressions more aggressively.
2223 - We should discourage splitting (symbol + offset) into hi/lo pairs
2224 to allow CSE'ing the symbol when it's used with more than one offset,
2225 but not so heavily as to avoid this addressing mode at all. */
2227 nios2_address_cost (rtx address
,
2228 machine_mode mode ATTRIBUTE_UNUSED
,
2229 addr_space_t as ATTRIBUTE_UNUSED
,
2230 bool speed ATTRIBUTE_UNUSED
)
2232 if (nios2_plus_large_constant_p (address
))
2233 return COSTS_N_INSNS (1);
2234 if (nios2_large_constant_p (address
))
2236 if (GET_CODE (address
) == CONST
)
2237 return COSTS_N_INSNS (1);
2239 return COSTS_N_INSNS (0);
2241 return COSTS_N_INSNS (0);
2244 /* Return true if X is a MEM whose address expression involves a large (32-bit)
2247 nios2_large_constant_memory_operand_p (rtx x
)
2251 if (GET_CODE (x
) != MEM
)
2255 return (nios2_large_constant_p (addr
)
2256 || nios2_plus_large_constant_p (addr
));
2260 /* Return true if X is something that needs to be split into a
2261 high/lo_sum pair. */
2263 nios2_large_constant_p (rtx x
)
2265 return (nios2_symbolic_constant_p (x
)
2266 || nios2_large_unspec_reloc_p (x
)
2267 || (CONST_INT_P (x
) && !SMALL_INT (INTVAL (x
))));
2270 /* Given an RTX X that satisfies nios2_large_constant_p, split it into
2271 high and lo_sum parts using TEMP as a scratch register. Emit the high
2272 instruction and return the lo_sum expression.
2273 Also handle special cases involving constant integers. */
2275 nios2_split_large_constant (rtx x
, rtx temp
)
2277 if (CONST_INT_P (x
))
2279 HOST_WIDE_INT val
= INTVAL (x
);
2280 if (SMALL_INT (val
))
2282 else if (SMALL_INT_UNSIGNED (val
) || UPPER16_INT (val
))
2284 emit_move_insn (temp
, x
);
2289 HOST_WIDE_INT high
= (val
+ 0x8000) & ~0xffff;
2290 HOST_WIDE_INT low
= val
- high
;
2291 emit_move_insn (temp
, gen_int_mode (high
, Pmode
));
2292 return gen_rtx_PLUS (Pmode
, temp
, gen_int_mode (low
, Pmode
));
2296 emit_insn (gen_rtx_SET (temp
, gen_rtx_HIGH (Pmode
, copy_rtx (x
))));
2297 return gen_rtx_LO_SUM (Pmode
, temp
, copy_rtx (x
));
2300 /* Split an RTX of the form
2302 where op1 is a large constant into
2303 (set temp (high op1))
2304 (set temp (plus op0 temp))
2306 returning the lo_sum expression as the value. */
2308 nios2_split_plus_large_constant (rtx op0
, rtx op1
)
2310 rtx temp
= gen_reg_rtx (Pmode
);
2311 op0
= force_reg (Pmode
, op0
);
2313 emit_insn (gen_rtx_SET (temp
, gen_rtx_HIGH (Pmode
, copy_rtx (op1
))));
2314 emit_insn (gen_rtx_SET (temp
, gen_rtx_PLUS (Pmode
, op0
, temp
)));
2315 return gen_rtx_LO_SUM (Pmode
, temp
, copy_rtx (op1
));
2318 /* Given a MEM OP with an address that includes a splittable symbol or
2319 other large constant, emit some instructions to do the split and
2320 return a new MEM. */
2322 nios2_split_large_constant_memory_operand (rtx op
)
2324 rtx addr
= XEXP (op
, 0);
2326 if (nios2_large_constant_p (addr
))
2327 addr
= nios2_split_large_constant (addr
, gen_reg_rtx (Pmode
));
2328 else if (nios2_plus_large_constant_p (addr
))
2329 addr
= nios2_split_plus_large_constant (XEXP (addr
, 0), XEXP (addr
, 1));
2332 return replace_equiv_address (op
, addr
, false);
2335 /* Return true if SECTION is a small section name. */
2337 nios2_small_section_name_p (const char *section
)
2339 return (strcmp (section
, ".sbss") == 0
2340 || startswith (section
, ".sbss.")
2341 || strcmp (section
, ".sdata") == 0
2342 || startswith (section
, ".sdata.")
2344 && regexec (&nios2_gprel_sec_regex
, section
, 0, NULL
, 0) == 0));
2347 /* Return true if SECTION is a r0-relative section name. */
2349 nios2_r0rel_section_name_p (const char *section
)
2351 return (nios2_r0rel_sec
2352 && regexec (&nios2_r0rel_sec_regex
, section
, 0, NULL
, 0) == 0);
2355 /* Return true if EXP should be placed in the small data section. */
2357 nios2_in_small_data_p (const_tree exp
)
2359 /* We want to merge strings, so we never consider them small data. */
2360 if (TREE_CODE (exp
) == STRING_CST
)
2363 if (TREE_CODE (exp
) == VAR_DECL
)
2365 if (DECL_SECTION_NAME (exp
))
2367 const char *section
= DECL_SECTION_NAME (exp
);
2368 if (nios2_small_section_name_p (section
))
2371 else if (flexible_array_type_p (TREE_TYPE (exp
))
2372 && (!TREE_PUBLIC (exp
) || DECL_EXTERNAL (exp
)))
2374 /* We really should not consider any objects of any flexibly-sized
2375 type to be small data, but pre-GCC 10 did not test
2376 for this and just fell through to the next case. Thus older
2377 code compiled with -mgpopt=global could contain GP-relative
2378 accesses to objects defined in this compilation unit with
2379 external linkage. We retain the possible small-data treatment
2380 of such definitions for backward ABI compatibility, but
2381 no longer generate GP-relative accesses for external
2382 references (so that the ABI could be changed in the future
2383 with less potential impact), or objects with internal
2389 HOST_WIDE_INT size
= int_size_in_bytes (TREE_TYPE (exp
));
2391 /* If this is an incomplete type with size 0, then we can't put it
2392 in sdata because it might be too big when completed. */
2394 && (unsigned HOST_WIDE_INT
) size
<= nios2_section_threshold
)
2402 /* Return true if symbol is in small data section. */
2405 nios2_symbol_ref_in_small_data_p (rtx sym
)
2409 gcc_assert (GET_CODE (sym
) == SYMBOL_REF
);
2410 decl
= SYMBOL_REF_DECL (sym
);
2412 /* TLS variables are not accessed through the GP. */
2413 if (SYMBOL_REF_TLS_MODEL (sym
) != 0)
2416 /* On Nios II R2, there is no GP-relative relocation that can be
2417 used with "io" instructions. So, if we are implicitly generating
2418 those instructions, we cannot emit GP-relative accesses. */
2420 && (TARGET_BYPASS_CACHE
|| TARGET_BYPASS_CACHE_VOLATILE
))
2423 /* If the user has explicitly placed the symbol in a small data section
2424 via an attribute, generate gp-relative addressing even if the symbol
2425 is external, weak, or larger than we'd automatically put in the
2426 small data section. OTOH, if the symbol is located in some
2427 non-small-data section, we can't use gp-relative accesses on it
2428 unless the user has requested gpopt_data or gpopt_all. */
2430 switch (nios2_gpopt_option
)
2433 /* Don't generate a gp-relative addressing mode if that's been
2438 /* Use GP-relative addressing for small data symbols that are
2439 not external or weak or uninitialized common, plus any symbols
2440 that have explicitly been placed in a small data section. */
2441 if (decl
&& DECL_SECTION_NAME (decl
))
2442 return nios2_small_section_name_p (DECL_SECTION_NAME (decl
));
2443 return (SYMBOL_REF_SMALL_P (sym
)
2444 && !SYMBOL_REF_EXTERNAL_P (sym
)
2445 && !(decl
&& DECL_WEAK (decl
))
2446 && !(decl
&& DECL_COMMON (decl
)
2447 && (DECL_INITIAL (decl
) == NULL
2449 && DECL_INITIAL (decl
) == error_mark_node
))));
2452 /* Use GP-relative addressing for small data symbols, even if
2453 they are external or weak. Note that SYMBOL_REF_SMALL_P
2454 is also true of symbols that have explicitly been placed
2455 in a small data section. */
2456 return SYMBOL_REF_SMALL_P (sym
);
2459 /* Use GP-relative addressing for all data symbols regardless
2460 of the object size, but not for code symbols. This option
2461 is equivalent to the user asserting that the entire data
2462 section is accessible from the GP. */
2463 return !SYMBOL_REF_FUNCTION_P (sym
);
2466 /* Use GP-relative addressing for everything, including code.
2467 Effectively, the user has asserted that the entire program
2468 fits within the 64K range of the GP offset. */
2472 /* We shouldn't get here. */
2477 /* Likewise for r0-relative addressing. */
2479 nios2_symbol_ref_in_r0rel_data_p (rtx sym
)
2483 gcc_assert (GET_CODE (sym
) == SYMBOL_REF
);
2484 decl
= SYMBOL_REF_DECL (sym
);
2486 /* TLS variables are not accessed through r0. */
2487 if (SYMBOL_REF_TLS_MODEL (sym
) != 0)
2490 /* On Nios II R2, there is no r0-relative relocation that can be
2491 used with "io" instructions. So, if we are implicitly generating
2492 those instructions, we cannot emit r0-relative accesses. */
2494 && (TARGET_BYPASS_CACHE
|| TARGET_BYPASS_CACHE_VOLATILE
))
2497 /* If the user has explicitly placed the symbol in a r0rel section
2498 via an attribute, generate r0-relative addressing. */
2499 if (decl
&& DECL_SECTION_NAME (decl
))
2500 return nios2_r0rel_section_name_p (DECL_SECTION_NAME (decl
));
2504 /* Implement TARGET_SECTION_TYPE_FLAGS. */
2507 nios2_section_type_flags (tree decl
, const char *name
, int reloc
)
2511 flags
= default_section_type_flags (decl
, name
, reloc
);
2513 if (nios2_small_section_name_p (name
))
2514 flags
|= SECTION_SMALL
;
2519 /* Return true if SYMBOL_REF X binds locally. */
2522 nios2_symbol_binds_local_p (const_rtx x
)
2524 return (SYMBOL_REF_DECL (x
)
2525 ? targetm
.binds_local_p (SYMBOL_REF_DECL (x
))
2526 : SYMBOL_REF_LOCAL_P (x
));
2529 /* Position independent code related. */
2531 /* Emit code to load the PIC register. */
2533 nios2_load_pic_register (void)
2535 rtx tmp
= gen_rtx_REG (Pmode
, TEMP_REG_NUM
);
2537 emit_insn (gen_load_got_register (pic_offset_table_rtx
, tmp
));
2538 emit_insn (gen_add3_insn (pic_offset_table_rtx
, pic_offset_table_rtx
, tmp
));
2541 /* Generate a PIC address as a MEM rtx. */
2543 nios2_load_pic_address (rtx sym
, int unspec
, rtx tmp
)
2546 && GET_CODE (sym
) == SYMBOL_REF
2547 && nios2_symbol_binds_local_p (sym
))
2548 /* Under -fPIC, generate a GOTOFF address for local symbols. */
2550 rtx offset
= nios2_unspec_offset (sym
, UNSPEC_PIC_GOTOFF_SYM
);
2551 crtl
->uses_pic_offset_table
= 1;
2552 return nios2_large_got_address (offset
, tmp
);
2555 return gen_const_mem (Pmode
, nios2_got_address (sym
, unspec
));
2558 /* Nonzero if the constant value X is a legitimate general operand
2559 when generating PIC code. It is given that flag_pic is on and
2560 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
2562 nios2_legitimate_pic_operand_p (rtx x
)
2564 if (nios2_large_unspec_reloc_p (x
))
2567 return ! (GET_CODE (x
) == SYMBOL_REF
2568 || GET_CODE (x
) == LABEL_REF
|| GET_CODE (x
) == CONST
);
2571 /* Return TRUE if X is a thread-local symbol. */
2573 nios2_tls_symbol_p (rtx x
)
2575 return (targetm
.have_tls
&& GET_CODE (x
) == SYMBOL_REF
2576 && SYMBOL_REF_TLS_MODEL (x
) != 0);
2579 /* Legitimize addresses that are CONSTANT_P expressions. */
2581 nios2_legitimize_constant_address (rtx addr
)
2584 split_const (addr
, &base
, &offset
);
2586 if (nios2_tls_symbol_p (base
))
2587 base
= nios2_legitimize_tls_address (base
);
2589 base
= nios2_load_pic_address (base
, UNSPEC_PIC_SYM
, NULL_RTX
);
2590 else if (!nios2_large_constant_allowed ()
2591 && nios2_symbolic_constant_p (addr
))
2592 return nios2_split_large_constant (addr
, gen_reg_rtx (Pmode
));
2593 else if (CONST_INT_P (addr
))
2595 HOST_WIDE_INT val
= INTVAL (addr
);
2596 if (SMALL_INT (val
))
2597 /* Use r0-relative addressing. */
2599 else if (!nios2_large_constant_allowed ())
2600 /* Split into high/lo pair. */
2601 return nios2_split_large_constant (addr
, gen_reg_rtx (Pmode
));
2606 if (offset
!= const0_rtx
)
2608 gcc_assert (can_create_pseudo_p ());
2609 return gen_rtx_PLUS (Pmode
, force_reg (Pmode
, base
),
2610 (CONST_INT_P (offset
)
2611 ? (SMALL_INT (INTVAL (offset
))
2612 ? offset
: force_reg (Pmode
, offset
))
2618 /* Implement TARGET_LEGITIMIZE_ADDRESS. */
2620 nios2_legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
2621 machine_mode mode ATTRIBUTE_UNUSED
)
2626 return nios2_legitimize_constant_address (x
);
2628 /* Remaining cases all involve something + a constant. */
2629 if (GET_CODE (x
) != PLUS
)
2635 /* Target-independent code turns (exp + constant) into plain
2636 register indirect. Although subsequent optimization passes will
2637 eventually sort that out, ivopts uses the unoptimized form for
2638 computing its cost model, so we get better results by generating
2639 the correct form from the start. */
2640 if (nios2_valid_addr_offset_p (op1
))
2641 return gen_rtx_PLUS (Pmode
, force_reg (Pmode
, op0
), copy_rtx (op1
));
2643 /* We may need to split symbolic constants now. */
2644 else if (nios2_symbolic_constant_p (op1
))
2646 if (nios2_large_constant_allowed ())
2647 return gen_rtx_PLUS (Pmode
, force_reg (Pmode
, op0
), copy_rtx (op1
));
2649 return nios2_split_plus_large_constant (op0
, op1
);
2652 /* For the TLS LE (Local Exec) model, the compiler may try to
2653 combine constant offsets with unspec relocs, creating address RTXs
2655 (plus:SI (reg:SI 23 r23)
2658 (unspec:SI [(symbol_ref:SI ("var"))] UNSPEC_ADD_TLS_LE)
2659 (const_int 48 [0x30]))))
2661 This usually happens when 'var' is a thread-local struct variable,
2662 and access of a field in var causes the addend.
2664 We typically want this combining, so transform the above into this
2665 form, which is allowed:
2666 (plus:SI (reg:SI 23 r23)
2670 (plus:SI (symbol_ref:SI ("var"))
2671 (const_int 48 [0x30])))] UNSPEC_ADD_TLS_LE)))
2673 Which will be output as '%tls_le(var+48)(r23)' in assembly. */
2674 else if (GET_CODE (op1
) == CONST
)
2677 split_const (op1
, &unspec
, &offset
);
2678 if (GET_CODE (unspec
) == UNSPEC
2679 && !nios2_large_offset_p (XINT (unspec
, 1))
2680 && offset
!= const0_rtx
)
2682 rtx reg
= force_reg (Pmode
, op0
);
2683 unspec
= copy_rtx (unspec
);
2684 XVECEXP (unspec
, 0, 0)
2685 = plus_constant (Pmode
, XVECEXP (unspec
, 0, 0), INTVAL (offset
));
2686 return gen_rtx_PLUS (Pmode
, reg
, gen_rtx_CONST (Pmode
, unspec
));
2694 nios2_delegitimize_address (rtx x
)
2696 x
= delegitimize_mem_from_attrs (x
);
2698 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == UNSPEC
)
2700 switch (XINT (XEXP (x
, 0), 1))
2702 case UNSPEC_PIC_SYM
:
2703 case UNSPEC_PIC_CALL_SYM
:
2704 case UNSPEC_PIC_GOTOFF_SYM
:
2705 case UNSPEC_ADD_TLS_GD
:
2706 case UNSPEC_ADD_TLS_LDM
:
2707 case UNSPEC_LOAD_TLS_IE
:
2708 case UNSPEC_ADD_TLS_LE
:
2709 x
= XVECEXP (XEXP (x
, 0), 0, 0);
2710 gcc_assert (CONSTANT_P (x
));
2717 /* Main expander function for RTL moves. */
2719 nios2_emit_move_sequence (rtx
*operands
, machine_mode mode
)
2721 rtx to
= operands
[0];
2722 rtx from
= operands
[1];
2724 if (!register_operand (to
, mode
) && !reg_or_0_operand (from
, mode
))
2726 gcc_assert (can_create_pseudo_p ());
2727 from
= copy_to_mode_reg (mode
, from
);
2730 if (CONSTANT_P (from
))
2732 if (CONST_INT_P (from
))
2734 if (!SMALL_INT (INTVAL (from
))
2735 && !SMALL_INT_UNSIGNED (INTVAL (from
))
2736 && !UPPER16_INT (INTVAL (from
)))
2738 HOST_WIDE_INT high
= (INTVAL (from
) + 0x8000) & ~0xffff;
2739 HOST_WIDE_INT low
= INTVAL (from
) & 0xffff;
2740 emit_move_insn (to
, gen_int_mode (high
, SImode
));
2741 emit_insn (gen_add2_insn (to
, gen_int_mode (low
, HImode
)));
2742 set_unique_reg_note (get_last_insn (), REG_EQUAL
,
2747 else if (gprel_constant_p (from
) || r0rel_constant_p (from
))
2748 /* Handled directly by movsi_internal as gp + offset
2751 else if (nios2_large_constant_p (from
))
2752 /* This case covers either a regular symbol reference or an UNSPEC
2753 representing a 32-bit offset. We split the former
2754 only conditionally and the latter always. */
2756 if (!nios2_large_constant_allowed ()
2757 || nios2_large_unspec_reloc_p (from
))
2759 rtx lo
= nios2_split_large_constant (from
, to
);
2760 emit_insn (gen_rtx_SET (to
, lo
));
2761 set_unique_reg_note (get_last_insn (), REG_EQUAL
,
2762 copy_rtx (operands
[1]));
2767 /* This is a TLS or PIC symbol. */
2769 from
= nios2_legitimize_constant_address (from
);
2770 if (CONSTANT_P (from
))
2772 emit_insn (gen_rtx_SET (to
,
2773 gen_rtx_HIGH (Pmode
, copy_rtx (from
))));
2774 emit_insn (gen_rtx_SET (to
, gen_rtx_LO_SUM (Pmode
, to
, from
)));
2775 set_unique_reg_note (get_last_insn (), REG_EQUAL
,
2776 copy_rtx (operands
[1]));
2787 /* The function with address *ADDR is being called. If the address
2788 needs to be loaded from the GOT, emit the instruction to do so and
2789 update *ADDR to point to the rtx for the loaded value.
2790 If REG != NULL_RTX, it is used as the target/scratch register in the
2791 GOT address calculation. */
2793 nios2_adjust_call_address (rtx
*call_op
, rtx reg
)
2795 if (MEM_P (*call_op
))
2796 call_op
= &XEXP (*call_op
, 0);
2798 rtx addr
= *call_op
;
2799 if (flag_pic
&& CONSTANT_P (addr
))
2801 rtx tmp
= reg
? reg
: NULL_RTX
;
2803 reg
= gen_reg_rtx (Pmode
);
2804 addr
= nios2_load_pic_address (addr
, UNSPEC_PIC_CALL_SYM
, tmp
);
2805 emit_insn (gen_rtx_SET (reg
, addr
));
2811 /* Output assembly language related definitions. */
2813 /* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P. */
2815 nios2_print_operand_punct_valid_p (unsigned char code
)
2817 return (code
== '.' || code
== '!');
2821 /* Print the operand OP to file stream FILE modified by LETTER.
2822 LETTER can be one of:
2824 i: print i/hi/ui suffixes (used for mov instruction variants),
2825 when OP is the appropriate immediate operand.
2827 u: like 'i', except without "ui" suffix case (used for cmpgeu/cmpltu)
2829 o: print "io" if OP needs volatile access (due to TARGET_BYPASS_CACHE
2830 or TARGET_BYPASS_CACHE_VOLATILE).
2832 x: print i/hi/ci/chi suffixes for the and instruction,
2833 when OP is the appropriate immediate operand.
2835 z: prints the third register immediate operand in assembly
2836 instructions. Outputs const0_rtx as the 'zero' register
2839 y: same as 'z', but for specifically for logical instructions,
2840 where the processing for immediates are slightly different.
2844 D: for the upper 32-bits of a 64-bit double value
2845 R: prints reverse condition.
2846 A: prints (reg) operand for ld[s]ex and st[s]ex.
2848 .: print .n suffix for 16-bit instructions.
2849 !: print r.n suffix for 16-bit instructions. Used for jmpr.n.
2852 nios2_print_operand (FILE *file
, rtx op
, int letter
)
2855 /* First take care of the format letters that just insert a string
2856 into the output stream. */
2860 if (current_output_insn
&& get_attr_length (current_output_insn
) == 2)
2861 fprintf (file
, ".n");
2865 if (current_output_insn
&& get_attr_length (current_output_insn
) == 2)
2866 fprintf (file
, "r.n");
2870 if (CONST_INT_P (op
))
2872 HOST_WIDE_INT val
= INTVAL (op
);
2873 HOST_WIDE_INT low
= val
& 0xffff;
2874 HOST_WIDE_INT high
= (val
>> 16) & 0xffff;
2882 gcc_assert (TARGET_ARCH_R2
);
2884 fprintf (file
, "c");
2885 else if (low
== 0xffff)
2886 fprintf (file
, "ch");
2891 fprintf (file
, "h");
2893 fprintf (file
, "i");
2900 if (CONST_INT_P (op
))
2902 HOST_WIDE_INT val
= INTVAL (op
);
2903 HOST_WIDE_INT low
= val
& 0xffff;
2904 HOST_WIDE_INT high
= (val
>> 16) & 0xffff;
2907 if (low
== 0 && high
!= 0)
2908 fprintf (file
, "h");
2909 else if (high
== 0 && (low
& 0x8000) != 0 && letter
!= 'u')
2910 fprintf (file
, "u");
2913 if (CONSTANT_P (op
) && op
!= const0_rtx
)
2914 fprintf (file
, "i");
2918 if (GET_CODE (op
) == MEM
2919 && ((MEM_VOLATILE_P (op
) && TARGET_BYPASS_CACHE_VOLATILE
)
2920 || TARGET_BYPASS_CACHE
))
2922 gcc_assert (current_output_insn
2923 && get_attr_length (current_output_insn
) == 4);
2924 fprintf (file
, "io");
2932 /* Handle comparison operator names. */
2933 if (comparison_operator (op
, VOIDmode
))
2935 enum rtx_code cond
= GET_CODE (op
);
2938 fprintf (file
, "%s", GET_RTX_NAME (cond
));
2943 fprintf (file
, "%s", GET_RTX_NAME (reverse_condition (cond
)));
2948 /* Now handle the cases where we actually need to format an operand. */
2949 switch (GET_CODE (op
))
2952 if (letter
== 0 || letter
== 'z' || letter
== 'y')
2954 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
2957 else if (letter
== 'D')
2959 fprintf (file
, "%s", reg_names
[REGNO (op
)+1]);
2967 HOST_WIDE_INT val
= INTVAL (int_rtx
);
2968 HOST_WIDE_INT low
= val
& 0xffff;
2969 HOST_WIDE_INT high
= (val
>> 16) & 0xffff;
2974 fprintf (file
, "zero");
2981 gcc_assert (TARGET_ARCH_R2
);
2984 int_rtx
= gen_int_mode (low
, SImode
);
2985 else if (low
== 0xffff)
2987 int_rtx
= gen_int_mode (high
, SImode
);
2993 int_rtx
= gen_int_mode (high
, SImode
);
2997 int_rtx
= gen_int_mode (low
, SImode
);
2998 output_addr_const (file
, int_rtx
);
3002 else if (letter
== 'z')
3005 fprintf (file
, "zero");
3008 if (low
== 0 && high
!= 0)
3009 int_rtx
= gen_int_mode (high
, SImode
);
3012 gcc_assert (high
== 0 || high
== 0xffff);
3013 int_rtx
= gen_int_mode (low
, high
== 0 ? SImode
: HImode
);
3017 output_addr_const (file
, int_rtx
);
3023 /* Else, fall through. */
3029 if (letter
== 0 || letter
== 'z')
3031 output_addr_const (file
, op
);
3034 else if (letter
== 'H' || letter
== 'L')
3036 fprintf (file
, "%%");
3037 if (GET_CODE (op
) == CONST
3038 && GET_CODE (XEXP (op
, 0)) == UNSPEC
)
3040 rtx unspec
= XEXP (op
, 0);
3041 int unspec_reloc
= XINT (unspec
, 1);
3042 gcc_assert (nios2_large_offset_p (unspec_reloc
));
3043 fprintf (file
, "%s_", nios2_unspec_reloc_name (unspec_reloc
));
3044 op
= XVECEXP (unspec
, 0, 0);
3046 fprintf (file
, letter
== 'H' ? "hiadj(" : "lo(");
3047 output_addr_const (file
, op
);
3048 fprintf (file
, ")");
3057 /* Address of '(reg)' form, with no index. */
3058 fprintf (file
, "(%s)", reg_names
[REGNO (XEXP (op
, 0))]);
3063 output_address (VOIDmode
, op
);
3071 output_addr_const (file
, op
);
3081 output_operand_lossage ("Unsupported operand for code '%c'", letter
);
3085 /* Return true if this is a GP-relative accessible reference. */
3087 gprel_constant_p (rtx op
)
3089 if (GET_CODE (op
) == SYMBOL_REF
3090 && nios2_symbol_ref_in_small_data_p (op
))
3092 else if (GET_CODE (op
) == CONST
3093 && GET_CODE (XEXP (op
, 0)) == PLUS
)
3094 return gprel_constant_p (XEXP (XEXP (op
, 0), 0));
3099 /* Likewise if this is a zero-relative accessible reference. */
3101 r0rel_constant_p (rtx op
)
3103 if (GET_CODE (op
) == SYMBOL_REF
3104 && nios2_symbol_ref_in_r0rel_data_p (op
))
3106 else if (GET_CODE (op
) == CONST
3107 && GET_CODE (XEXP (op
, 0)) == PLUS
)
3108 return r0rel_constant_p (XEXP (XEXP (op
, 0), 0));
3109 else if (GET_CODE (op
) == CONST_INT
3110 && SMALL_INT (INTVAL (op
)))
3116 /* Return the name string for a supported unspec reloc offset. */
3118 nios2_unspec_reloc_name (int unspec
)
3122 case UNSPEC_PIC_SYM
:
3124 case UNSPEC_PIC_CALL_SYM
:
3126 case UNSPEC_PIC_GOTOFF_SYM
:
3128 case UNSPEC_LOAD_TLS_IE
:
3130 case UNSPEC_ADD_TLS_LE
:
3132 case UNSPEC_ADD_TLS_GD
:
3134 case UNSPEC_ADD_TLS_LDM
:
3136 case UNSPEC_ADD_TLS_LDO
:
3143 /* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */
3145 nios2_output_addr_const_extra (FILE *file
, rtx op
)
3148 gcc_assert (GET_CODE (op
) == UNSPEC
);
3150 /* Support for printing out const unspec relocations. */
3151 name
= nios2_unspec_reloc_name (XINT (op
, 1));
3154 fprintf (file
, "%%%s(", name
);
3155 output_addr_const (file
, XVECEXP (op
, 0, 0));
3156 fprintf (file
, ")");
3162 /* Implement TARGET_PRINT_OPERAND_ADDRESS. */
3164 nios2_print_operand_address (FILE *file
, machine_mode mode
, rtx op
)
3166 switch (GET_CODE (op
))
3173 if (gprel_constant_p (op
))
3175 fprintf (file
, "%%gprel(");
3176 output_addr_const (file
, op
);
3177 fprintf (file
, ")(%s)", reg_names
[GP_REGNO
]);
3180 else if (r0rel_constant_p (op
))
3182 if (CONST_INT_P (op
))
3184 output_addr_const (file
, op
);
3185 fprintf (file
, "(r0)");
3190 fprintf (file
, "%%lo(");
3191 output_addr_const (file
, op
);
3192 fprintf (file
, ")(r0)");
3200 rtx op0
= XEXP (op
, 0);
3201 rtx op1
= XEXP (op
, 1);
3203 if (REG_P (op0
) && CONSTANT_P (op1
))
3205 output_addr_const (file
, op1
);
3206 fprintf (file
, "(%s)", reg_names
[REGNO (op0
)]);
3209 else if (REG_P (op1
) && CONSTANT_P (op0
))
3211 output_addr_const (file
, op0
);
3212 fprintf (file
, "(%s)", reg_names
[REGNO (op1
)]);
3220 rtx op0
= XEXP (op
, 0);
3221 rtx op1
= XEXP (op
, 1);
3223 if (REG_P (op0
) && CONSTANT_P (op1
))
3225 nios2_print_operand (file
, op1
, 'L');
3226 fprintf (file
, "(%s)", reg_names
[REGNO (op0
)]);
3233 fprintf (file
, "0(%s)", reg_names
[REGNO (op
)]);
3238 rtx base
= XEXP (op
, 0);
3239 nios2_print_operand_address (file
, mode
, base
);
3246 fprintf (stderr
, "Missing way to print address\n");
3251 /* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL. */
3253 nios2_output_dwarf_dtprel (FILE *file
, int size
, rtx x
)
3255 gcc_assert (size
== 4);
3256 fprintf (file
, "\t.4byte\t%%tls_ldo(");
3257 output_addr_const (file
, x
);
3258 fprintf (file
, ")");
3261 /* Implemet TARGET_ASM_FILE_END. */
3264 nios2_asm_file_end (void)
3266 /* The Nios II Linux stack is mapped non-executable by default, so add a
3267 .note.GNU-stack section for switching to executable stacks only when
3268 trampolines are generated. */
3269 if (TARGET_LINUX_ABI
&& trampolines_created
)
3270 file_end_indicate_exec_stack ();
3273 /* Implement TARGET_ASM_FUNCTION_PROLOGUE. */
3275 nios2_asm_function_prologue (FILE *file
)
3277 if (flag_verbose_asm
|| flag_debug_asm
)
3279 nios2_compute_frame_layout ();
3280 nios2_dump_frame_layout (file
);
3284 /* Emit assembly of custom FPU instructions. */
3286 nios2_fpu_insn_asm (enum n2fpu_code code
)
3288 static char buf
[256];
3289 const char *op1
, *op2
, *op3
;
3290 int ln
= 256, n
= 0;
3292 int N
= N2FPU_N (code
);
3293 int num_operands
= N2FPU (code
).num_operands
;
3294 const char *insn_name
= N2FPU_NAME (code
);
3295 tree ftype
= nios2_ftype (N2FPU_FTCODE (code
));
3296 machine_mode dst_mode
= TYPE_MODE (TREE_TYPE (ftype
));
3297 machine_mode src_mode
= TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (ftype
)));
3299 /* Prepare X register for DF input operands. */
3300 if (GET_MODE_SIZE (src_mode
) == 8 && num_operands
== 3)
3301 n
= snprintf (buf
, ln
, "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t",
3302 N2FPU_N (n2fpu_fwrx
));
3304 if (src_mode
== SFmode
)
3306 if (dst_mode
== VOIDmode
)
3308 /* The fwry case. */
3315 op1
= (dst_mode
== DFmode
? "%D0" : "%0");
3317 op3
= (num_operands
== 2 ? "zero" : "%2");
3320 else if (src_mode
== DFmode
)
3322 if (dst_mode
== VOIDmode
)
3324 /* The fwrx case. */
3332 op1
= (dst_mode
== DFmode
? "%D0" : "%0");
3333 op2
= (num_operands
== 2 ? "%1" : "%2");
3334 op3
= (num_operands
== 2 ? "%D1" : "%D2");
3337 else if (src_mode
== VOIDmode
)
3339 /* frdxlo, frdxhi, frdy cases. */
3340 gcc_assert (dst_mode
== SFmode
);
3344 else if (src_mode
== SImode
)
3346 /* Conversion operators. */
3347 gcc_assert (num_operands
== 2);
3348 op1
= (dst_mode
== DFmode
? "%D0" : "%0");
3355 /* Main instruction string. */
3356 n
+= snprintf (buf
+ n
, ln
- n
, "custom\t%d, %s, %s, %s # %s %%0%s%s",
3357 N
, op1
, op2
, op3
, insn_name
,
3358 (num_operands
>= 2 ? ", %1" : ""),
3359 (num_operands
== 3 ? ", %2" : ""));
3361 /* Extraction of Y register for DF results. */
3362 if (dst_mode
== DFmode
)
3363 snprintf (buf
+ n
, ln
- n
, "\n\tcustom\t%d, %%0, zero, zero # frdy %%0",
3364 N2FPU_N (n2fpu_frdy
));
3370 /* Function argument related. */
3372 /* Define where to put the arguments to a function. Value is zero to
3373 push the argument on the stack, or a hard register in which to
3376 CUM is a variable of type CUMULATIVE_ARGS which gives info about
3377 the preceding args and about the function being called.
3378 ARG is a description of the argument. */
3381 nios2_function_arg (cumulative_args_t cum_v
, const function_arg_info
&arg
)
3383 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
3384 rtx return_rtx
= NULL_RTX
;
3386 if (cum
->regs_used
< NUM_ARG_REGS
)
3387 return_rtx
= gen_rtx_REG (arg
.mode
, FIRST_ARG_REGNO
+ cum
->regs_used
);
3392 /* Return number of bytes, at the beginning of the argument, that must be
3393 put in registers. 0 is the argument is entirely in registers or entirely
3397 nios2_arg_partial_bytes (cumulative_args_t cum_v
, const function_arg_info
&arg
)
3399 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
3400 HOST_WIDE_INT param_size
= arg
.promoted_size_in_bytes ();
3401 gcc_assert (param_size
>= 0);
3403 /* Convert to words (round up). */
3404 param_size
= (UNITS_PER_WORD
- 1 + param_size
) / UNITS_PER_WORD
;
3406 if (cum
->regs_used
< NUM_ARG_REGS
3407 && cum
->regs_used
+ param_size
> NUM_ARG_REGS
)
3408 return (NUM_ARG_REGS
- cum
->regs_used
) * UNITS_PER_WORD
;
3413 /* Update the data in CUM to advance over argument ARG. */
3416 nios2_function_arg_advance (cumulative_args_t cum_v
,
3417 const function_arg_info
&arg
)
3419 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
3420 HOST_WIDE_INT param_size
= arg
.promoted_size_in_bytes ();
3421 gcc_assert (param_size
>= 0);
3423 /* Convert to words (round up). */
3424 param_size
= (UNITS_PER_WORD
- 1 + param_size
) / UNITS_PER_WORD
;
3426 if (cum
->regs_used
+ param_size
> NUM_ARG_REGS
)
3427 cum
->regs_used
= NUM_ARG_REGS
;
3429 cum
->regs_used
+= param_size
;
3432 static pad_direction
3433 nios2_function_arg_padding (machine_mode mode
, const_tree type
)
3435 /* On little-endian targets, the first byte of every stack argument
3436 is passed in the first byte of the stack slot. */
3437 if (!BYTES_BIG_ENDIAN
)
3440 /* Otherwise, integral types are padded downward: the last byte of a
3441 stack argument is passed in the last byte of the stack slot. */
3443 ? INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
)
3444 : GET_MODE_CLASS (mode
) == MODE_INT
)
3445 return PAD_DOWNWARD
;
3447 /* Arguments smaller than a stack slot are padded downward. */
3448 if (mode
!= BLKmode
)
3449 return (GET_MODE_BITSIZE (mode
) >= PARM_BOUNDARY
3450 ? PAD_UPWARD
: PAD_DOWNWARD
);
3452 return ((int_size_in_bytes (type
) >= (PARM_BOUNDARY
/ BITS_PER_UNIT
))
3453 ? PAD_UPWARD
: PAD_DOWNWARD
);
3457 nios2_block_reg_padding (machine_mode mode
, tree type
,
3458 int first ATTRIBUTE_UNUSED
)
3460 return nios2_function_arg_padding (mode
, type
);
3463 /* Emit RTL insns to initialize the variable parts of a trampoline.
3464 FNADDR is an RTX for the address of the function's pure code.
3465 CXT is an RTX for the static chain value for the function.
3466 On Nios II, we handle this by a library call. */
3468 nios2_trampoline_init (rtx m_tramp
, tree fndecl
, rtx cxt
)
3470 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
3471 rtx ctx_reg
= force_reg (Pmode
, cxt
);
3472 rtx addr
= force_reg (Pmode
, XEXP (m_tramp
, 0));
3474 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "__trampoline_setup"),
3475 LCT_NORMAL
, VOIDmode
, addr
, Pmode
, fnaddr
, Pmode
,
3479 /* Implement TARGET_FUNCTION_VALUE. */
3481 nios2_function_value (const_tree ret_type
, const_tree fn ATTRIBUTE_UNUSED
,
3482 bool outgoing ATTRIBUTE_UNUSED
)
3484 return gen_rtx_REG (TYPE_MODE (ret_type
), FIRST_RETVAL_REGNO
);
3487 /* Implement TARGET_LIBCALL_VALUE. */
3489 nios2_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
3491 return gen_rtx_REG (mode
, FIRST_RETVAL_REGNO
);
3494 /* Implement TARGET_FUNCTION_VALUE_REGNO_P. */
3496 nios2_function_value_regno_p (const unsigned int regno
)
3498 return regno
== FIRST_RETVAL_REGNO
;
3501 /* Implement TARGET_RETURN_IN_MEMORY. */
3503 nios2_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
3505 return (int_size_in_bytes (type
) > (2 * UNITS_PER_WORD
)
3506 || int_size_in_bytes (type
) == -1);
3509 /* TODO: It may be possible to eliminate the copyback and implement
3512 nios2_setup_incoming_varargs (cumulative_args_t cum_v
,
3513 const function_arg_info
&arg
,
3514 int *pretend_size
, int second_time
)
3516 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
3517 CUMULATIVE_ARGS local_cum
;
3518 cumulative_args_t local_cum_v
= pack_cumulative_args (&local_cum
);
3522 cfun
->machine
->uses_anonymous_args
= 1;
3524 nios2_function_arg_advance (local_cum_v
, arg
);
3526 regs_to_push
= NUM_ARG_REGS
- local_cum
.regs_used
;
3528 /* If we can use CDX stwm to push the arguments on the stack,
3529 nios2_expand_prologue will do that instead. */
3530 if (!TARGET_HAS_CDX
&& !second_time
&& regs_to_push
> 0)
3532 rtx ptr
= virtual_incoming_args_rtx
;
3533 rtx mem
= gen_rtx_MEM (BLKmode
, ptr
);
3534 emit_insn (gen_blockage ());
3535 move_block_from_reg (local_cum
.regs_used
+ FIRST_ARG_REGNO
, mem
,
3537 emit_insn (gen_blockage ());
3540 pret_size
= regs_to_push
* UNITS_PER_WORD
;
3542 *pretend_size
= pret_size
;
3547 /* Init FPU builtins. */
3549 nios2_init_fpu_builtins (int start_code
)
3552 char builtin_name
[64] = "__builtin_custom_";
3553 unsigned int i
, n
= strlen ("__builtin_custom_");
3555 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
3557 snprintf (builtin_name
+ n
, sizeof (builtin_name
) - n
,
3558 "%s", N2FPU_NAME (i
));
3560 add_builtin_function (builtin_name
, nios2_ftype (N2FPU_FTCODE (i
)),
3561 start_code
+ i
, BUILT_IN_MD
, NULL
, NULL_TREE
);
3562 nios2_register_builtin_fndecl (start_code
+ i
, fndecl
);
3566 /* Helper function for expanding FPU builtins. */
3568 nios2_expand_fpu_builtin (tree exp
, unsigned int code
, rtx target
)
3570 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
3571 enum insn_code icode
= N2FPU_ICODE (code
);
3572 int nargs
, argno
, opno
= 0;
3573 int num_operands
= N2FPU (code
).num_operands
;
3574 machine_mode dst_mode
= TYPE_MODE (TREE_TYPE (exp
));
3575 bool has_target_p
= (dst_mode
!= VOIDmode
);
3577 if (N2FPU_N (code
) < 0)
3578 fatal_error (input_location
,
3579 "cannot call %<__builtin_custom_%s%> without specifying "
3580 "switch %<-mcustom-%s%>",
3581 N2FPU_NAME (code
), N2FPU_NAME (code
));
3583 create_output_operand (&ops
[opno
++], target
, dst_mode
);
3585 /* Subtract away the count of the VOID return, mainly for fwrx/fwry. */
3587 nargs
= call_expr_nargs (exp
);
3588 for (argno
= 0; argno
< nargs
; argno
++)
3590 tree arg
= CALL_EXPR_ARG (exp
, argno
);
3591 create_input_operand (&ops
[opno
++], expand_normal (arg
),
3592 TYPE_MODE (TREE_TYPE (arg
)));
3594 if (!maybe_expand_insn (icode
, num_operands
, ops
))
3596 error ("invalid argument to built-in function");
3597 return has_target_p
? gen_reg_rtx (ops
[0].mode
) : const0_rtx
;
3599 return has_target_p
? ops
[0].value
: const0_rtx
;
3602 /* Nios II has custom instruction built-in functions of the forms:
3605 __builtin_custom_nXX
3607 __builtin_custom_XnX
3608 __builtin_custom_XnXX
3610 where each X could be either 'i' (int), 'f' (float), or 'p' (void*).
3611 Therefore with 0-1 return values, and 0-2 arguments, we have a
3612 total of (3 + 1) * (1 + 3 + 9) == 52 custom builtin functions.
3614 #define NUM_CUSTOM_BUILTINS ((3 + 1) * (1 + 3 + 9))
3615 static char custom_builtin_name
[NUM_CUSTOM_BUILTINS
][5];
3618 nios2_init_custom_builtins (int start_code
)
3620 tree builtin_ftype
, ret_type
, fndecl
;
3621 char builtin_name
[32] = "__builtin_custom_";
3622 int n
= strlen ("__builtin_custom_");
3623 int builtin_code
= 0;
3624 int lhs
, rhs1
, rhs2
;
3626 struct { tree type
; const char *c
; } op
[4];
3627 /* z */ op
[0].c
= ""; op
[0].type
= NULL_TREE
;
3628 /* f */ op
[1].c
= "f"; op
[1].type
= float_type_node
;
3629 /* i */ op
[2].c
= "i"; op
[2].type
= integer_type_node
;
3630 /* p */ op
[3].c
= "p"; op
[3].type
= ptr_type_node
;
3632 /* We enumerate through the possible operand types to create all the
3633 __builtin_custom_XnXX function tree types. Note that these may slightly
3634 overlap with the function types created for other fixed builtins. */
3636 for (lhs
= 0; lhs
< 4; lhs
++)
3637 for (rhs1
= 0; rhs1
< 4; rhs1
++)
3638 for (rhs2
= 0; rhs2
< 4; rhs2
++)
3640 if (rhs1
== 0 && rhs2
!= 0)
3642 ret_type
= (op
[lhs
].type
? op
[lhs
].type
: void_type_node
);
3644 = build_function_type_list (ret_type
, integer_type_node
,
3645 op
[rhs1
].type
, op
[rhs2
].type
,
3647 /* Save copy of parameter string into custom_builtin_name[]. */
3648 snprintf (custom_builtin_name
[builtin_code
], 5, "%sn%s%s",
3649 op
[lhs
].c
, op
[rhs1
].c
, op
[rhs2
].c
);
3650 strncpy (builtin_name
+ n
, custom_builtin_name
[builtin_code
], 5);
3652 add_builtin_function (builtin_name
, builtin_ftype
,
3653 start_code
+ builtin_code
,
3654 BUILT_IN_MD
, NULL
, NULL_TREE
);
3655 nios2_register_builtin_fndecl (start_code
+ builtin_code
, fndecl
);
3660 /* Helper function for expanding custom builtins. */
3662 nios2_expand_custom_builtin (tree exp
, unsigned int index
, rtx target
)
3664 bool has_target_p
= (TREE_TYPE (exp
) != void_type_node
);
3665 machine_mode tmode
= VOIDmode
;
3667 rtx value
, insn
, unspec_args
[3];
3673 tmode
= TYPE_MODE (TREE_TYPE (exp
));
3674 if (!target
|| GET_MODE (target
) != tmode
3676 target
= gen_reg_rtx (tmode
);
3679 nargs
= call_expr_nargs (exp
);
3680 for (argno
= 0; argno
< nargs
; argno
++)
3682 arg
= CALL_EXPR_ARG (exp
, argno
);
3683 value
= expand_normal (arg
);
3684 unspec_args
[argno
] = value
;
3687 if (!custom_insn_opcode (value
, VOIDmode
))
3688 error ("custom instruction opcode must be a compile-time "
3689 "constant in the range 0-255 for %<__builtin_custom_%s%>",
3690 custom_builtin_name
[index
]);
3693 /* For other arguments, force into a register. */
3694 unspec_args
[argno
] = force_reg (TYPE_MODE (TREE_TYPE (arg
)),
3695 unspec_args
[argno
]);
3697 /* Fill remaining unspec operands with zero. */
3698 for (; argno
< 3; argno
++)
3699 unspec_args
[argno
] = const0_rtx
;
3701 insn
= (has_target_p
3702 ? gen_rtx_SET (target
,
3703 gen_rtx_UNSPEC_VOLATILE (tmode
,
3704 gen_rtvec_v (3, unspec_args
),
3705 UNSPECV_CUSTOM_XNXX
))
3706 : gen_rtx_UNSPEC_VOLATILE (VOIDmode
, gen_rtvec_v (3, unspec_args
),
3707 UNSPECV_CUSTOM_NXX
));
3709 return has_target_p
? target
: const0_rtx
;
3715 /* Main definition of built-in functions. Nios II has a small number of fixed
3716 builtins, plus a large number of FPU insn builtins, and builtins for
3717 generating custom instructions. */
3719 struct nios2_builtin_desc
3721 enum insn_code icode
;
3722 enum nios2_arch_type arch
;
3723 enum nios2_ftcode ftype
;
3727 #define N2_BUILTINS \
3728 N2_BUILTIN_DEF (sync, R1, N2_FTYPE_VOID_VOID) \
3729 N2_BUILTIN_DEF (ldbio, R1, N2_FTYPE_SI_CVPTR) \
3730 N2_BUILTIN_DEF (ldbuio, R1, N2_FTYPE_UI_CVPTR) \
3731 N2_BUILTIN_DEF (ldhio, R1, N2_FTYPE_SI_CVPTR) \
3732 N2_BUILTIN_DEF (ldhuio, R1, N2_FTYPE_UI_CVPTR) \
3733 N2_BUILTIN_DEF (ldwio, R1, N2_FTYPE_SI_CVPTR) \
3734 N2_BUILTIN_DEF (stbio, R1, N2_FTYPE_VOID_VPTR_SI) \
3735 N2_BUILTIN_DEF (sthio, R1, N2_FTYPE_VOID_VPTR_SI) \
3736 N2_BUILTIN_DEF (stwio, R1, N2_FTYPE_VOID_VPTR_SI) \
3737 N2_BUILTIN_DEF (rdctl, R1, N2_FTYPE_SI_SI) \
3738 N2_BUILTIN_DEF (wrctl, R1, N2_FTYPE_VOID_SI_SI) \
3739 N2_BUILTIN_DEF (rdprs, R1, N2_FTYPE_SI_SI_SI) \
3740 N2_BUILTIN_DEF (flushd, R1, N2_FTYPE_VOID_VPTR) \
3741 N2_BUILTIN_DEF (flushda, R1, N2_FTYPE_VOID_VPTR) \
3742 N2_BUILTIN_DEF (wrpie, R2, N2_FTYPE_SI_SI) \
3743 N2_BUILTIN_DEF (eni, R2, N2_FTYPE_VOID_SI) \
3744 N2_BUILTIN_DEF (ldex, R2, N2_FTYPE_SI_CVPTR) \
3745 N2_BUILTIN_DEF (ldsex, R2, N2_FTYPE_SI_CVPTR) \
3746 N2_BUILTIN_DEF (stex, R2, N2_FTYPE_SI_VPTR_SI) \
3747 N2_BUILTIN_DEF (stsex, R2, N2_FTYPE_SI_VPTR_SI)
3749 enum nios2_builtin_code
{
3750 #define N2_BUILTIN_DEF(name, arch, ftype) NIOS2_BUILTIN_ ## name,
3752 #undef N2_BUILTIN_DEF
3753 NUM_FIXED_NIOS2_BUILTINS
3756 static const struct nios2_builtin_desc nios2_builtins
[] = {
3757 #define N2_BUILTIN_DEF(name, arch, ftype) \
3758 { CODE_FOR_ ## name, ARCH_ ## arch, ftype, "__builtin_" #name },
3760 #undef N2_BUILTIN_DEF
3763 /* Start/ends of FPU/custom insn builtin index ranges. */
3764 static unsigned int nios2_fpu_builtin_base
;
3765 static unsigned int nios2_custom_builtin_base
;
3766 static unsigned int nios2_custom_builtin_end
;
3768 /* Implement TARGET_INIT_BUILTINS. */
3770 nios2_init_builtins (void)
3774 /* Initialize fixed builtins. */
3775 for (i
= 0; i
< ARRAY_SIZE (nios2_builtins
); i
++)
3777 const struct nios2_builtin_desc
*d
= &nios2_builtins
[i
];
3779 add_builtin_function (d
->name
, nios2_ftype (d
->ftype
), i
,
3780 BUILT_IN_MD
, NULL
, NULL
);
3781 nios2_register_builtin_fndecl (i
, fndecl
);
3784 /* Initialize FPU builtins. */
3785 nios2_fpu_builtin_base
= ARRAY_SIZE (nios2_builtins
);
3786 nios2_init_fpu_builtins (nios2_fpu_builtin_base
);
3788 /* Initialize custom insn builtins. */
3789 nios2_custom_builtin_base
3790 = nios2_fpu_builtin_base
+ ARRAY_SIZE (nios2_fpu_insn
);
3791 nios2_custom_builtin_end
3792 = nios2_custom_builtin_base
+ NUM_CUSTOM_BUILTINS
;
3793 nios2_init_custom_builtins (nios2_custom_builtin_base
);
3796 /* Array of fndecls for TARGET_BUILTIN_DECL. */
3797 #define NIOS2_NUM_BUILTINS \
3798 (ARRAY_SIZE (nios2_builtins) + ARRAY_SIZE (nios2_fpu_insn) + NUM_CUSTOM_BUILTINS)
3799 static GTY(()) tree nios2_builtin_decls
[NIOS2_NUM_BUILTINS
];
3802 nios2_register_builtin_fndecl (unsigned code
, tree fndecl
)
3804 nios2_builtin_decls
[code
] = fndecl
;
3807 /* Implement TARGET_BUILTIN_DECL. */
3809 nios2_builtin_decl (unsigned code
, bool initialize_p ATTRIBUTE_UNUSED
)
3811 gcc_assert (nios2_custom_builtin_end
== ARRAY_SIZE (nios2_builtin_decls
));
3813 if (code
>= nios2_custom_builtin_end
)
3814 return error_mark_node
;
3816 if (code
>= nios2_fpu_builtin_base
3817 && code
< nios2_custom_builtin_base
3818 && ! N2FPU_ENABLED_P (code
- nios2_fpu_builtin_base
))
3819 return error_mark_node
;
3821 return nios2_builtin_decls
[code
];
3825 /* Low-level built-in expand routine. */
3827 nios2_expand_builtin_insn (const struct nios2_builtin_desc
*d
, int n
,
3828 struct expand_operand
*ops
, bool has_target_p
)
3830 if (maybe_expand_insn (d
->icode
, n
, ops
))
3831 return has_target_p
? ops
[0].value
: const0_rtx
;
3834 error ("invalid argument to built-in function %s", d
->name
);
3835 return has_target_p
? gen_reg_rtx (ops
[0].mode
) : const0_rtx
;
3839 /* Expand ldio/stio and ldex/ldsex/stex/stsex form load-store
3840 instruction builtins. */
3842 nios2_expand_ldst_builtin (tree exp
, rtx target
,
3843 const struct nios2_builtin_desc
*d
)
3847 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
3848 machine_mode mode
= insn_data
[d
->icode
].operand
[0].mode
;
3850 addr
= expand_normal (CALL_EXPR_ARG (exp
, 0));
3851 mem
= gen_rtx_MEM (mode
, addr
);
3853 if (insn_data
[d
->icode
].operand
[0].allows_mem
)
3855 /* stxio/stex/stsex. */
3856 val
= expand_normal (CALL_EXPR_ARG (exp
, 1));
3857 if (CONST_INT_P (val
))
3858 val
= force_reg (mode
, gen_int_mode (INTVAL (val
), mode
));
3859 val
= simplify_gen_subreg (mode
, val
, GET_MODE (val
), 0);
3860 create_output_operand (&ops
[0], mem
, mode
);
3861 create_input_operand (&ops
[1], val
, mode
);
3862 if (insn_data
[d
->icode
].n_operands
== 3)
3864 /* stex/stsex status value, returned as result of function. */
3865 create_output_operand (&ops
[2], target
, mode
);
3866 has_target_p
= true;
3869 has_target_p
= false;
3874 create_output_operand (&ops
[0], target
, mode
);
3875 create_input_operand (&ops
[1], mem
, mode
);
3876 has_target_p
= true;
3878 return nios2_expand_builtin_insn (d
, insn_data
[d
->icode
].n_operands
, ops
,
3882 /* Expand rdctl/wrctl builtins. */
3884 nios2_expand_rdwrctl_builtin (tree exp
, rtx target
,
3885 const struct nios2_builtin_desc
*d
)
3887 bool has_target_p
= (insn_data
[d
->icode
].operand
[0].predicate
3888 == register_operand
);
3889 rtx ctlcode
= expand_normal (CALL_EXPR_ARG (exp
, 0));
3890 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
3891 if (!rdwrctl_operand (ctlcode
, VOIDmode
))
3893 error ("control register number must be in range 0-31 for %s",
3895 return has_target_p
? gen_reg_rtx (SImode
) : const0_rtx
;
3899 create_output_operand (&ops
[0], target
, SImode
);
3900 create_integer_operand (&ops
[1], INTVAL (ctlcode
));
3904 rtx val
= expand_normal (CALL_EXPR_ARG (exp
, 1));
3905 create_integer_operand (&ops
[0], INTVAL (ctlcode
));
3906 create_input_operand (&ops
[1], val
, SImode
);
3908 return nios2_expand_builtin_insn (d
, 2, ops
, has_target_p
);
3912 nios2_expand_rdprs_builtin (tree exp
, rtx target
,
3913 const struct nios2_builtin_desc
*d
)
3915 rtx reg
= expand_normal (CALL_EXPR_ARG (exp
, 0));
3916 rtx imm
= expand_normal (CALL_EXPR_ARG (exp
, 1));
3917 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
3919 if (!rdwrctl_operand (reg
, VOIDmode
))
3921 error ("register number must be in range 0-31 for %s",
3923 return gen_reg_rtx (SImode
);
3926 if (!rdprs_dcache_operand (imm
, VOIDmode
))
3928 error ("immediate value must fit into a %d-bit integer for %s",
3929 (TARGET_ARCH_R2
) ? 12 : 16, d
->name
);
3930 return gen_reg_rtx (SImode
);
3933 create_output_operand (&ops
[0], target
, SImode
);
3934 create_input_operand (&ops
[1], reg
, SImode
);
3935 create_integer_operand (&ops
[2], INTVAL (imm
));
3937 return nios2_expand_builtin_insn (d
, 3, ops
, true);
3941 nios2_expand_cache_builtin (tree exp
, rtx target ATTRIBUTE_UNUSED
,
3942 const struct nios2_builtin_desc
*d
)
3945 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
3947 addr
= expand_normal (CALL_EXPR_ARG (exp
, 0));
3948 mem
= gen_rtx_MEM (SImode
, addr
);
3950 create_input_operand (&ops
[0], mem
, SImode
);
3952 return nios2_expand_builtin_insn (d
, 1, ops
, false);
3956 nios2_expand_wrpie_builtin (tree exp
, rtx target
,
3957 const struct nios2_builtin_desc
*d
)
3960 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
3962 val
= expand_normal (CALL_EXPR_ARG (exp
, 0));
3963 create_input_operand (&ops
[1], val
, SImode
);
3964 create_output_operand (&ops
[0], target
, SImode
);
3966 return nios2_expand_builtin_insn (d
, 2, ops
, true);
3970 nios2_expand_eni_builtin (tree exp
, rtx target ATTRIBUTE_UNUSED
,
3971 const struct nios2_builtin_desc
*d
)
3973 rtx imm
= expand_normal (CALL_EXPR_ARG (exp
, 0));
3974 struct expand_operand ops
[MAX_RECOG_OPERANDS
];
3976 if (INTVAL (imm
) != 0 && INTVAL (imm
) != 1)
3978 error ("the ENI instruction operand must be either 0 or 1");
3981 create_integer_operand (&ops
[0], INTVAL (imm
));
3983 return nios2_expand_builtin_insn (d
, 1, ops
, false);
3986 /* Implement TARGET_EXPAND_BUILTIN. Expand an expression EXP that calls
3987 a built-in function, with result going to TARGET if that's convenient
3988 (and in mode MODE if that's convenient).
3989 SUBTARGET may be used as the target for computing one of EXP's operands.
3990 IGNORE is nonzero if the value is to be ignored. */
3993 nios2_expand_builtin (tree exp
, rtx target
, rtx subtarget ATTRIBUTE_UNUSED
,
3994 machine_mode mode ATTRIBUTE_UNUSED
,
3995 int ignore ATTRIBUTE_UNUSED
)
3997 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
3998 unsigned int fcode
= DECL_MD_FUNCTION_CODE (fndecl
);
4000 if (fcode
< nios2_fpu_builtin_base
)
4002 const struct nios2_builtin_desc
*d
= &nios2_builtins
[fcode
];
4004 if (d
->arch
> nios2_arch_option
)
4006 error ("built-in function %s requires Nios II R%d",
4007 d
->name
, (int) d
->arch
);
4008 /* Given it is invalid, just generate a normal call. */
4009 return expand_call (exp
, target
, ignore
);
4014 case NIOS2_BUILTIN_sync
:
4015 emit_insn (gen_sync ());
4018 case NIOS2_BUILTIN_ldbio
:
4019 case NIOS2_BUILTIN_ldbuio
:
4020 case NIOS2_BUILTIN_ldhio
:
4021 case NIOS2_BUILTIN_ldhuio
:
4022 case NIOS2_BUILTIN_ldwio
:
4023 case NIOS2_BUILTIN_stbio
:
4024 case NIOS2_BUILTIN_sthio
:
4025 case NIOS2_BUILTIN_stwio
:
4026 case NIOS2_BUILTIN_ldex
:
4027 case NIOS2_BUILTIN_ldsex
:
4028 case NIOS2_BUILTIN_stex
:
4029 case NIOS2_BUILTIN_stsex
:
4030 return nios2_expand_ldst_builtin (exp
, target
, d
);
4032 case NIOS2_BUILTIN_rdctl
:
4033 case NIOS2_BUILTIN_wrctl
:
4034 return nios2_expand_rdwrctl_builtin (exp
, target
, d
);
4036 case NIOS2_BUILTIN_rdprs
:
4037 return nios2_expand_rdprs_builtin (exp
, target
, d
);
4039 case NIOS2_BUILTIN_flushd
:
4040 case NIOS2_BUILTIN_flushda
:
4041 return nios2_expand_cache_builtin (exp
, target
, d
);
4043 case NIOS2_BUILTIN_wrpie
:
4044 return nios2_expand_wrpie_builtin (exp
, target
, d
);
4046 case NIOS2_BUILTIN_eni
:
4047 return nios2_expand_eni_builtin (exp
, target
, d
);
4053 else if (fcode
< nios2_custom_builtin_base
)
4054 /* FPU builtin range. */
4055 return nios2_expand_fpu_builtin (exp
, fcode
- nios2_fpu_builtin_base
,
4057 else if (fcode
< nios2_custom_builtin_end
)
4058 /* Custom insn builtin range. */
4059 return nios2_expand_custom_builtin (exp
, fcode
- nios2_custom_builtin_base
,
4065 /* Implement TARGET_INIT_LIBFUNCS. */
4066 static void ATTRIBUTE_UNUSED
4067 nios2_init_libfuncs (void)
4069 init_sync_libfuncs (UNITS_PER_WORD
);
4074 /* Register a custom code use, and signal error if a conflict was found. */
4076 nios2_register_custom_code (unsigned int N
, enum nios2_ccs_code status
,
4079 gcc_assert (N
<= 255);
4081 if (status
== CCS_FPU
)
4083 if (custom_code_status
[N
] == CCS_FPU
&& index
!= custom_code_index
[N
])
4085 custom_code_conflict
= true;
4086 error ("switch %<-mcustom-%s%> conflicts with "
4087 "switch %<-mcustom-%s%>",
4088 N2FPU_NAME (custom_code_index
[N
]), N2FPU_NAME (index
));
4090 else if (custom_code_status
[N
] == CCS_BUILTIN_CALL
)
4092 custom_code_conflict
= true;
4093 error ("call to %<__builtin_custom_%s%> conflicts with "
4094 "switch %<-mcustom-%s%>",
4095 custom_builtin_name
[custom_code_index
[N
]],
4096 N2FPU_NAME (index
));
4099 else if (status
== CCS_BUILTIN_CALL
)
4101 if (custom_code_status
[N
] == CCS_FPU
)
4103 custom_code_conflict
= true;
4104 error ("call to %<__builtin_custom_%s%> conflicts with "
4105 "switch %<-mcustom-%s%>",
4106 custom_builtin_name
[index
],
4107 N2FPU_NAME (custom_code_index
[N
]));
4111 /* Note that code conflicts between different __builtin_custom_xnxx
4112 calls are not checked. */
4118 custom_code_status
[N
] = status
;
4119 custom_code_index
[N
] = index
;
4122 /* Mark a custom code as not in use. */
4124 nios2_deregister_custom_code (unsigned int N
)
4128 custom_code_status
[N
] = CCS_UNUSED
;
4129 custom_code_index
[N
] = 0;
4133 /* Target attributes can affect per-function option state, so we need to
4134 save/restore the custom code tracking info using the
4135 TARGET_OPTION_SAVE/TARGET_OPTION_RESTORE hooks. */
4138 nios2_option_save (struct cl_target_option
*ptr
,
4139 struct gcc_options
*opts ATTRIBUTE_UNUSED
,
4140 struct gcc_options
*opts_set ATTRIBUTE_UNUSED
)
4143 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
4144 ptr
->saved_fpu_custom_code
[i
] = N2FPU_N (i
);
4145 memcpy (ptr
->saved_custom_code_status
, custom_code_status
,
4146 sizeof (custom_code_status
));
4147 memcpy (ptr
->saved_custom_code_index
, custom_code_index
,
4148 sizeof (custom_code_index
));
4152 nios2_option_restore (struct gcc_options
*opts ATTRIBUTE_UNUSED
,
4153 struct gcc_options
*opts_set ATTRIBUTE_UNUSED
,
4154 struct cl_target_option
*ptr
)
4157 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
4158 N2FPU_N (i
) = ptr
->saved_fpu_custom_code
[i
];
4159 memcpy (custom_code_status
, ptr
->saved_custom_code_status
,
4160 sizeof (custom_code_status
));
4161 memcpy (custom_code_index
, ptr
->saved_custom_code_index
,
4162 sizeof (custom_code_index
));
4166 nios2_can_inline_p (tree caller
, tree callee
)
4168 tree callee_opts
= DECL_FUNCTION_SPECIFIC_TARGET (callee
);
4169 tree caller_opts
= DECL_FUNCTION_SPECIFIC_TARGET (caller
);
4170 struct cl_target_option
*callee_ptr
, *caller_ptr
;
4174 callee_opts
= target_option_default_node
;
4176 caller_opts
= target_option_default_node
;
4178 /* If both caller and callee have attributes, assume that if the
4179 pointer is different, the two functions have different target
4180 options since build_target_option_node uses a hash table for the
4182 if (callee_opts
== caller_opts
)
4185 /* The only target options we recognize via function attributes are
4186 those related to custom instructions. If we failed the above test,
4187 check that any custom instructions enabled in the callee are also
4188 enabled with the same value in the caller. */
4189 callee_ptr
= TREE_TARGET_OPTION (callee_opts
);
4190 caller_ptr
= TREE_TARGET_OPTION (caller_opts
);
4191 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
4192 if (callee_ptr
->saved_fpu_custom_code
[i
] != -1
4193 && (callee_ptr
->saved_fpu_custom_code
[i
]
4194 != caller_ptr
->saved_fpu_custom_code
[i
]))
4199 /* Inner function to process the attribute((target(...))), take an argument and
4200 set the current options from the argument. If we have a list, recursively
4201 go over the list. */
4204 nios2_valid_target_attribute_rec (tree args
)
4206 if (TREE_CODE (args
) == TREE_LIST
)
4209 for (; args
; args
= TREE_CHAIN (args
))
4210 if (TREE_VALUE (args
)
4211 && !nios2_valid_target_attribute_rec (TREE_VALUE (args
)))
4215 else if (TREE_CODE (args
) == STRING_CST
)
4217 char *argstr
= ASTRDUP (TREE_STRING_POINTER (args
));
4218 while (argstr
&& *argstr
!= '\0')
4220 bool no_opt
= false, end_p
= false;
4221 char *eq
= NULL
, *p
;
4222 while (ISSPACE (*argstr
))
4225 while (*p
!= '\0' && *p
!= ',')
4227 if (!eq
&& *p
== '=')
4237 if (startswith (argstr
, "no-"))
4242 if (startswith (argstr
, "custom-fpu-cfg"))
4247 error ("%<custom-fpu-cfg%> option does not support %<no-%>");
4252 error ("%<custom-fpu-cfg%> option requires configuration "
4256 /* Increment and skip whitespace. */
4257 while (ISSPACE (*(++eq
))) ;
4258 /* Decrement and skip to before any trailing whitespace. */
4259 while (ISSPACE (*(--end_eq
))) ;
4261 nios2_handle_custom_fpu_cfg (eq
, end_eq
+ 1, true);
4263 else if (startswith (argstr
, "custom-"))
4267 for (i
= 0; i
< ARRAY_SIZE (nios2_fpu_insn
); i
++)
4268 if (startswith (argstr
+ 7, N2FPU_NAME (i
)))
4280 error ("%<no-custom-%s%> does not accept arguments",
4284 /* Disable option by setting to -1. */
4285 nios2_deregister_custom_code (N2FPU_N (code
));
4286 N2FPU_N (code
) = -1;
4292 while (ISSPACE (*(++eq
))) ;
4295 error ("%<custom-%s=%> requires argument",
4299 for (t
= eq
; t
!= p
; ++t
)
4305 error ("%<custom-%s=%> argument should be "
4306 "a non-negative integer", N2FPU_NAME (code
));
4310 /* Set option to argument. */
4311 N2FPU_N (code
) = atoi (eq
);
4312 nios2_handle_custom_fpu_insn_option (code
);
4317 error ("%<custom-%s=%> is not recognized as FPU instruction",
4324 error ("invalid custom instruction option %qs", argstr
);
4339 /* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. */
4342 nios2_valid_target_attribute_tree (tree args
)
4344 if (!nios2_valid_target_attribute_rec (args
))
4346 nios2_custom_check_insns ();
4347 return build_target_option_node (&global_options
, &global_options_set
);
4350 /* Hook to validate attribute((target("string"))). */
4353 nios2_valid_target_attribute_p (tree fndecl
, tree
ARG_UNUSED (name
),
4354 tree args
, int ARG_UNUSED (flags
))
4356 struct cl_target_option cur_target
;
4359 = build_optimization_node (&global_options
, &global_options_set
);
4360 tree new_target
, new_optimize
;
4361 tree func_optimize
= DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl
);
4363 /* If the function changed the optimization levels as well as setting target
4364 options, start with the optimizations specified. */
4365 if (func_optimize
&& func_optimize
!= old_optimize
)
4366 cl_optimization_restore (&global_options
, &global_options_set
,
4367 TREE_OPTIMIZATION (func_optimize
));
4369 /* The target attributes may also change some optimization flags, so update
4370 the optimization options if necessary. */
4371 cl_target_option_save (&cur_target
, &global_options
, &global_options_set
);
4372 new_target
= nios2_valid_target_attribute_tree (args
);
4373 new_optimize
= build_optimization_node (&global_options
, &global_options_set
);
4380 DECL_FUNCTION_SPECIFIC_TARGET (fndecl
) = new_target
;
4382 if (old_optimize
!= new_optimize
)
4383 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl
) = new_optimize
;
4386 cl_target_option_restore (&global_options
, &global_options_set
, &cur_target
);
4388 if (old_optimize
!= new_optimize
)
4389 cl_optimization_restore (&global_options
, &global_options_set
,
4390 TREE_OPTIMIZATION (old_optimize
));
4394 /* Remember the last target of nios2_set_current_function. */
4395 static GTY(()) tree nios2_previous_fndecl
;
4397 /* Establish appropriate back-end context for processing the function
4398 FNDECL. The argument might be NULL to indicate processing at top
4399 level, outside of any function scope. */
4401 nios2_set_current_function (tree fndecl
)
4403 tree old_tree
= (nios2_previous_fndecl
4404 ? DECL_FUNCTION_SPECIFIC_TARGET (nios2_previous_fndecl
)
4407 tree new_tree
= (fndecl
4408 ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl
)
4411 if (fndecl
&& fndecl
!= nios2_previous_fndecl
)
4413 nios2_previous_fndecl
= fndecl
;
4414 if (old_tree
== new_tree
)
4419 cl_target_option_restore (&global_options
, &global_options_set
,
4420 TREE_TARGET_OPTION (new_tree
));
4426 struct cl_target_option
*def
4427 = TREE_TARGET_OPTION (target_option_current_node
);
4429 cl_target_option_restore (&global_options
, &global_options_set
, def
);
4435 /* Hook to validate the current #pragma GCC target and set the FPU custom
4436 code option state. If ARGS is NULL, then POP_TARGET is used to reset
4439 nios2_pragma_target_parse (tree args
, tree pop_target
)
4444 cur_tree
= ((pop_target
)
4446 : target_option_default_node
);
4447 cl_target_option_restore (&global_options
, &global_options_set
,
4448 TREE_TARGET_OPTION (cur_tree
));
4452 cur_tree
= nios2_valid_target_attribute_tree (args
);
4457 target_option_current_node
= cur_tree
;
4461 /* Implement TARGET_MERGE_DECL_ATTRIBUTES.
4462 We are just using this hook to add some additional error checking to
4463 the default behavior. GCC does not provide a target hook for merging
4464 the target options, and only correctly handles merging empty vs non-empty
4465 option data; see merge_decls() in c-decl.c.
4466 So here we require either that at least one of the decls has empty
4467 target options, or that the target options/data be identical. */
4469 nios2_merge_decl_attributes (tree olddecl
, tree newdecl
)
4471 tree oldopts
= lookup_attribute ("target", DECL_ATTRIBUTES (olddecl
));
4472 tree newopts
= lookup_attribute ("target", DECL_ATTRIBUTES (newdecl
));
4473 if (newopts
&& oldopts
&& newopts
!= oldopts
)
4475 tree oldtree
= DECL_FUNCTION_SPECIFIC_TARGET (olddecl
);
4476 tree newtree
= DECL_FUNCTION_SPECIFIC_TARGET (newdecl
);
4477 if (oldtree
&& newtree
&& oldtree
!= newtree
)
4479 struct cl_target_option
*olddata
= TREE_TARGET_OPTION (oldtree
);
4480 struct cl_target_option
*newdata
= TREE_TARGET_OPTION (newtree
);
4481 if (olddata
!= newdata
4482 && memcmp (olddata
, newdata
, sizeof (struct cl_target_option
)))
4483 error ("%qE redeclared with conflicting %qs attributes",
4484 DECL_NAME (newdecl
), "target");
4487 return merge_attributes (DECL_ATTRIBUTES (olddecl
),
4488 DECL_ATTRIBUTES (newdecl
));
4491 /* Implement TARGET_ASM_OUTPUT_MI_THUNK. */
4493 nios2_asm_output_mi_thunk (FILE *file
, tree thunk_fndecl ATTRIBUTE_UNUSED
,
4494 HOST_WIDE_INT delta
, HOST_WIDE_INT vcall_offset
,
4497 const char *fnname
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl
));
4498 rtx this_rtx
, funexp
;
4501 /* Pretend to be a post-reload pass while generating rtl. */
4502 reload_completed
= 1;
4505 nios2_load_pic_register ();
4507 /* Mark the end of the (empty) prologue. */
4508 emit_note (NOTE_INSN_PROLOGUE_END
);
4510 /* Find the "this" pointer. If the function returns a structure,
4511 the structure return pointer is in $5. */
4512 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
))
4513 this_rtx
= gen_rtx_REG (Pmode
, FIRST_ARG_REGNO
+ 1);
4515 this_rtx
= gen_rtx_REG (Pmode
, FIRST_ARG_REGNO
);
4517 /* Add DELTA to THIS_RTX. */
4518 nios2_emit_add_constant (this_rtx
, delta
);
4520 /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */
4525 tmp
= gen_rtx_REG (Pmode
, 2);
4526 emit_move_insn (tmp
, gen_rtx_MEM (Pmode
, this_rtx
));
4527 nios2_emit_add_constant (tmp
, vcall_offset
);
4528 emit_move_insn (tmp
, gen_rtx_MEM (Pmode
, tmp
));
4529 emit_insn (gen_add2_insn (this_rtx
, tmp
));
4532 /* Generate a tail call to the target function. */
4533 if (!TREE_USED (function
))
4535 assemble_external (function
);
4536 TREE_USED (function
) = 1;
4538 funexp
= XEXP (DECL_RTL (function
), 0);
4539 /* Function address needs to be constructed under PIC,
4540 provide r2 to use here. */
4541 nios2_adjust_call_address (&funexp
, gen_rtx_REG (Pmode
, 2));
4542 insn
= emit_call_insn (gen_sibcall_internal (funexp
, const0_rtx
));
4543 SIBLING_CALL_P (insn
) = 1;
4545 /* Run just enough of rest_of_compilation to get the insns emitted.
4546 There's not really enough bulk here to make other passes such as
4547 instruction scheduling worth while. */
4548 insn
= get_insns ();
4549 shorten_branches (insn
);
4550 assemble_start_function (thunk_fndecl
, fnname
);
4551 final_start_function (insn
, file
, 1);
4552 final (insn
, file
, 1);
4553 final_end_function ();
4554 assemble_end_function (thunk_fndecl
, fnname
);
4556 /* Stop pretending to be a post-reload pass. */
4557 reload_completed
= 0;
4561 /* Utility function to break a memory address into
4562 base register + constant offset. Return false if something
4563 unexpected is seen. */
4565 split_mem_address (rtx addr
, rtx
*base_reg
, rtx
*offset
)
4570 *offset
= const0_rtx
;
4573 else if (GET_CODE (addr
) == PLUS
)
4575 *base_reg
= XEXP (addr
, 0);
4576 *offset
= XEXP (addr
, 1);
4582 /* Splits out the operands of an ALU insn, places them in *LHS, *RHS1, *RHS2. */
4584 split_alu_insn (rtx_insn
*insn
, rtx
*lhs
, rtx
*rhs1
, rtx
*rhs2
)
4586 rtx pat
= PATTERN (insn
);
4587 gcc_assert (GET_CODE (pat
) == SET
);
4588 *lhs
= SET_DEST (pat
);
4589 *rhs1
= XEXP (SET_SRC (pat
), 0);
4590 if (GET_RTX_CLASS (GET_CODE (SET_SRC (pat
))) != RTX_UNARY
)
4591 *rhs2
= XEXP (SET_SRC (pat
), 1);
4595 /* Returns true if OP is a REG and assigned a CDX reg. */
4599 return REG_P (op
) && (!reload_completed
|| CDX_REG_P (REGNO (op
)));
4602 /* Returns true if OP is within range of CDX addi.n immediates. */
4604 cdx_add_immed (rtx op
)
4606 if (CONST_INT_P (op
))
4608 HOST_WIDE_INT ival
= INTVAL (op
);
4609 return ival
<= 128 && ival
> 0 && (ival
& (ival
- 1)) == 0;
4614 /* Returns true if OP is within range of CDX andi.n immediates. */
4616 cdx_and_immed (rtx op
)
4618 if (CONST_INT_P (op
))
4620 HOST_WIDE_INT ival
= INTVAL (op
);
4621 return (ival
== 1 || ival
== 2 || ival
== 3 || ival
== 4
4622 || ival
== 8 || ival
== 0xf || ival
== 0x10
4623 || ival
== 0x1f || ival
== 0x20
4624 || ival
== 0x3f || ival
== 0x7f
4625 || ival
== 0x80 || ival
== 0xff || ival
== 0x7ff
4626 || ival
== 0xff00 || ival
== 0xffff);
4631 /* Returns true if OP is within range of CDX movi.n immediates. */
4633 cdx_mov_immed (rtx op
)
4635 if (CONST_INT_P (op
))
4637 HOST_WIDE_INT ival
= INTVAL (op
);
4638 return ((ival
>= 0 && ival
<= 124)
4639 || ival
== 0xff || ival
== -2 || ival
== -1);
4644 /* Returns true if OP is within range of CDX slli.n/srli.n immediates. */
4646 cdx_shift_immed (rtx op
)
4648 if (CONST_INT_P (op
))
4650 HOST_WIDE_INT ival
= INTVAL (op
);
4651 return (ival
== 1 || ival
== 2 || ival
== 3 || ival
== 8
4652 || ival
== 12 || ival
== 16 || ival
== 24
4660 /* Classification of different kinds of add instructions. */
4661 enum nios2_add_insn_kind
{
4665 nios2_spaddi_n_kind
,
4666 nios2_spinci_n_kind
,
4667 nios2_spdeci_n_kind
,
4672 static const char *nios2_add_insn_names
[] = {
4673 "add.n", "addi.n", "subi.n", "spaddi.n", "spinci.n", "spdeci.n",
4675 static bool nios2_add_insn_narrow
[] = {
4676 true, true, true, true, true, true,
4679 /* Function to classify kinds of add instruction patterns. */
4680 static enum nios2_add_insn_kind
4681 nios2_add_insn_classify (rtx_insn
*insn ATTRIBUTE_UNUSED
,
4682 rtx lhs
, rtx rhs1
, rtx rhs2
)
4686 if (cdxreg (lhs
) && cdxreg (rhs1
))
4689 return nios2_add_n_kind
;
4690 if (CONST_INT_P (rhs2
))
4692 HOST_WIDE_INT ival
= INTVAL (rhs2
);
4693 if (ival
> 0 && cdx_add_immed (rhs2
))
4694 return nios2_addi_n_kind
;
4695 if (ival
< 0 && cdx_add_immed (GEN_INT (-ival
)))
4696 return nios2_subi_n_kind
;
4699 else if (rhs1
== stack_pointer_rtx
4700 && CONST_INT_P (rhs2
))
4702 HOST_WIDE_INT imm7
= INTVAL (rhs2
) >> 2;
4703 HOST_WIDE_INT rem
= INTVAL (rhs2
) & 3;
4704 if (rem
== 0 && (imm7
& ~0x7f) == 0)
4707 return nios2_spaddi_n_kind
;
4708 if (lhs
== stack_pointer_rtx
)
4709 return nios2_spinci_n_kind
;
4711 imm7
= -INTVAL(rhs2
) >> 2;
4712 rem
= -INTVAL (rhs2
) & 3;
4713 if (lhs
== stack_pointer_rtx
4714 && rem
== 0 && (imm7
& ~0x7f) == 0)
4715 return nios2_spdeci_n_kind
;
4718 return ((REG_P (rhs2
) || rhs2
== const0_rtx
)
4719 ? nios2_add_kind
: nios2_addi_kind
);
4722 /* Emit assembly language for the different kinds of add instructions. */
4724 nios2_add_insn_asm (rtx_insn
*insn
, rtx
*operands
)
4726 static char buf
[256];
4728 enum nios2_add_insn_kind kind
4729 = nios2_add_insn_classify (insn
, operands
[0], operands
[1], operands
[2]);
4730 if (kind
== nios2_subi_n_kind
)
4731 snprintf (buf
, ln
, "subi.n\t%%0, %%1, %d", (int) -INTVAL (operands
[2]));
4732 else if (kind
== nios2_spaddi_n_kind
)
4733 snprintf (buf
, ln
, "spaddi.n\t%%0, %%2");
4734 else if (kind
== nios2_spinci_n_kind
)
4735 snprintf (buf
, ln
, "spinci.n\t%%2");
4736 else if (kind
== nios2_spdeci_n_kind
)
4737 snprintf (buf
, ln
, "spdeci.n\t%d", (int) -INTVAL (operands
[2]));
4739 snprintf (buf
, ln
, "%s\t%%0, %%1, %%z2", nios2_add_insn_names
[(int)kind
]);
4743 /* This routine, which the default "length" attribute computation is
4744 based on, encapsulates information about all the cases where CDX
4745 provides a narrow 2-byte instruction form. */
4747 nios2_cdx_narrow_form_p (rtx_insn
*insn
)
4749 rtx pat
, lhs
, rhs1
= NULL_RTX
, rhs2
= NULL_RTX
;
4750 enum attr_type type
;
4751 if (!TARGET_HAS_CDX
)
4753 type
= get_attr_type (insn
);
4754 pat
= PATTERN (insn
);
4755 gcc_assert (reload_completed
);
4759 if (GET_CODE (pat
) == SIMPLE_RETURN
)
4761 if (GET_CODE (pat
) == PARALLEL
)
4762 pat
= XVECEXP (pat
, 0, 0);
4763 if (GET_CODE (pat
) == SET
)
4764 pat
= SET_SRC (pat
);
4765 if (GET_CODE (pat
) == IF_THEN_ELSE
)
4767 /* Conditional branch patterns; for these we
4768 only check the comparison to find beqz.n/bnez.n cases.
4769 For the 'nios2_cbranch' pattern, we cannot also check
4770 the branch range here. That will be done at the md
4771 pattern "length" attribute computation. */
4772 rtx cmp
= XEXP (pat
, 0);
4773 return ((GET_CODE (cmp
) == EQ
|| GET_CODE (cmp
) == NE
)
4774 && cdxreg (XEXP (cmp
, 0))
4775 && XEXP (cmp
, 1) == const0_rtx
);
4777 if (GET_CODE (pat
) == TRAP_IF
)
4778 /* trap.n is always usable. */
4780 if (GET_CODE (pat
) == CALL
)
4781 pat
= XEXP (XEXP (pat
, 0), 0);
4783 /* Control instructions taking a register operand are indirect
4784 jumps and calls. The CDX instructions have a 5-bit register
4785 field so any reg is valid. */
4789 gcc_assert (!insn_variable_length_p (insn
));
4794 enum nios2_add_insn_kind kind
;
4795 split_alu_insn (insn
, &lhs
, &rhs1
, &rhs2
);
4796 kind
= nios2_add_insn_classify (insn
, lhs
, rhs1
, rhs2
);
4797 return nios2_add_insn_narrow
[(int)kind
];
4802 HOST_WIDE_INT offset
, rem
= 0;
4803 rtx addr
, reg
= SET_DEST (pat
), mem
= SET_SRC (pat
);
4804 if (GET_CODE (mem
) == SIGN_EXTEND
)
4805 /* No CDX form for sign-extended load. */
4807 if (GET_CODE (mem
) == ZERO_EXTEND
)
4808 /* The load alternatives in the zero_extend* patterns. */
4809 mem
= XEXP (mem
, 0);
4813 if ((MEM_VOLATILE_P (mem
) && TARGET_BYPASS_CACHE_VOLATILE
)
4814 || TARGET_BYPASS_CACHE
)
4816 addr
= XEXP (mem
, 0);
4817 /* GP-based and R0-based references are never narrow. */
4818 if (gprel_constant_p (addr
) || r0rel_constant_p (addr
))
4820 /* %lo requires a 16-bit relocation and is never narrow. */
4821 if (GET_CODE (addr
) == LO_SUM
)
4823 ret
= split_mem_address (addr
, &rhs1
, &rhs2
);
4829 offset
= INTVAL (rhs2
);
4830 if (GET_MODE (mem
) == SImode
)
4835 if (rtx_equal_p (rhs1
, stack_pointer_rtx
)
4836 && rem
== 0 && (offset
& ~0x1f) == 0)
4839 else if (GET_MODE (mem
) == HImode
)
4844 /* ldbu.n, ldhu.n, ldw.n cases. */
4845 return (cdxreg (reg
) && cdxreg (rhs1
)
4846 && rem
== 0 && (offset
& ~0xf) == 0);
4849 if (GET_CODE (pat
) == PARALLEL
)
4855 HOST_WIDE_INT offset
, rem
= 0;
4856 rtx addr
, reg
= SET_SRC (pat
), mem
= SET_DEST (pat
);
4860 if ((MEM_VOLATILE_P (mem
) && TARGET_BYPASS_CACHE_VOLATILE
)
4861 || TARGET_BYPASS_CACHE
)
4863 addr
= XEXP (mem
, 0);
4864 /* GP-based and r0-based references are never narrow. */
4865 if (gprel_constant_p (addr
) || r0rel_constant_p (addr
))
4867 /* %lo requires a 16-bit relocation and is never narrow. */
4868 if (GET_CODE (addr
) == LO_SUM
)
4870 ret
= split_mem_address (addr
, &rhs1
, &rhs2
);
4872 offset
= INTVAL (rhs2
);
4873 if (GET_MODE (mem
) == SImode
)
4878 if (rtx_equal_p (rhs1
, stack_pointer_rtx
)
4879 && rem
== 0 && (offset
& ~0x1f) == 0)
4882 else if (reg
== const0_rtx
&& cdxreg (rhs1
)
4883 && rem
== 0 && (offset
& ~0x3f) == 0)
4886 else if (GET_MODE (mem
) == HImode
)
4893 gcc_assert (GET_MODE (mem
) == QImode
);
4895 if (reg
== const0_rtx
&& cdxreg (rhs1
)
4896 && (offset
& ~0x3f) == 0)
4900 /* stbu.n, sthu.n, stw.n cases. */
4901 return (cdxreg (reg
) && cdxreg (rhs1
)
4902 && rem
== 0 && (offset
& ~0xf) == 0);
4905 lhs
= SET_DEST (pat
);
4906 rhs1
= SET_SRC (pat
);
4907 if (CONST_INT_P (rhs1
))
4908 return (cdxreg (lhs
) && cdx_mov_immed (rhs1
));
4909 gcc_assert (REG_P (lhs
) && REG_P (rhs1
));
4913 /* Some zero_extend* alternatives are and insns. */
4914 if (GET_CODE (SET_SRC (pat
)) == ZERO_EXTEND
)
4915 return (cdxreg (SET_DEST (pat
))
4916 && cdxreg (XEXP (SET_SRC (pat
), 0)));
4917 split_alu_insn (insn
, &lhs
, &rhs1
, &rhs2
);
4918 if (CONST_INT_P (rhs2
))
4919 return (cdxreg (lhs
) && cdxreg (rhs1
) && cdx_and_immed (rhs2
));
4920 return (cdxreg (lhs
) && cdxreg (rhs2
)
4921 && (!reload_completed
|| rtx_equal_p (lhs
, rhs1
)));
4925 /* Note the two-address limitation for CDX form. */
4926 split_alu_insn (insn
, &lhs
, &rhs1
, &rhs2
);
4927 return (cdxreg (lhs
) && cdxreg (rhs2
)
4928 && (!reload_completed
|| rtx_equal_p (lhs
, rhs1
)));
4931 split_alu_insn (insn
, &lhs
, &rhs1
, &rhs2
);
4932 return (cdxreg (lhs
) && cdxreg (rhs1
) && cdxreg (rhs2
));
4936 split_alu_insn (insn
, &lhs
, &rhs1
, NULL
);
4937 return (cdxreg (lhs
) && cdxreg (rhs1
));
4941 split_alu_insn (insn
, &lhs
, &rhs1
, &rhs2
);
4942 return (cdxreg (lhs
)
4943 && ((cdxreg (rhs1
) && cdx_shift_immed (rhs2
))
4945 && (!reload_completed
|| rtx_equal_p (lhs
, rhs1
)))));
4956 /* Main function to implement the pop_operation predicate that
4957 check pop.n insn pattern integrity. The CDX pop.n patterns mostly
4958 hardcode the restored registers, so the main checking is for the
4961 pop_operation_p (rtx op
)
4964 HOST_WIDE_INT last_offset
= -1, len
= XVECLEN (op
, 0);
4965 rtx base_reg
, offset
;
4967 if (len
< 3 /* At least has a return, SP-update, and RA restore. */
4968 || GET_CODE (XVECEXP (op
, 0, 0)) != RETURN
4969 || !base_reg_adjustment_p (XVECEXP (op
, 0, 1), &base_reg
, &offset
)
4970 || !rtx_equal_p (base_reg
, stack_pointer_rtx
)
4971 || !CONST_INT_P (offset
)
4972 || (INTVAL (offset
) & 3) != 0)
4975 for (i
= len
- 1; i
> 1; i
--)
4977 rtx set
= XVECEXP (op
, 0, i
);
4978 rtx curr_base_reg
, curr_offset
;
4980 if (GET_CODE (set
) != SET
|| !MEM_P (SET_SRC (set
))
4981 || !split_mem_address (XEXP (SET_SRC (set
), 0),
4982 &curr_base_reg
, &curr_offset
)
4983 || !rtx_equal_p (base_reg
, curr_base_reg
)
4984 || !CONST_INT_P (curr_offset
))
4988 last_offset
= INTVAL (curr_offset
);
4989 if ((last_offset
& 3) != 0 || last_offset
> 60)
4995 if (INTVAL (curr_offset
) != last_offset
)
4999 if (last_offset
< 0 || last_offset
+ 4 != INTVAL (offset
))
5006 /* Masks of registers that are valid for CDX ldwm/stwm instructions.
5007 The instruction can encode subsets drawn from either R2-R13 or
5008 R14-R23 + FP + RA. */
5009 #define CDX_LDSTWM_VALID_REGS_0 0x00003ffc
5010 #define CDX_LDSTWM_VALID_REGS_1 0x90ffc000
5013 nios2_ldstwm_regset_p (unsigned int regno
, unsigned int *regset
)
5017 if (CDX_LDSTWM_VALID_REGS_0
& (1 << regno
))
5018 *regset
= CDX_LDSTWM_VALID_REGS_0
;
5019 else if (CDX_LDSTWM_VALID_REGS_1
& (1 << regno
))
5020 *regset
= CDX_LDSTWM_VALID_REGS_1
;
5026 return (*regset
& (1 << regno
)) != 0;
5029 /* Main function to implement ldwm_operation/stwm_operation
5030 predicates that check ldwm/stwm insn pattern integrity. */
5032 ldstwm_operation_p (rtx op
, bool load_p
)
5034 int start
, i
, end
= XVECLEN (op
, 0) - 1, last_regno
= -1;
5035 unsigned int regset
= 0;
5036 rtx base_reg
, offset
;
5037 rtx first_elt
= XVECEXP (op
, 0, 0);
5039 bool wb_p
= base_reg_adjustment_p (first_elt
, &base_reg
, &offset
);
5040 if (GET_CODE (XVECEXP (op
, 0, end
)) == RETURN
)
5042 start
= wb_p
? 1 : 0;
5043 for (i
= start
; i
<= end
; i
++)
5046 rtx reg
, mem
, elt
= XVECEXP (op
, 0, i
);
5047 /* Return early if not a SET at all. */
5048 if (GET_CODE (elt
) != SET
)
5050 reg
= load_p
? SET_DEST (elt
) : SET_SRC (elt
);
5051 mem
= load_p
? SET_SRC (elt
) : SET_DEST (elt
);
5052 if (!REG_P (reg
) || !MEM_P (mem
))
5054 regno
= REGNO (reg
);
5055 if (!nios2_ldstwm_regset_p (regno
, ®set
))
5057 /* If no writeback to determine direction, use offset of first MEM. */
5059 inc_p
= INTVAL (offset
) > 0;
5060 else if (i
== start
)
5062 rtx first_base
, first_offset
;
5063 if (!split_mem_address (XEXP (mem
, 0),
5064 &first_base
, &first_offset
))
5066 if (!REG_P (first_base
) || !CONST_INT_P (first_offset
))
5068 base_reg
= first_base
;
5069 inc_p
= INTVAL (first_offset
) >= 0;
5071 /* Ensure that the base register is not loaded into. */
5072 if (load_p
&& regno
== (int) REGNO (base_reg
))
5074 /* Check for register order inc/dec integrity. */
5075 if (last_regno
>= 0)
5077 if (inc_p
&& last_regno
>= regno
)
5079 if (!inc_p
&& last_regno
<= regno
)
5087 /* Helper for nios2_ldst_parallel, for generating a parallel vector
5090 gen_ldst (bool load_p
, int regno
, rtx base_mem
, int offset
)
5092 rtx reg
= gen_rtx_REG (SImode
, regno
);
5093 rtx mem
= adjust_address_nv (base_mem
, SImode
, offset
);
5094 return gen_rtx_SET (load_p
? reg
: mem
,
5095 load_p
? mem
: reg
);
5098 /* A general routine for creating the body RTL pattern of
5099 ldwm/stwm/push.n/pop.n insns.
5100 LOAD_P: true/false for load/store direction.
5101 REG_INC_P: whether registers are incrementing/decrementing in the
5102 *RTL vector* (not necessarily the order defined in the ISA specification).
5103 OFFSET_INC_P: Same as REG_INC_P, but for the memory offset order.
5104 BASE_MEM: starting MEM.
5105 BASE_UPDATE: amount to update base register; zero means no writeback.
5106 REGMASK: register mask to load/store.
5107 RET_P: true if to tag a (return) element at the end.
5109 Note that this routine does not do any checking. It's the job of the
5110 caller to do the right thing, and the insn patterns to do the
5113 nios2_ldst_parallel (bool load_p
, bool reg_inc_p
, bool offset_inc_p
,
5114 rtx base_mem
, int base_update
,
5115 unsigned HOST_WIDE_INT regmask
, bool ret_p
)
5118 int regno
, b
= 0, i
= 0, n
= 0, len
= popcount_hwi (regmask
);
5119 if (ret_p
) len
++, i
++, b
++;
5120 if (base_update
!= 0) len
++, i
++;
5121 p
= rtvec_alloc (len
);
5122 for (regno
= (reg_inc_p
? 0 : 31);
5123 regno
!= (reg_inc_p
? 32 : -1);
5124 regno
+= (reg_inc_p
? 1 : -1))
5125 if ((regmask
& (1 << regno
)) != 0)
5127 int offset
= (offset_inc_p
? 4 : -4) * n
++;
5128 RTVEC_ELT (p
, i
++) = gen_ldst (load_p
, regno
, base_mem
, offset
);
5131 RTVEC_ELT (p
, 0) = ret_rtx
;
5132 if (base_update
!= 0)
5135 if (!split_mem_address (XEXP (base_mem
, 0), ®
, &offset
))
5138 gen_rtx_SET (reg
, plus_constant (Pmode
, reg
, base_update
));
5140 return gen_rtx_PARALLEL (VOIDmode
, p
);
5143 /* CDX ldwm/stwm peephole optimization pattern related routines. */
5145 /* Data structure and sorting function for ldwm/stwm peephole optimizers. */
5146 struct ldstwm_operand
5148 int offset
; /* Offset from base register. */
5149 rtx reg
; /* Register to store at this offset. */
5150 rtx mem
; /* Original mem. */
5151 bool bad
; /* True if this load/store can't be combined. */
5152 bool rewrite
; /* True if we should rewrite using scratch. */
5156 compare_ldstwm_operands (const void *arg1
, const void *arg2
)
5158 const struct ldstwm_operand
*op1
= (const struct ldstwm_operand
*) arg1
;
5159 const struct ldstwm_operand
*op2
= (const struct ldstwm_operand
*) arg2
;
5161 return op2
->bad
? 0 : 1;
5165 return op1
->offset
- op2
->offset
;
5168 /* Helper function: return true if a load/store using REGNO with address
5169 BASEREG and offset OFFSET meets the constraints for a 2-byte CDX ldw.n,
5170 stw.n, ldwsp.n, or stwsp.n instruction. */
5172 can_use_cdx_ldstw (int regno
, int basereg
, int offset
)
5174 if (CDX_REG_P (regno
) && CDX_REG_P (basereg
)
5175 && (offset
& 0x3) == 0 && offset
>= 0 && offset
< 0x40)
5177 else if (basereg
== SP_REGNO
5178 && offset
>= 0 && offset
< 0x80 && (offset
& 0x3) == 0)
5183 /* This function is called from peephole2 optimizers to try to merge
5184 a series of individual loads and stores into a ldwm or stwm. It
5185 can also rewrite addresses inside the individual loads and stores
5186 using a common base register using a scratch register and smaller
5187 offsets if that allows them to use CDX ldw.n or stw.n instructions
5188 instead of 4-byte loads or stores.
5189 N is the number of insns we are trying to merge. SCRATCH is non-null
5190 if there is a scratch register available. The OPERANDS array contains
5191 alternating REG (even) and MEM (odd) operands. */
5193 gen_ldstwm_peep (bool load_p
, int n
, rtx scratch
, rtx
*operands
)
5195 /* CDX ldwm/stwm instructions allow a maximum of 12 registers to be
5197 #define MAX_LDSTWM_OPS 12
5198 struct ldstwm_operand sort
[MAX_LDSTWM_OPS
];
5201 int i
, m
, lastoffset
, lastreg
;
5202 unsigned int regmask
= 0, usemask
= 0, regset
;
5207 if (!TARGET_HAS_CDX
)
5209 if (n
< 2 || n
> MAX_LDSTWM_OPS
)
5212 /* Check all the operands for validity and initialize the sort array.
5213 The places where we return false here are all situations that aren't
5214 expected to ever happen -- invalid patterns, invalid registers, etc. */
5215 for (i
= 0; i
< n
; i
++)
5218 rtx reg
= operands
[i
];
5219 rtx mem
= operands
[i
+ n
];
5223 if (!REG_P (reg
) || !MEM_P (mem
))
5226 regno
= REGNO (reg
);
5229 if (load_p
&& (regmask
& (1 << regno
)) != 0)
5231 regmask
|= 1 << regno
;
5233 if (!split_mem_address (XEXP (mem
, 0), &base
, &offset
))
5236 o
= INTVAL (offset
);
5240 else if (r
!= basereg
)
5245 sort
[i
].rewrite
= false;
5251 /* If we are doing a series of register loads, we can't safely reorder
5252 them if any of the regs used in addr expressions are also being set. */
5253 if (load_p
&& (regmask
& usemask
))
5256 /* Sort the array by increasing mem offset order, then check that
5257 offsets are valid and register order matches mem order. At the
5258 end of this loop, m is the number of loads/stores we will try to
5259 combine; the rest are leftovers. */
5260 qsort (sort
, n
, sizeof (struct ldstwm_operand
), compare_ldstwm_operands
);
5262 baseoffset
= sort
[0].offset
;
5263 needscratch
= baseoffset
!= 0;
5264 if (needscratch
&& !scratch
)
5267 lastreg
= regmask
= regset
= 0;
5268 lastoffset
= baseoffset
;
5269 for (m
= 0; m
< n
&& !sort
[m
].bad
; m
++)
5271 int thisreg
= REGNO (sort
[m
].reg
);
5272 if (sort
[m
].offset
!= lastoffset
5273 || (m
> 0 && lastreg
>= thisreg
)
5274 || !nios2_ldstwm_regset_p (thisreg
, ®set
))
5278 regmask
|= (1 << thisreg
);
5281 /* For loads, make sure we are not overwriting the scratch reg.
5282 The peephole2 pattern isn't supposed to match unless the register is
5283 unused all the way through, so this isn't supposed to happen anyway. */
5286 && ((1 << REGNO (scratch
)) & regmask
) != 0)
5288 newbasereg
= needscratch
? (int) REGNO (scratch
) : basereg
;
5290 /* We may be able to combine only the first m of the n total loads/stores
5291 into a single instruction. If m < 2, there's no point in emitting
5292 a ldwm/stwm at all, but we might be able to do further optimizations
5293 if we have a scratch. We will count the instruction lengths of the
5294 old and new patterns and store the savings in nbytes. */
5303 nbytes
= -4; /* Size of ldwm/stwm. */
5306 int bo
= baseoffset
> 0 ? baseoffset
: -baseoffset
;
5307 if (CDX_REG_P (newbasereg
)
5308 && CDX_REG_P (basereg
)
5309 && bo
<= 128 && bo
> 0 && (bo
& (bo
- 1)) == 0)
5310 nbytes
-= 2; /* Size of addi.n/subi.n. */
5312 nbytes
-= 4; /* Size of non-CDX addi. */
5315 /* Count the size of the input load/store instructions being replaced. */
5316 for (i
= 0; i
< m
; i
++)
5317 if (can_use_cdx_ldstw (REGNO (sort
[i
].reg
), basereg
, sort
[i
].offset
))
5322 /* We may also be able to save a bit if we can rewrite non-CDX
5323 load/stores that can't be combined into the ldwm/stwm into CDX
5324 load/stores using the scratch reg. For example, this might happen
5325 if baseoffset is large, by bringing in the offsets in the load/store
5326 instructions within the range that fits in the CDX instruction. */
5327 if (needscratch
&& CDX_REG_P (newbasereg
))
5328 for (i
= m
; i
< n
&& !sort
[i
].bad
; i
++)
5329 if (!can_use_cdx_ldstw (REGNO (sort
[i
].reg
), basereg
, sort
[i
].offset
)
5330 && can_use_cdx_ldstw (REGNO (sort
[i
].reg
), newbasereg
,
5331 sort
[i
].offset
- baseoffset
))
5333 sort
[i
].rewrite
= true;
5337 /* Are we good to go? */
5341 /* Emit the scratch load. */
5343 emit_insn (gen_rtx_SET (scratch
, XEXP (sort
[0].mem
, 0)));
5345 /* Emit the ldwm/stwm insn. */
5348 rtvec p
= rtvec_alloc (m
);
5349 for (i
= 0; i
< m
; i
++)
5351 int offset
= sort
[i
].offset
;
5352 rtx mem
, reg
= sort
[i
].reg
;
5353 rtx base_reg
= gen_rtx_REG (Pmode
, newbasereg
);
5355 offset
-= baseoffset
;
5356 mem
= gen_rtx_MEM (SImode
, plus_constant (Pmode
, base_reg
, offset
));
5358 RTVEC_ELT (p
, i
) = gen_rtx_SET (reg
, mem
);
5360 RTVEC_ELT (p
, i
) = gen_rtx_SET (mem
, reg
);
5362 emit_insn (gen_rtx_PARALLEL (VOIDmode
, p
));
5365 /* Emit any leftover load/stores as individual instructions, doing
5366 the previously-noted rewrites to use the scratch reg. */
5367 for (i
= m
; i
< n
; i
++)
5369 rtx reg
= sort
[i
].reg
;
5370 rtx mem
= sort
[i
].mem
;
5371 if (sort
[i
].rewrite
)
5373 int offset
= sort
[i
].offset
- baseoffset
;
5374 mem
= gen_rtx_MEM (SImode
, plus_constant (Pmode
, scratch
, offset
));
5377 emit_move_insn (reg
, mem
);
5379 emit_move_insn (mem
, reg
);
5384 /* Implement TARGET_MACHINE_DEPENDENT_REORG:
5385 We use this hook when emitting CDX code to enforce the 4-byte
5386 alignment requirement for labels that are used as the targets of
5387 jmpi instructions. CDX code can otherwise contain a mix of 16-bit
5388 and 32-bit instructions aligned on any 16-bit boundary, but functions
5389 and jmpi labels have to be 32-bit aligned because of the way the address
5390 is encoded in the instruction. */
5392 static unsigned char *label_align
;
5393 static int min_labelno
, max_labelno
;
5398 bool changed
= true;
5401 if (!TARGET_HAS_CDX
)
5404 /* Initialize the data structures. */
5407 max_labelno
= max_label_num ();
5408 min_labelno
= get_first_label_num ();
5409 label_align
= XCNEWVEC (unsigned char, max_labelno
- min_labelno
+ 1);
5411 /* Iterate on inserting alignment and adjusting branch lengths until
5416 shorten_branches (get_insns ());
5418 for (insn
= get_insns (); insn
!= 0; insn
= NEXT_INSN (insn
))
5419 if (JUMP_P (insn
) && insn_variable_length_p (insn
))
5421 rtx label
= JUMP_LABEL (insn
);
5422 /* We use the current fact that all cases of 'jmpi'
5423 doing the actual branch in the machine description
5424 has a computed length of 6 or 8. Length 4 and below
5425 are all PC-relative 'br' branches without the jump-align
5427 if (label
&& LABEL_P (label
) && get_attr_length (insn
) > 4)
5429 int index
= CODE_LABEL_NUMBER (label
) - min_labelno
;
5430 if (label_align
[index
] != 2)
5432 label_align
[index
] = 2;
5440 /* Implement LABEL_ALIGN, using the information gathered in nios2_reorg. */
5442 nios2_label_align (rtx label
)
5444 int n
= CODE_LABEL_NUMBER (label
);
5446 if (label_align
&& n
>= min_labelno
&& n
<= max_labelno
)
5447 return MAX (label_align
[n
- min_labelno
], align_labels
.levels
[0].log
);
5448 return align_labels
.levels
[0].log
;
5451 /* Implement ADJUST_REG_ALLOC_ORDER. We use the default ordering
5452 for R1 and non-CDX R2 code; for CDX we tweak thing to prefer
5453 the registers that can be used as operands to instructions that
5454 have 3-bit register fields. */
5456 nios2_adjust_reg_alloc_order (void)
5458 const int cdx_reg_alloc_order
[] =
5460 /* Call-clobbered GPRs within CDX 3-bit encoded range. */
5462 /* Call-saved GPRs within CDX 3-bit encoded range. */
5464 /* Other call-clobbered GPRs. */
5465 8, 9, 10, 11, 12, 13, 14, 15,
5466 /* Other call-saved GPRs. RA placed first since it is always saved. */
5467 31, 18, 19, 20, 21, 22, 23, 28,
5468 /* Fixed GPRs, not used by the register allocator. */
5469 0, 1, 24, 25, 26, 27, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39
5473 memcpy (reg_alloc_order
, cdx_reg_alloc_order
,
5474 sizeof (int) * FIRST_PSEUDO_REGISTER
);
5478 /* Initialize the GCC target structure. */
5479 #undef TARGET_ASM_FUNCTION_PROLOGUE
5480 #define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
5482 #undef TARGET_IN_SMALL_DATA_P
5483 #define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
5485 #undef TARGET_SECTION_TYPE_FLAGS
5486 #define TARGET_SECTION_TYPE_FLAGS nios2_section_type_flags
5488 #undef TARGET_INIT_BUILTINS
5489 #define TARGET_INIT_BUILTINS nios2_init_builtins
5490 #undef TARGET_EXPAND_BUILTIN
5491 #define TARGET_EXPAND_BUILTIN nios2_expand_builtin
5492 #undef TARGET_BUILTIN_DECL
5493 #define TARGET_BUILTIN_DECL nios2_builtin_decl
5495 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5496 #define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
5498 #undef TARGET_CAN_ELIMINATE
5499 #define TARGET_CAN_ELIMINATE nios2_can_eliminate
5501 #undef TARGET_FUNCTION_ARG
5502 #define TARGET_FUNCTION_ARG nios2_function_arg
5504 #undef TARGET_FUNCTION_ARG_ADVANCE
5505 #define TARGET_FUNCTION_ARG_ADVANCE nios2_function_arg_advance
5507 #undef TARGET_FUNCTION_ARG_PADDING
5508 #define TARGET_FUNCTION_ARG_PADDING nios2_function_arg_padding
5510 #undef TARGET_ARG_PARTIAL_BYTES
5511 #define TARGET_ARG_PARTIAL_BYTES nios2_arg_partial_bytes
5513 #undef TARGET_TRAMPOLINE_INIT
5514 #define TARGET_TRAMPOLINE_INIT nios2_trampoline_init
5516 #undef TARGET_FUNCTION_VALUE
5517 #define TARGET_FUNCTION_VALUE nios2_function_value
5519 #undef TARGET_LIBCALL_VALUE
5520 #define TARGET_LIBCALL_VALUE nios2_libcall_value
5522 #undef TARGET_FUNCTION_VALUE_REGNO_P
5523 #define TARGET_FUNCTION_VALUE_REGNO_P nios2_function_value_regno_p
5525 #undef TARGET_RETURN_IN_MEMORY
5526 #define TARGET_RETURN_IN_MEMORY nios2_return_in_memory
5528 #undef TARGET_PROMOTE_PROTOTYPES
5529 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
5531 #undef TARGET_SETUP_INCOMING_VARARGS
5532 #define TARGET_SETUP_INCOMING_VARARGS nios2_setup_incoming_varargs
5534 #undef TARGET_MUST_PASS_IN_STACK
5535 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
5537 #undef TARGET_LEGITIMATE_CONSTANT_P
5538 #define TARGET_LEGITIMATE_CONSTANT_P nios2_legitimate_constant_p
5540 #undef TARGET_LEGITIMIZE_ADDRESS
5541 #define TARGET_LEGITIMIZE_ADDRESS nios2_legitimize_address
5543 #undef TARGET_DELEGITIMIZE_ADDRESS
5544 #define TARGET_DELEGITIMIZE_ADDRESS nios2_delegitimize_address
5546 #undef TARGET_LEGITIMATE_ADDRESS_P
5547 #define TARGET_LEGITIMATE_ADDRESS_P nios2_legitimate_address_p
5549 #undef TARGET_PREFERRED_RELOAD_CLASS
5550 #define TARGET_PREFERRED_RELOAD_CLASS nios2_preferred_reload_class
5552 #undef TARGET_RTX_COSTS
5553 #define TARGET_RTX_COSTS nios2_rtx_costs
5555 #undef TARGET_ADDRESS_COST
5556 #define TARGET_ADDRESS_COST nios2_address_cost
5558 #undef TARGET_HAVE_TLS
5559 #define TARGET_HAVE_TLS TARGET_LINUX_ABI
5561 #undef TARGET_CANNOT_FORCE_CONST_MEM
5562 #define TARGET_CANNOT_FORCE_CONST_MEM nios2_cannot_force_const_mem
5564 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
5565 #define TARGET_ASM_OUTPUT_DWARF_DTPREL nios2_output_dwarf_dtprel
5567 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
5568 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P nios2_print_operand_punct_valid_p
5570 #undef TARGET_PRINT_OPERAND
5571 #define TARGET_PRINT_OPERAND nios2_print_operand
5573 #undef TARGET_PRINT_OPERAND_ADDRESS
5574 #define TARGET_PRINT_OPERAND_ADDRESS nios2_print_operand_address
5576 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
5577 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA nios2_output_addr_const_extra
5579 #undef TARGET_ASM_FILE_END
5580 #define TARGET_ASM_FILE_END nios2_asm_file_end
5582 #undef TARGET_OPTION_OVERRIDE
5583 #define TARGET_OPTION_OVERRIDE nios2_option_override
5585 #undef TARGET_OPTION_SAVE
5586 #define TARGET_OPTION_SAVE nios2_option_save
5588 #undef TARGET_OPTION_RESTORE
5589 #define TARGET_OPTION_RESTORE nios2_option_restore
5591 #undef TARGET_CAN_INLINE_P
5592 #define TARGET_CAN_INLINE_P nios2_can_inline_p
5594 #undef TARGET_SET_CURRENT_FUNCTION
5595 #define TARGET_SET_CURRENT_FUNCTION nios2_set_current_function
5597 #undef TARGET_OPTION_VALID_ATTRIBUTE_P
5598 #define TARGET_OPTION_VALID_ATTRIBUTE_P nios2_valid_target_attribute_p
5600 #undef TARGET_OPTION_PRAGMA_PARSE
5601 #define TARGET_OPTION_PRAGMA_PARSE nios2_pragma_target_parse
5603 #undef TARGET_MERGE_DECL_ATTRIBUTES
5604 #define TARGET_MERGE_DECL_ATTRIBUTES nios2_merge_decl_attributes
5606 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5607 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
5608 hook_bool_const_tree_hwi_hwi_const_tree_true
5610 #undef TARGET_ASM_OUTPUT_MI_THUNK
5611 #define TARGET_ASM_OUTPUT_MI_THUNK nios2_asm_output_mi_thunk
5613 #undef TARGET_MACHINE_DEPENDENT_REORG
5614 #define TARGET_MACHINE_DEPENDENT_REORG nios2_reorg
5616 #undef TARGET_CONSTANT_ALIGNMENT
5617 #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
5619 #undef TARGET_HAVE_SPECULATION_SAFE_VALUE
5620 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
5622 struct gcc_target targetm
= TARGET_INITIALIZER
;
5624 #include "gt-nios2.h"