1 /* Subroutines used for code generation of Andes NDS32 cpu for GNU compiler
2 Copyright (C) 2012-2014 Free Software Foundation, Inc.
3 Contributed by Andes Technology Corporation.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
25 #include "coretypes.h"
28 #include "stor-layout.h"
33 #include "hard-reg-set.h"
34 #include "insn-config.h" /* Required by recog.h. */
35 #include "conditions.h"
37 #include "insn-attr.h" /* For DFA state_t. */
38 #include "insn-codes.h" /* For CODE_FOR_xxx. */
39 #include "reload.h" /* For push_reload(). */
44 #include "diagnostic-core.h"
47 #include "tm-constrs.h"
48 #include "optabs.h" /* For GEN_FCN. */
50 #include "target-def.h"
51 #include "langhooks.h" /* For add_builtin_function(). */
54 /* ------------------------------------------------------------------------ */
56 /* This file is divided into five parts:
58 PART 1: Auxiliary static variable definitions and
59 target hook static variable definitions.
61 PART 2: Auxiliary static function definitions.
63 PART 3: Implement target hook stuff definitions.
65 PART 4: Implemet extern function definitions,
66 the prototype is in nds32-protos.h.
68 PART 5: Initialize target hook structure and definitions. */
70 /* ------------------------------------------------------------------------ */
72 /* PART 1: Auxiliary static variable definitions and
73 target hook static variable definitions. */
75 /* Refer to nds32.h, there are maximum 73 isr vectors in nds32 architecture.
76 0 for reset handler with __attribute__((reset())),
77 1-8 for exception handler with __attribute__((exception(1,...,8))),
78 and 9-72 for interrupt handler with __attribute__((interrupt(0,...,63))).
79 We use an array to record essential information for each vector. */
80 static struct nds32_isr_info nds32_isr_vectors
[NDS32_N_ISR_VECTORS
];
82 /* Define intrinsic register names.
83 Please refer to nds32_intrinsic.h file, the index is corresponding to
84 'enum nds32_intrinsic_registers' data type values.
85 NOTE that the base value starting from 1024. */
86 static const char * const nds32_intrinsic_register_names
[] =
88 "$PSW", "$IPSW", "$ITYPE", "$IPC"
91 /* Defining target-specific uses of __attribute__. */
92 static const struct attribute_spec nds32_attribute_table
[] =
94 /* Syntax: { name, min_len, max_len, decl_required, type_required,
95 function_type_required, handler, affects_type_identity } */
97 /* The interrupt vid: [0-63]+ (actual vector number starts from 9 to 72). */
98 { "interrupt", 1, 64, false, false, false, NULL
, false },
99 /* The exception vid: [1-8]+ (actual vector number starts from 1 to 8). */
100 { "exception", 1, 8, false, false, false, NULL
, false },
101 /* Argument is user's interrupt numbers. The vector number is always 0. */
102 { "reset", 1, 1, false, false, false, NULL
, false },
104 /* The attributes describing isr nested type. */
105 { "nested", 0, 0, false, false, false, NULL
, false },
106 { "not_nested", 0, 0, false, false, false, NULL
, false },
107 { "nested_ready", 0, 0, false, false, false, NULL
, false },
109 /* The attributes describing isr register save scheme. */
110 { "save_all", 0, 0, false, false, false, NULL
, false },
111 { "partial_save", 0, 0, false, false, false, NULL
, false },
113 /* The attributes used by reset attribute. */
114 { "nmi", 1, 1, false, false, false, NULL
, false },
115 { "warm", 1, 1, false, false, false, NULL
, false },
117 /* The attribute telling no prologue/epilogue. */
118 { "naked", 0, 0, false, false, false, NULL
, false },
120 /* The last attribute spec is set to be NULL. */
121 { NULL
, 0, 0, false, false, false, NULL
, false }
125 /* ------------------------------------------------------------------------ */
127 /* PART 2: Auxiliary static function definitions. */
129 /* Function to save and restore machine-specific function data. */
130 static struct machine_function
*
131 nds32_init_machine_status (void)
133 struct machine_function
*machine
;
134 machine
= ggc_cleared_alloc
<machine_function
> ();
136 /* Initially assume this function needs prologue/epilogue. */
137 machine
->naked_p
= 0;
139 /* Initially assume this function does NOT use fp_as_gp optimization. */
140 machine
->fp_as_gp_p
= 0;
145 /* Function to compute stack frame size and
146 store into cfun->machine structure. */
148 nds32_compute_stack_frame (void)
153 /* Because nds32_compute_stack_frame() will be called from different place,
154 everytime we enter this function, we have to assume this function
155 needs prologue/epilogue. */
156 cfun
->machine
->naked_p
= 0;
158 /* Get variadic arguments size to prepare pretend arguments and
159 push them into stack at prologue.
160 Currently, we do not push variadic arguments by ourself.
161 We have GCC handle all the works.
162 The caller will push all corresponding nameless arguments into stack,
163 and the callee is able to retrieve them without problems.
164 These variables are still preserved in case one day
165 we would like caller passing arguments with registers. */
166 cfun
->machine
->va_args_size
= 0;
167 cfun
->machine
->va_args_first_regno
= SP_REGNUM
;
168 cfun
->machine
->va_args_last_regno
= SP_REGNUM
;
170 /* Get local variables, incoming variables, and temporary variables size.
171 Note that we need to make sure it is 8-byte alignment because
172 there may be no padding bytes if we are using LRA. */
173 cfun
->machine
->local_size
= NDS32_ROUND_UP_DOUBLE_WORD (get_frame_size ());
175 /* Get outgoing arguments size. */
176 cfun
->machine
->out_args_size
= crtl
->outgoing_args_size
;
178 /* If $fp value is required to be saved on stack, it needs 4 bytes space.
179 Check whether $fp is ever live. */
180 cfun
->machine
->fp_size
= (df_regs_ever_live_p (FP_REGNUM
)) ? 4 : 0;
182 /* If $gp value is required to be saved on stack, it needs 4 bytes space.
183 Check whether we are using PIC code genration. */
184 cfun
->machine
->gp_size
= (flag_pic
) ? 4 : 0;
186 /* If $lp value is required to be saved on stack, it needs 4 bytes space.
187 Check whether $lp is ever live. */
188 cfun
->machine
->lp_size
= (df_regs_ever_live_p (LP_REGNUM
)) ? 4 : 0;
190 /* Initially there is no padding bytes. */
191 cfun
->machine
->callee_saved_area_padding_bytes
= 0;
193 /* Calculate the bytes of saving callee-saved registers on stack. */
194 cfun
->machine
->callee_saved_regs_size
= 0;
195 cfun
->machine
->callee_saved_regs_first_regno
= SP_REGNUM
;
196 cfun
->machine
->callee_saved_regs_last_regno
= SP_REGNUM
;
197 /* Currently, there is no need to check $r28~$r31
198 because we will save them in another way. */
199 for (r
= 0; r
< 28; r
++)
201 if (NDS32_REQUIRED_CALLEE_SAVED_P (r
))
203 /* Mark the first required callee-saved register
204 (only need to set it once).
205 If first regno == SP_REGNUM, we can tell that
206 it is the first time to be here. */
207 if (cfun
->machine
->callee_saved_regs_first_regno
== SP_REGNUM
)
208 cfun
->machine
->callee_saved_regs_first_regno
= r
;
209 /* Mark the last required callee-saved register. */
210 cfun
->machine
->callee_saved_regs_last_regno
= r
;
214 /* Check if this function can omit prologue/epilogue code fragment.
215 If there is 'naked' attribute in this function,
216 we can set 'naked_p' flag to indicate that
217 we do not have to generate prologue/epilogue.
218 Or, if all the following conditions succeed,
219 we can set this function 'naked_p' as well:
220 condition 1: first_regno == last_regno == SP_REGNUM,
221 which means we do not have to save
222 any callee-saved registers.
223 condition 2: Both $lp and $fp are NOT live in this function,
224 which means we do not need to save them.
225 condition 3: There is no local_size, which means
226 we do not need to adjust $sp. */
227 if (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl
))
228 || (cfun
->machine
->callee_saved_regs_first_regno
== SP_REGNUM
229 && cfun
->machine
->callee_saved_regs_last_regno
== SP_REGNUM
230 && !df_regs_ever_live_p (FP_REGNUM
)
231 && !df_regs_ever_live_p (LP_REGNUM
)
232 && cfun
->machine
->local_size
== 0))
234 /* Set this function 'naked_p' and
235 other functions can check this flag. */
236 cfun
->machine
->naked_p
= 1;
238 /* No need to save $fp, $gp, and $lp.
239 We should set these value to be zero
240 so that nds32_initial_elimination_offset() can work properly. */
241 cfun
->machine
->fp_size
= 0;
242 cfun
->machine
->gp_size
= 0;
243 cfun
->machine
->lp_size
= 0;
245 /* If stack usage computation is required,
246 we need to provide the static stack size. */
247 if (flag_stack_usage_info
)
248 current_function_static_stack_size
= 0;
250 /* No need to do following adjustment, return immediately. */
254 /* Adjustment for v3push instructions:
255 If we are using v3push (push25/pop25) instructions,
256 we need to make sure Rb is $r6 and Re is
257 located on $r6, $r8, $r10, or $r14.
258 Some results above will be discarded and recomputed.
259 Note that it is only available under V3/V3M ISA. */
263 cfun->machine->fp_size
264 cfun->machine->gp_size
265 cfun->machine->lp_size
266 cfun->machine->callee_saved_regs_first_regno
267 cfun->machine->callee_saved_regs_last_regno */
269 /* For v3push instructions, $fp, $gp, and $lp are always saved. */
270 cfun
->machine
->fp_size
= 4;
271 cfun
->machine
->gp_size
= 4;
272 cfun
->machine
->lp_size
= 4;
274 /* Remember to set Rb = $r6. */
275 cfun
->machine
->callee_saved_regs_first_regno
= 6;
277 if (cfun
->machine
->callee_saved_regs_last_regno
<= 6)
280 cfun
->machine
->callee_saved_regs_last_regno
= 6;
282 else if (cfun
->machine
->callee_saved_regs_last_regno
<= 8)
285 cfun
->machine
->callee_saved_regs_last_regno
= 8;
287 else if (cfun
->machine
->callee_saved_regs_last_regno
<= 10)
290 cfun
->machine
->callee_saved_regs_last_regno
= 10;
292 else if (cfun
->machine
->callee_saved_regs_last_regno
<= 14)
295 cfun
->machine
->callee_saved_regs_last_regno
= 14;
297 else if (cfun
->machine
->callee_saved_regs_last_regno
== SP_REGNUM
)
299 /* If last_regno is SP_REGNUM, which means
300 it is never changed, so set it to Re = $r6. */
301 cfun
->machine
->callee_saved_regs_last_regno
= 6;
305 /* The program flow should not go here. */
310 /* We have correctly set callee_saved_regs_first_regno
311 and callee_saved_regs_last_regno.
312 Initially, the callee_saved_regs_size is supposed to be 0.
313 As long as callee_saved_regs_last_regno is not SP_REGNUM,
314 we can update callee_saved_regs_size with new size. */
315 if (cfun
->machine
->callee_saved_regs_last_regno
!= SP_REGNUM
)
317 /* Compute pushed size of callee-saved registers. */
318 cfun
->machine
->callee_saved_regs_size
319 = 4 * (cfun
->machine
->callee_saved_regs_last_regno
320 - cfun
->machine
->callee_saved_regs_first_regno
324 /* Important: We need to make sure that
325 (va_args_size + fp_size + gp_size
326 + lp_size + callee_saved_regs_size)
328 If it is not, calculate the padding bytes. */
329 block_size
= cfun
->machine
->va_args_size
330 + cfun
->machine
->fp_size
331 + cfun
->machine
->gp_size
332 + cfun
->machine
->lp_size
333 + cfun
->machine
->callee_saved_regs_size
;
334 if (!NDS32_DOUBLE_WORD_ALIGN_P (block_size
))
336 cfun
->machine
->callee_saved_area_padding_bytes
337 = NDS32_ROUND_UP_DOUBLE_WORD (block_size
) - block_size
;
340 /* If stack usage computation is required,
341 we need to provide the static stack size. */
342 if (flag_stack_usage_info
)
344 current_function_static_stack_size
345 = NDS32_ROUND_UP_DOUBLE_WORD (block_size
)
346 + cfun
->machine
->local_size
347 + cfun
->machine
->out_args_size
;
351 /* Function to create a parallel rtx pattern
352 which presents stack push multiple behavior.
353 The overall concept are:
354 "push registers to memory",
355 "adjust stack pointer". */
357 nds32_gen_stack_push_multiple (rtx Rb
, rtx Re
,
358 rtx En4 ATTRIBUTE_UNUSED
)
372 /* We need to provide a customized rtx which contains
373 necessary information for data analysis,
374 so we create a parallel rtx like this:
375 (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
377 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
380 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
382 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
384 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
386 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
388 (set (reg:SI SP_REGNUM)
389 (plus (reg:SI SP_REGNUM) (const_int -32)))]) */
391 /* Calculate the number of registers that will be pushed. */
393 if (cfun
->machine
->fp_size
)
395 if (cfun
->machine
->gp_size
)
397 if (cfun
->machine
->lp_size
)
399 /* Note that Rb and Re may be SP_REGNUM. DO NOT count it in. */
400 if (REGNO (Rb
) == SP_REGNUM
&& REGNO (Re
) == SP_REGNUM
)
401 num_use_regs
= extra_count
;
403 num_use_regs
= REGNO (Re
) - REGNO (Rb
) + 1 + extra_count
;
405 /* In addition to used registers,
406 we need one more space for (set sp sp-x) rtx. */
407 parallel_insn
= gen_rtx_PARALLEL (VOIDmode
,
408 rtvec_alloc (num_use_regs
+ 1));
411 /* Initialize offset and start to create push behavior. */
412 offset
= -(num_use_regs
* 4);
414 /* Create (set mem regX) from Rb, Rb+1 up to Re. */
415 for (regno
= REGNO (Rb
); regno
<= (int) REGNO (Re
); regno
++)
417 /* Rb and Re may be SP_REGNUM.
418 We need to break this loop immediately. */
419 if (regno
== SP_REGNUM
)
422 reg
= gen_rtx_REG (SImode
, regno
);
423 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
426 push_rtx
= gen_rtx_SET (VOIDmode
, mem
, reg
);
427 XVECEXP (parallel_insn
, 0, par_index
) = push_rtx
;
428 RTX_FRAME_RELATED_P (push_rtx
) = 1;
433 /* Create (set mem fp), (set mem gp), and (set mem lp) if necessary. */
434 if (cfun
->machine
->fp_size
)
436 reg
= gen_rtx_REG (SImode
, FP_REGNUM
);
437 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
440 push_rtx
= gen_rtx_SET (VOIDmode
, mem
, reg
);
441 XVECEXP (parallel_insn
, 0, par_index
) = push_rtx
;
442 RTX_FRAME_RELATED_P (push_rtx
) = 1;
446 if (cfun
->machine
->gp_size
)
448 reg
= gen_rtx_REG (SImode
, GP_REGNUM
);
449 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
452 push_rtx
= gen_rtx_SET (VOIDmode
, mem
, reg
);
453 XVECEXP (parallel_insn
, 0, par_index
) = push_rtx
;
454 RTX_FRAME_RELATED_P (push_rtx
) = 1;
458 if (cfun
->machine
->lp_size
)
460 reg
= gen_rtx_REG (SImode
, LP_REGNUM
);
461 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
464 push_rtx
= gen_rtx_SET (VOIDmode
, mem
, reg
);
465 XVECEXP (parallel_insn
, 0, par_index
) = push_rtx
;
466 RTX_FRAME_RELATED_P (push_rtx
) = 1;
471 /* Create (set sp sp-x). */
473 /* We need to re-calculate the offset value again for adjustment. */
474 offset
= -(num_use_regs
* 4);
476 = gen_rtx_SET (VOIDmode
,
478 plus_constant (Pmode
, stack_pointer_rtx
, offset
));
479 XVECEXP (parallel_insn
, 0, par_index
) = adjust_sp_rtx
;
480 RTX_FRAME_RELATED_P (adjust_sp_rtx
) = 1;
482 return parallel_insn
;
485 /* Function to create a parallel rtx pattern
486 which presents stack pop multiple behavior.
487 The overall concept are:
488 "pop registers from memory",
489 "adjust stack pointer". */
491 nds32_gen_stack_pop_multiple (rtx Rb
, rtx Re
,
492 rtx En4 ATTRIBUTE_UNUSED
)
506 /* We need to provide a customized rtx which contains
507 necessary information for data analysis,
508 so we create a parallel rtx like this:
509 (parallel [(set (reg:SI Rb)
510 (mem (reg:SI SP_REGNUM)))
512 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
515 (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
516 (set (reg:SI FP_REGNUM)
517 (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
518 (set (reg:SI GP_REGNUM)
519 (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
520 (set (reg:SI LP_REGNUM)
521 (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
522 (set (reg:SI SP_REGNUM)
523 (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
525 /* Calculate the number of registers that will be poped. */
527 if (cfun
->machine
->fp_size
)
529 if (cfun
->machine
->gp_size
)
531 if (cfun
->machine
->lp_size
)
533 /* Note that Rb and Re may be SP_REGNUM. DO NOT count it in. */
534 if (REGNO (Rb
) == SP_REGNUM
&& REGNO (Re
) == SP_REGNUM
)
535 num_use_regs
= extra_count
;
537 num_use_regs
= REGNO (Re
) - REGNO (Rb
) + 1 + extra_count
;
539 /* In addition to used registers,
540 we need one more space for (set sp sp+x) rtx. */
541 parallel_insn
= gen_rtx_PARALLEL (VOIDmode
,
542 rtvec_alloc (num_use_regs
+ 1));
545 /* Initialize offset and start to create pop behavior. */
548 /* Create (set regX mem) from Rb, Rb+1 up to Re. */
549 for (regno
= REGNO (Rb
); regno
<= (int) REGNO (Re
); regno
++)
551 /* Rb and Re may be SP_REGNUM.
552 We need to break this loop immediately. */
553 if (regno
== SP_REGNUM
)
556 reg
= gen_rtx_REG (SImode
, regno
);
557 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
560 pop_rtx
= gen_rtx_SET (VOIDmode
, reg
, mem
);
561 XVECEXP (parallel_insn
, 0, par_index
) = pop_rtx
;
562 RTX_FRAME_RELATED_P (pop_rtx
) = 1;
567 /* Create (set fp mem), (set gp mem), and (set lp mem) if necessary. */
568 if (cfun
->machine
->fp_size
)
570 reg
= gen_rtx_REG (SImode
, FP_REGNUM
);
571 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
574 pop_rtx
= gen_rtx_SET (VOIDmode
, reg
, mem
);
575 XVECEXP (parallel_insn
, 0, par_index
) = pop_rtx
;
576 RTX_FRAME_RELATED_P (pop_rtx
) = 1;
580 if (cfun
->machine
->gp_size
)
582 reg
= gen_rtx_REG (SImode
, GP_REGNUM
);
583 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
586 pop_rtx
= gen_rtx_SET (VOIDmode
, reg
, mem
);
587 XVECEXP (parallel_insn
, 0, par_index
) = pop_rtx
;
588 RTX_FRAME_RELATED_P (pop_rtx
) = 1;
592 if (cfun
->machine
->lp_size
)
594 reg
= gen_rtx_REG (SImode
, LP_REGNUM
);
595 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
598 pop_rtx
= gen_rtx_SET (VOIDmode
, reg
, mem
);
599 XVECEXP (parallel_insn
, 0, par_index
) = pop_rtx
;
600 RTX_FRAME_RELATED_P (pop_rtx
) = 1;
605 /* Create (set sp sp+x). */
607 /* The offset value is already in place. No need to re-calculate it. */
609 = gen_rtx_SET (VOIDmode
,
611 plus_constant (Pmode
, stack_pointer_rtx
, offset
));
612 XVECEXP (parallel_insn
, 0, par_index
) = adjust_sp_rtx
;
613 RTX_FRAME_RELATED_P (adjust_sp_rtx
) = 1;
615 return parallel_insn
;
618 /* Function to create a parallel rtx pattern
619 which presents stack v3push behavior.
620 The overall concept are:
621 "push registers to memory",
622 "adjust stack pointer". */
624 nds32_gen_stack_v3push (rtx Rb
,
626 rtx En4 ATTRIBUTE_UNUSED
,
640 /* We need to provide a customized rtx which contains
641 necessary information for data analysis,
642 so we create a parallel rtx like this:
644 (set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
646 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
649 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
651 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
653 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
655 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
657 (set (reg:SI SP_REGNUM)
658 (plus (reg:SI SP_REGNUM) (const_int -32-imm8u)))]) */
660 /* Calculate the number of registers that will be pushed.
661 Since $fp, $gp, and $lp is always pushed with v3push instruction,
662 we need to count these three registers.
663 Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
664 So there is no need to worry about Rb=Re=SP_REGNUM case. */
665 num_use_regs
= REGNO (Re
) - REGNO (Rb
) + 1 + 3;
667 /* In addition to used registers,
668 we need one more space for (set sp sp-x-imm8u) rtx. */
669 parallel_insn
= gen_rtx_PARALLEL (VOIDmode
,
670 rtvec_alloc (num_use_regs
+ 1));
673 /* Initialize offset and start to create push behavior. */
674 offset
= -(num_use_regs
* 4);
676 /* Create (set mem regX) from Rb, Rb+1 up to Re.
677 Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
678 So there is no need to worry about Rb=Re=SP_REGNUM case. */
679 for (regno
= REGNO (Rb
); regno
<= (int) REGNO (Re
); regno
++)
681 reg
= gen_rtx_REG (SImode
, regno
);
682 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
685 push_rtx
= gen_rtx_SET (VOIDmode
, mem
, reg
);
686 XVECEXP (parallel_insn
, 0, par_index
) = push_rtx
;
687 RTX_FRAME_RELATED_P (push_rtx
) = 1;
692 /* Create (set mem fp). */
693 reg
= gen_rtx_REG (SImode
, FP_REGNUM
);
694 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
697 push_rtx
= gen_rtx_SET (VOIDmode
, mem
, reg
);
698 XVECEXP (parallel_insn
, 0, par_index
) = push_rtx
;
699 RTX_FRAME_RELATED_P (push_rtx
) = 1;
702 /* Create (set mem gp). */
703 reg
= gen_rtx_REG (SImode
, GP_REGNUM
);
704 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
707 push_rtx
= gen_rtx_SET (VOIDmode
, mem
, reg
);
708 XVECEXP (parallel_insn
, 0, par_index
) = push_rtx
;
709 RTX_FRAME_RELATED_P (push_rtx
) = 1;
712 /* Create (set mem lp). */
713 reg
= gen_rtx_REG (SImode
, LP_REGNUM
);
714 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
717 push_rtx
= gen_rtx_SET (VOIDmode
, mem
, reg
);
718 XVECEXP (parallel_insn
, 0, par_index
) = push_rtx
;
719 RTX_FRAME_RELATED_P (push_rtx
) = 1;
723 /* Create (set sp sp-x-imm8u). */
725 /* We need to re-calculate the offset value again for adjustment. */
726 offset
= -(num_use_regs
* 4);
728 = gen_rtx_SET (VOIDmode
,
730 plus_constant (Pmode
,
732 offset
- INTVAL (imm8u
)));
733 XVECEXP (parallel_insn
, 0, par_index
) = adjust_sp_rtx
;
734 RTX_FRAME_RELATED_P (adjust_sp_rtx
) = 1;
736 return parallel_insn
;
739 /* Function to create a parallel rtx pattern
740 which presents stack v3pop behavior.
741 The overall concept are:
742 "pop registers from memory",
743 "adjust stack pointer". */
745 nds32_gen_stack_v3pop (rtx Rb
,
747 rtx En4 ATTRIBUTE_UNUSED
,
761 /* We need to provide a customized rtx which contains
762 necessary information for data analysis,
763 so we create a parallel rtx like this:
764 (parallel [(set (reg:SI Rb)
765 (mem (reg:SI SP_REGNUM)))
767 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
770 (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
771 (set (reg:SI FP_REGNUM)
772 (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
773 (set (reg:SI GP_REGNUM)
774 (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
775 (set (reg:SI LP_REGNUM)
776 (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
777 (set (reg:SI SP_REGNUM)
778 (plus (reg:SI SP_REGNUM) (const_int 32+imm8u)))]) */
780 /* Calculate the number of registers that will be poped.
781 Since $fp, $gp, and $lp is always poped with v3pop instruction,
782 we need to count these three registers.
783 Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
784 So there is no need to worry about Rb=Re=SP_REGNUM case. */
785 num_use_regs
= REGNO (Re
) - REGNO (Rb
) + 1 + 3;
787 /* In addition to used registers,
788 we need one more space for (set sp sp+x+imm8u) rtx. */
789 parallel_insn
= gen_rtx_PARALLEL (VOIDmode
,
790 rtvec_alloc (num_use_regs
+ 1));
793 /* Initialize offset and start to create pop behavior. */
796 /* Create (set regX mem) from Rb, Rb+1 up to Re.
797 Under v3pop, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
798 So there is no need to worry about Rb=Re=SP_REGNUM case. */
799 for (regno
= REGNO (Rb
); regno
<= (int) REGNO (Re
); regno
++)
801 reg
= gen_rtx_REG (SImode
, regno
);
802 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
805 pop_rtx
= gen_rtx_SET (VOIDmode
, reg
, mem
);
806 XVECEXP (parallel_insn
, 0, par_index
) = pop_rtx
;
807 RTX_FRAME_RELATED_P (pop_rtx
) = 1;
812 /* Create (set fp mem). */
813 reg
= gen_rtx_REG (SImode
, FP_REGNUM
);
814 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
817 pop_rtx
= gen_rtx_SET (VOIDmode
, reg
, mem
);
818 XVECEXP (parallel_insn
, 0, par_index
) = pop_rtx
;
819 RTX_FRAME_RELATED_P (pop_rtx
) = 1;
822 /* Create (set gp mem). */
823 reg
= gen_rtx_REG (SImode
, GP_REGNUM
);
824 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
827 pop_rtx
= gen_rtx_SET (VOIDmode
, reg
, mem
);
828 XVECEXP (parallel_insn
, 0, par_index
) = pop_rtx
;
829 RTX_FRAME_RELATED_P (pop_rtx
) = 1;
832 /* Create (set lp mem ). */
833 reg
= gen_rtx_REG (SImode
, LP_REGNUM
);
834 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
837 pop_rtx
= gen_rtx_SET (VOIDmode
, reg
, mem
);
838 XVECEXP (parallel_insn
, 0, par_index
) = pop_rtx
;
839 RTX_FRAME_RELATED_P (pop_rtx
) = 1;
843 /* Create (set sp sp+x+imm8u). */
845 /* The offset value is already in place. No need to re-calculate it. */
847 = gen_rtx_SET (VOIDmode
,
849 plus_constant (Pmode
,
851 offset
+ INTVAL (imm8u
)));
852 XVECEXP (parallel_insn
, 0, par_index
) = adjust_sp_rtx
;
853 RTX_FRAME_RELATED_P (adjust_sp_rtx
) = 1;
855 return parallel_insn
;
858 /* A subroutine that checks multiple load and store
859 using consecutive registers.
860 OP is a parallel rtx we would like to check.
861 LOAD_P indicates whether we are checking load operation.
862 PAR_INDEX is starting element of parallel rtx.
863 FIRST_ELT_REGNO is used to tell starting register number.
864 COUNT helps us to check consecutive register numbers. */
866 nds32_consecutive_registers_load_store_p (rtx op
,
878 for (i
= 0; i
< count
; i
++)
880 /* Pick up each element from parallel rtx. */
881 elt
= XVECEXP (op
, 0, i
+ par_index
);
883 /* If this element is not a 'set' rtx, return false immediately. */
884 if (GET_CODE (elt
) != SET
)
887 /* Pick up reg and mem of this element. */
888 elt_reg
= load_p
? SET_DEST (elt
) : SET_SRC (elt
);
889 elt_mem
= load_p
? SET_SRC (elt
) : SET_DEST (elt
);
891 /* If elt_reg is not a expected reg rtx, return false. */
892 if (GET_CODE (elt_reg
) != REG
|| GET_MODE (elt_reg
) != SImode
)
894 /* If elt_mem is not a expected mem rtx, return false. */
895 if (GET_CODE (elt_mem
) != MEM
|| GET_MODE (elt_mem
) != SImode
)
898 /* The consecutive registers should be in (Rb,Rb+1...Re) order. */
899 check_regno
= first_elt_regno
+ i
;
901 /* If the register number is not continuous, return false. */
902 if (REGNO (elt_reg
) != (unsigned int) check_regno
)
909 /* A helper function to emit section head template. */
911 nds32_emit_section_head_template (char section_name
[],
916 const char *flags_str
;
917 const char *type_str
;
919 flags_str
= (object_p
) ? "\"a\"" : "\"ax\"";
920 type_str
= (object_p
) ? "@object" : "@function";
922 fprintf (asm_out_file
, "\t.section\t%s, %s\n", section_name
, flags_str
);
923 fprintf (asm_out_file
, "\t.align\t%d\n", align_value
);
924 fprintf (asm_out_file
, "\t.global\t%s\n", symbol_name
);
925 fprintf (asm_out_file
, "\t.type\t%s, %s\n", symbol_name
, type_str
);
926 fprintf (asm_out_file
, "%s:\n", symbol_name
);
929 /* A helper function to emit section tail template. */
931 nds32_emit_section_tail_template (char symbol_name
[])
933 fprintf (asm_out_file
, "\t.size\t%s, .-%s\n", symbol_name
, symbol_name
);
936 /* Function to emit isr jump table section. */
938 nds32_emit_isr_jmptbl_section (int vector_id
)
940 char section_name
[100];
941 char symbol_name
[100];
943 /* Prepare jmptbl section and symbol name. */
944 snprintf (section_name
, sizeof (section_name
),
945 ".nds32_jmptbl.%02d", vector_id
);
946 snprintf (symbol_name
, sizeof (symbol_name
),
947 "_nds32_jmptbl_%02d", vector_id
);
949 nds32_emit_section_head_template (section_name
, symbol_name
, 2, true);
950 fprintf (asm_out_file
, "\t.word\t%s\n",
951 nds32_isr_vectors
[vector_id
].func_name
);
952 nds32_emit_section_tail_template (symbol_name
);
955 /* Function to emit isr vector section. */
957 nds32_emit_isr_vector_section (int vector_id
)
959 unsigned int vector_number_offset
= 0;
960 const char *c_str
= "CATEGORY";
961 const char *sr_str
= "SR";
962 const char *nt_str
= "NT";
963 const char *vs_str
= "VS";
964 char first_level_handler_name
[100];
965 char section_name
[100];
966 char symbol_name
[100];
968 /* Set the vector number offset so that we can calculate
969 the value that user specifies in the attribute.
970 We also prepare the category string for first level handler name. */
971 switch (nds32_isr_vectors
[vector_id
].category
)
973 case NDS32_ISR_INTERRUPT
:
974 vector_number_offset
= 9;
977 case NDS32_ISR_EXCEPTION
:
978 vector_number_offset
= 0;
982 case NDS32_ISR_RESET
:
983 /* Normally it should not be here. */
988 /* Prepare save reg string for first level handler name. */
989 switch (nds32_isr_vectors
[vector_id
].save_reg
)
994 case NDS32_PARTIAL_SAVE
:
999 /* Prepare nested type string for first level handler name. */
1000 switch (nds32_isr_vectors
[vector_id
].nested_type
)
1005 case NDS32_NOT_NESTED
:
1008 case NDS32_NESTED_READY
:
1013 /* Currently we have 4-byte or 16-byte size for each vector.
1014 If it is 4-byte, the first level handler name has suffix string "_4b". */
1015 vs_str
= (nds32_isr_vector_size
== 4) ? "_4b" : "";
1017 /* Now we can create first level handler name. */
1018 snprintf (first_level_handler_name
, sizeof (first_level_handler_name
),
1019 "_nds32_%s_%s_%s%s", c_str
, sr_str
, nt_str
, vs_str
);
1021 /* Prepare vector section and symbol name. */
1022 snprintf (section_name
, sizeof (section_name
),
1023 ".nds32_vector.%02d", vector_id
);
1024 snprintf (symbol_name
, sizeof (symbol_name
),
1025 "_nds32_vector_%02d%s", vector_id
, vs_str
);
1028 /* Everything is ready. We can start emit vector section content. */
1029 nds32_emit_section_head_template (section_name
, symbol_name
,
1030 floor_log2 (nds32_isr_vector_size
), false);
1032 /* According to the vector size, the instructions in the
1033 vector section may be different. */
1034 if (nds32_isr_vector_size
== 4)
1036 /* This block is for 4-byte vector size.
1037 Hardware $VID support is necessary and only one instruction
1038 is needed in vector section. */
1039 fprintf (asm_out_file
, "\tj\t%s ! jump to first level handler\n",
1040 first_level_handler_name
);
1044 /* This block is for 16-byte vector size.
1045 There is NO hardware $VID so that we need several instructions
1046 such as pushing GPRs and preparing software vid at vector section.
1047 For pushing GPRs, there are four variations for
1048 16-byte vector content and we have to handle each combination.
1049 For preparing software vid, note that the vid need to
1050 be substracted vector_number_offset. */
1051 if (TARGET_REDUCED_REGS
)
1053 if (nds32_isr_vectors
[vector_id
].save_reg
== NDS32_SAVE_ALL
)
1055 /* Case of reduced set registers and save_all attribute. */
1056 fprintf (asm_out_file
, "\t! reduced set regs + save_all\n");
1057 fprintf (asm_out_file
, "\tsmw.adm\t$r15, [$sp], $r15, 0xf\n");
1058 fprintf (asm_out_file
, "\tsmw.adm\t$r0, [$sp], $r10, 0x0\n");
1063 /* Case of reduced set registers and partial_save attribute. */
1064 fprintf (asm_out_file
, "\t! reduced set regs + partial_save\n");
1065 fprintf (asm_out_file
, "\tsmw.adm\t$r15, [$sp], $r15, 0x2\n");
1066 fprintf (asm_out_file
, "\tsmw.adm\t$r0, [$sp], $r5, 0x0\n");
1071 if (nds32_isr_vectors
[vector_id
].save_reg
== NDS32_SAVE_ALL
)
1073 /* Case of full set registers and save_all attribute. */
1074 fprintf (asm_out_file
, "\t! full set regs + save_all\n");
1075 fprintf (asm_out_file
, "\tsmw.adm\t$r0, [$sp], $r27, 0xf\n");
1079 /* Case of full set registers and partial_save attribute. */
1080 fprintf (asm_out_file
, "\t! full set regs + partial_save\n");
1081 fprintf (asm_out_file
, "\tsmw.adm\t$r15, [$sp], $r27, 0x2\n");
1082 fprintf (asm_out_file
, "\tsmw.adm\t$r0, [$sp], $r5, 0x0\n");
1086 fprintf (asm_out_file
, "\tmovi\t$r0, %d ! preparing software vid\n",
1087 vector_id
- vector_number_offset
);
1088 fprintf (asm_out_file
, "\tj\t%s ! jump to first level handler\n",
1089 first_level_handler_name
);
1092 nds32_emit_section_tail_template (symbol_name
);
1095 /* Function to emit isr reset handler content.
1096 Including all jmptbl/vector references, jmptbl section,
1097 vector section, nmi handler section, and warm handler section. */
1099 nds32_emit_isr_reset_content (void)
1102 unsigned int total_n_vectors
;
1104 char reset_handler_name
[100];
1105 char section_name
[100];
1106 char symbol_name
[100];
1108 total_n_vectors
= nds32_isr_vectors
[0].total_n_vectors
;
1109 vs_str
= (nds32_isr_vector_size
== 4) ? "_4b" : "";
1111 fprintf (asm_out_file
, "\t! RESET HANDLER CONTENT - BEGIN !\n");
1113 /* Create references in .rodata according to total number of vectors. */
1114 fprintf (asm_out_file
, "\t.section\t.rodata\n");
1115 fprintf (asm_out_file
, "\t.align\t2\n");
1117 /* Emit jmptbl references. */
1118 fprintf (asm_out_file
, "\t ! references to jmptbl section entries\n");
1119 for (i
= 0; i
< total_n_vectors
; i
++)
1120 fprintf (asm_out_file
, "\t.word\t_nds32_jmptbl_%02d\n", i
);
1122 /* Emit vector references. */
1123 fprintf (asm_out_file
, "\t ! references to vector section entries\n");
1124 for (i
= 0; i
< total_n_vectors
; i
++)
1125 fprintf (asm_out_file
, "\t.word\t_nds32_vector_%02d%s\n", i
, vs_str
);
1127 /* Emit jmptbl_00 section. */
1128 snprintf (section_name
, sizeof (section_name
), ".nds32_jmptbl.00");
1129 snprintf (symbol_name
, sizeof (symbol_name
), "_nds32_jmptbl_00");
1131 fprintf (asm_out_file
, "\t! ....................................\n");
1132 nds32_emit_section_head_template (section_name
, symbol_name
, 2, true);
1133 fprintf (asm_out_file
, "\t.word\t%s\n",
1134 nds32_isr_vectors
[0].func_name
);
1135 nds32_emit_section_tail_template (symbol_name
);
1137 /* Emit vector_00 section. */
1138 snprintf (section_name
, sizeof (section_name
), ".nds32_vector.00");
1139 snprintf (symbol_name
, sizeof (symbol_name
), "_nds32_vector_00%s", vs_str
);
1140 snprintf (reset_handler_name
, sizeof (reset_handler_name
),
1141 "_nds32_reset%s", vs_str
);
1143 fprintf (asm_out_file
, "\t! ....................................\n");
1144 nds32_emit_section_head_template (section_name
, symbol_name
,
1145 floor_log2 (nds32_isr_vector_size
), false);
1146 fprintf (asm_out_file
, "\tj\t%s ! jump to reset handler\n",
1147 reset_handler_name
);
1148 nds32_emit_section_tail_template (symbol_name
);
1150 /* Emit nmi handler section. */
1151 snprintf (section_name
, sizeof (section_name
), ".nds32_nmih");
1152 snprintf (symbol_name
, sizeof (symbol_name
), "_nds32_nmih");
1154 fprintf (asm_out_file
, "\t! ....................................\n");
1155 nds32_emit_section_head_template (section_name
, symbol_name
, 2, true);
1156 fprintf (asm_out_file
, "\t.word\t%s\n",
1157 (strlen (nds32_isr_vectors
[0].nmi_name
) == 0)
1159 : nds32_isr_vectors
[0].nmi_name
);
1160 nds32_emit_section_tail_template (symbol_name
);
1162 /* Emit warm handler section. */
1163 snprintf (section_name
, sizeof (section_name
), ".nds32_wrh");
1164 snprintf (symbol_name
, sizeof (symbol_name
), "_nds32_wrh");
1166 fprintf (asm_out_file
, "\t! ....................................\n");
1167 nds32_emit_section_head_template (section_name
, symbol_name
, 2, true);
1168 fprintf (asm_out_file
, "\t.word\t%s\n",
1169 (strlen (nds32_isr_vectors
[0].warm_name
) == 0)
1171 : nds32_isr_vectors
[0].warm_name
);
1172 nds32_emit_section_tail_template (symbol_name
);
1174 fprintf (asm_out_file
, "\t! RESET HANDLER CONTENT - END !\n");
1177 /* Function for nds32_merge_decl_attributes() and nds32_insert_attributes()
1178 to check if there are any conflict isr-specific attributes being set.
1180 1. Only 'save_all' or 'partial_save' in the attributes.
1181 2. Only 'nested', 'not_nested', or 'nested_ready' in the attributes.
1182 3. Only 'interrupt', 'exception', or 'reset' in the attributes. */
1184 nds32_check_isr_attrs_conflict (tree func_decl
, tree func_attrs
)
1186 int save_all_p
, partial_save_p
;
1187 int nested_p
, not_nested_p
, nested_ready_p
;
1188 int intr_p
, excp_p
, reset_p
;
1190 /* Initialize variables. */
1191 save_all_p
= partial_save_p
= 0;
1192 nested_p
= not_nested_p
= nested_ready_p
= 0;
1193 intr_p
= excp_p
= reset_p
= 0;
1195 /* We must check at MOST one attribute to set save-reg. */
1196 if (lookup_attribute ("save_all", func_attrs
))
1198 if (lookup_attribute ("partial_save", func_attrs
))
1201 if ((save_all_p
+ partial_save_p
) > 1)
1202 error ("multiple save reg attributes to function %qD", func_decl
);
1204 /* We must check at MOST one attribute to set nested-type. */
1205 if (lookup_attribute ("nested", func_attrs
))
1207 if (lookup_attribute ("not_nested", func_attrs
))
1209 if (lookup_attribute ("nested_ready", func_attrs
))
1212 if ((nested_p
+ not_nested_p
+ nested_ready_p
) > 1)
1213 error ("multiple nested types attributes to function %qD", func_decl
);
1215 /* We must check at MOST one attribute to
1216 set interrupt/exception/reset. */
1217 if (lookup_attribute ("interrupt", func_attrs
))
1219 if (lookup_attribute ("exception", func_attrs
))
1221 if (lookup_attribute ("reset", func_attrs
))
1224 if ((intr_p
+ excp_p
+ reset_p
) > 1)
1225 error ("multiple interrupt attributes to function %qD", func_decl
);
1228 /* Function to construct isr vectors information array.
1229 We DO NOT HAVE TO check if the attributes are valid
1230 because those works are supposed to be done on
1231 nds32_merge_decl_attributes() and nds32_insert_attributes(). */
1233 nds32_construct_isr_vectors_information (tree func_attrs
,
1234 const char *func_name
)
1236 tree save_all
, partial_save
;
1237 tree nested
, not_nested
, nested_ready
;
1238 tree intr
, excp
, reset
;
1240 save_all
= lookup_attribute ("save_all", func_attrs
);
1241 partial_save
= lookup_attribute ("partial_save", func_attrs
);
1243 nested
= lookup_attribute ("nested", func_attrs
);
1244 not_nested
= lookup_attribute ("not_nested", func_attrs
);
1245 nested_ready
= lookup_attribute ("nested_ready", func_attrs
);
1247 intr
= lookup_attribute ("interrupt", func_attrs
);
1248 excp
= lookup_attribute ("exception", func_attrs
);
1249 reset
= lookup_attribute ("reset", func_attrs
);
1251 /* If there is no interrupt/exception/reset, we can return immediately. */
1252 if (!intr
&& !excp
&& !reset
)
1255 /* If we are here, either we have interrupt/exception,
1256 or reset attribute. */
1261 /* Prepare id list so that we can traverse and set vector id. */
1262 id_list
= (intr
) ? (TREE_VALUE (intr
)) : (TREE_VALUE (excp
));
1268 unsigned int vector_number_offset
;
1270 /* The way to handle interrupt or exception is the same,
1271 we just need to take care of actual vector number.
1272 For interrupt(0..63), the actual vector number is (9..72).
1273 For exception(1..8), the actual vector number is (1..8). */
1274 vector_number_offset
= (intr
) ? (9) : (0);
1276 /* Pick up each vector id value. */
1277 id
= TREE_VALUE (id_list
);
1278 /* Add vector_number_offset to get actual vector number. */
1279 vector_id
= TREE_INT_CST_LOW (id
) + vector_number_offset
;
1281 /* Enable corresponding vector and set function name. */
1282 nds32_isr_vectors
[vector_id
].category
= (intr
)
1283 ? (NDS32_ISR_INTERRUPT
)
1284 : (NDS32_ISR_EXCEPTION
);
1285 strcpy (nds32_isr_vectors
[vector_id
].func_name
, func_name
);
1287 /* Set register saving scheme. */
1289 nds32_isr_vectors
[vector_id
].save_reg
= NDS32_SAVE_ALL
;
1290 else if (partial_save
)
1291 nds32_isr_vectors
[vector_id
].save_reg
= NDS32_PARTIAL_SAVE
;
1293 /* Set nested type. */
1295 nds32_isr_vectors
[vector_id
].nested_type
= NDS32_NESTED
;
1296 else if (not_nested
)
1297 nds32_isr_vectors
[vector_id
].nested_type
= NDS32_NOT_NESTED
;
1298 else if (nested_ready
)
1299 nds32_isr_vectors
[vector_id
].nested_type
= NDS32_NESTED_READY
;
1301 /* Advance to next id. */
1302 id_list
= TREE_CHAIN (id_list
);
1311 /* Deal with reset attribute. Its vector number is always 0. */
1312 nds32_isr_vectors
[0].category
= NDS32_ISR_RESET
;
1314 /* Prepare id_list and identify id value so that
1315 we can set total number of vectors. */
1316 id_list
= TREE_VALUE (reset
);
1317 id
= TREE_VALUE (id_list
);
1319 /* The total vectors = interrupt + exception numbers + reset.
1320 There are 8 exception and 1 reset in nds32 architecture. */
1321 nds32_isr_vectors
[0].total_n_vectors
= TREE_INT_CST_LOW (id
) + 8 + 1;
1322 strcpy (nds32_isr_vectors
[0].func_name
, func_name
);
1324 /* Retrieve nmi and warm function. */
1325 nmi
= lookup_attribute ("nmi", func_attrs
);
1326 warm
= lookup_attribute ("warm", func_attrs
);
1328 if (nmi
!= NULL_TREE
)
1333 nmi_func_list
= TREE_VALUE (nmi
);
1334 nmi_func
= TREE_VALUE (nmi_func_list
);
1336 /* Record nmi function name. */
1337 strcpy (nds32_isr_vectors
[0].nmi_name
,
1338 IDENTIFIER_POINTER (nmi_func
));
1341 if (warm
!= NULL_TREE
)
1343 tree warm_func_list
;
1346 warm_func_list
= TREE_VALUE (warm
);
1347 warm_func
= TREE_VALUE (warm_func_list
);
1349 /* Record warm function name. */
1350 strcpy (nds32_isr_vectors
[0].warm_name
,
1351 IDENTIFIER_POINTER (warm_func
));
1356 /* Function that may creates more instructions
1357 for large value on adjusting stack pointer.
1359 In nds32 target, 'addi' can be used for stack pointer
1360 adjustment in prologue/epilogue stage.
1361 However, sometimes there are too many local variables so that
1362 the adjustment value is not able to be fit in the 'addi' instruction.
1363 One solution is to move value into a register
1364 and then use 'add' instruction.
1365 In practice, we use TA_REGNUM ($r15) to accomplish this purpose.
1366 Also, we need to return zero for sp adjustment so that
1367 proglogue/epilogue knows there is no need to create 'addi' instruction. */
1369 nds32_force_addi_stack_int (int full_value
)
1376 if (!satisfies_constraint_Is15 (GEN_INT (full_value
)))
1378 /* The value is not able to fit in single addi instruction.
1379 Create more instructions of moving value into a register
1380 and then add stack pointer with it. */
1382 /* $r15 is going to be temporary register to hold the value. */
1383 tmp_reg
= gen_rtx_REG (SImode
, TA_REGNUM
);
1385 /* Create one more instruction to move value
1386 into the temporary register. */
1387 emit_move_insn (tmp_reg
, GEN_INT (full_value
));
1389 /* Create new 'add' rtx. */
1390 sp_adjust_insn
= gen_addsi3 (stack_pointer_rtx
,
1393 /* Emit rtx into insn list and receive its transformed insn rtx. */
1394 sp_adjust_insn
= emit_insn (sp_adjust_insn
);
1396 /* At prologue, we need to tell GCC that this is frame related insn,
1397 so that we can consider this instruction to output debug information.
1398 If full_value is NEGATIVE, it means this function
1399 is invoked by expand_prologue. */
1402 /* Because (tmp_reg <- full_value) may be split into two
1403 rtl patterns, we can not set its RTX_FRAME_RELATED_P.
1404 We need to construct another (sp <- sp + full_value)
1405 and then insert it into sp_adjust_insn's reg note to
1406 represent a frame related expression.
1407 GCC knows how to refer it and output debug information. */
1412 plus_rtx
= plus_constant (Pmode
, stack_pointer_rtx
, full_value
);
1413 set_rtx
= gen_rtx_SET (VOIDmode
, stack_pointer_rtx
, plus_rtx
);
1414 add_reg_note (sp_adjust_insn
, REG_FRAME_RELATED_EXPR
, set_rtx
);
1416 RTX_FRAME_RELATED_P (sp_adjust_insn
) = 1;
1419 /* We have used alternative way to adjust stack pointer value.
1420 Return zero so that prologue/epilogue
1421 will not generate other instructions. */
1426 /* The value is able to fit in addi instruction.
1427 However, remember to make it to be positive value
1428 because we want to return 'adjustment' result. */
1429 adjust_value
= (full_value
< 0) ? (-full_value
) : (full_value
);
1431 return adjust_value
;
1435 /* Return true if MODE/TYPE need double word alignment. */
1437 nds32_needs_double_word_align (enum machine_mode mode
, const_tree type
)
1441 /* Pick up the alignment according to the mode or type. */
1442 align
= NDS32_MODE_TYPE_ALIGN (mode
, type
);
1444 return (align
> PARM_BOUNDARY
);
1447 /* Return true if FUNC is a naked function. */
1449 nds32_naked_function_p (tree func
)
1453 if (TREE_CODE (func
) != FUNCTION_DECL
)
1456 t
= lookup_attribute ("naked", DECL_ATTRIBUTES (func
));
1458 return (t
!= NULL_TREE
);
1461 /* Function that check if 'X' is a valid address register.
1462 The variable 'STRICT' is very important to
1463 make decision for register number.
1466 => We are in reload pass or after reload pass.
1467 The register number should be strictly limited in general registers.
1470 => Before reload pass, we are free to use any register number. */
1472 nds32_address_register_rtx_p (rtx x
, bool strict
)
1476 if (GET_CODE (x
) != REG
)
1482 return REGNO_OK_FOR_BASE_P (regno
);
1487 /* Function that check if 'INDEX' is valid to be a index rtx for address.
1489 OUTER_MODE : Machine mode of outer address rtx.
1490 INDEX : Check if this rtx is valid to be a index for address.
1491 STRICT : If it is true, we are in reload pass or after reload pass. */
1493 nds32_legitimate_index_p (enum machine_mode outer_mode
,
1501 switch (GET_CODE (index
))
1504 regno
= REGNO (index
);
1505 /* If we are in reload pass or after reload pass,
1506 we need to limit it to general register. */
1508 return REGNO_OK_FOR_INDEX_P (regno
);
1513 /* The alignment of the integer value is determined by 'outer_mode'. */
1514 if (GET_MODE_SIZE (outer_mode
) == 1)
1516 /* Further check if the value is legal for the 'outer_mode'. */
1517 if (!satisfies_constraint_Is15 (index
))
1520 /* Pass all test, the value is valid, return true. */
1523 if (GET_MODE_SIZE (outer_mode
) == 2
1524 && NDS32_HALF_WORD_ALIGN_P (INTVAL (index
)))
1526 /* Further check if the value is legal for the 'outer_mode'. */
1527 if (!satisfies_constraint_Is16 (index
))
1530 /* Pass all test, the value is valid, return true. */
1533 if (GET_MODE_SIZE (outer_mode
) == 4
1534 && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index
)))
1536 /* Further check if the value is legal for the 'outer_mode'. */
1537 if (!satisfies_constraint_Is17 (index
))
1540 /* Pass all test, the value is valid, return true. */
1543 if (GET_MODE_SIZE (outer_mode
) == 8
1544 && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index
)))
1546 /* Further check if the value is legal for the 'outer_mode'. */
1547 if (!satisfies_constraint_Is17 (gen_int_mode (INTVAL (index
) + 4,
1551 /* Pass all test, the value is valid, return true. */
1558 op0
= XEXP (index
, 0);
1559 op1
= XEXP (index
, 1);
1561 if (REG_P (op0
) && CONST_INT_P (op1
))
1564 multiplier
= INTVAL (op1
);
1566 /* We only allow (mult reg const_int_1)
1567 or (mult reg const_int_2) or (mult reg const_int_4). */
1568 if (multiplier
!= 1 && multiplier
!= 2 && multiplier
!= 4)
1571 regno
= REGNO (op0
);
1572 /* Limit it in general registers if we are
1573 in reload pass or after reload pass. */
1575 return REGNO_OK_FOR_INDEX_P (regno
);
1583 op0
= XEXP (index
, 0);
1584 op1
= XEXP (index
, 1);
1586 if (REG_P (op0
) && CONST_INT_P (op1
))
1589 /* op1 is already the sv value for use to do left shift. */
1592 /* We only allow (ashift reg const_int_0)
1593 or (ashift reg const_int_1) or (ashift reg const_int_2). */
1594 if (sv
!= 0 && sv
!= 1 && sv
!=2)
1597 regno
= REGNO (op0
);
1598 /* Limit it in general registers if we are
1599 in reload pass or after reload pass. */
1601 return REGNO_OK_FOR_INDEX_P (regno
);
1613 /* Function to expand builtin function for
1614 '[(unspec_volatile [(reg)])]'. */
1616 nds32_expand_builtin_null_ftype_reg (enum insn_code icode
,
1617 tree exp
, rtx target
)
1620 ops[0] <--> value0 <--> arg0 */
1621 struct expand_operand ops
[1];
1625 /* Grab the incoming arguments and extract its rtx. */
1626 arg0
= CALL_EXPR_ARG (exp
, 0);
1627 value0
= expand_normal (arg0
);
1629 /* Create operands. */
1630 create_input_operand (&ops
[0], value0
, TYPE_MODE (TREE_TYPE (arg0
)));
1632 /* Emit new instruction. */
1633 if (!maybe_expand_insn (icode
, 1, ops
))
1634 error ("invalid argument to built-in function");
1639 /* Function to expand builtin function for
1640 '[(set (reg) (unspec_volatile [(imm)]))]'. */
1642 nds32_expand_builtin_reg_ftype_imm (enum insn_code icode
,
1643 tree exp
, rtx target
)
1646 ops[0] <--> target <--> exp
1647 ops[1] <--> value0 <--> arg0 */
1648 struct expand_operand ops
[2];
1652 /* Grab the incoming arguments and extract its rtx. */
1653 arg0
= CALL_EXPR_ARG (exp
, 0);
1654 value0
= expand_normal (arg0
);
1656 /* Create operands. */
1657 create_output_operand (&ops
[0], target
, TYPE_MODE (TREE_TYPE (exp
)));
1658 create_input_operand (&ops
[1], value0
, TYPE_MODE (TREE_TYPE (arg0
)));
1660 /* Emit new instruction. */
1661 if (!maybe_expand_insn (icode
, 2, ops
))
1662 error ("invalid argument to built-in function");
1667 /* Function to expand builtin function for
1668 '[(unspec_volatile [(reg) (imm)])]' pattern. */
1670 nds32_expand_builtin_null_ftype_reg_imm (enum insn_code icode
,
1671 tree exp
, rtx target
)
1674 ops[0] <--> value0 <--> arg0
1675 ops[1] <--> value1 <--> arg1 */
1676 struct expand_operand ops
[2];
1680 /* Grab the incoming arguments and extract its rtx. */
1681 arg0
= CALL_EXPR_ARG (exp
, 0);
1682 arg1
= CALL_EXPR_ARG (exp
, 1);
1683 value0
= expand_normal (arg0
);
1684 value1
= expand_normal (arg1
);
1686 /* Create operands. */
1687 create_input_operand (&ops
[0], value0
, TYPE_MODE (TREE_TYPE (arg0
)));
1688 create_input_operand (&ops
[1], value1
, TYPE_MODE (TREE_TYPE (arg1
)));
1690 /* Emit new instruction. */
1691 if (!maybe_expand_insn (icode
, 2, ops
))
1692 error ("invalid argument to built-in function");
1697 /* A helper function to return character based on byte size. */
1699 nds32_byte_to_size (int byte
)
1710 /* Normally it should not be here. */
1715 /* A helper function to check if this function should contain prologue. */
1717 nds32_have_prologue_p (void)
1721 for (i
= 0; i
< 28; i
++)
1722 if (NDS32_REQUIRED_CALLEE_SAVED_P (i
))
1726 || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM
)
1727 || NDS32_REQUIRED_CALLEE_SAVED_P (LP_REGNUM
));
1730 /* ------------------------------------------------------------------------ */
1732 /* PART 3: Implement target hook stuff definitions. */
1734 /* Register Classes. */
1736 static unsigned char
1737 nds32_class_max_nregs (reg_class_t rclass ATTRIBUTE_UNUSED
,
1738 enum machine_mode mode
)
1740 /* Return the maximum number of consecutive registers
1741 needed to represent "mode" in a register of "rclass". */
1742 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
);
1746 nds32_register_priority (int hard_regno
)
1748 /* Encourage to use r0-r7 for LRA when optimize for size. */
1749 if (optimize_size
&& hard_regno
< 8)
1755 /* Stack Layout and Calling Conventions. */
1757 /* There are three kinds of pointer concepts using in GCC compiler:
1759 frame pointer: A pointer to the first location of local variables.
1760 stack pointer: A pointer to the top of a stack frame.
1761 argument pointer: A pointer to the incoming arguments.
1763 In nds32 target calling convention, we are using 8-byte alignment.
1764 Besides, we would like to have each stack frame of a function includes:
1767 1. previous hard frame pointer
1769 3. callee-saved registers
1770 4. <padding bytes> (we will calculte in nds32_compute_stack_frame()
1772 cfun->machine->callee_saved_area_padding_bytes)
1776 2. spilling location
1777 3. <padding bytes> (it will be calculated by GCC itself)
1778 4. incoming arguments
1779 5. <padding bytes> (it will be calculated by GCC itself)
1782 1. <padding bytes> (it will be calculated by GCC itself)
1783 2. outgoing arguments
1785 We 'wrap' these blocks together with
1786 hard frame pointer ($r28) and stack pointer ($r31).
1787 By applying the basic frame/stack/argument pointers concept,
1788 the layout of a stack frame shoule be like this:
1791 old stack pointer -> ----
1793 | | saved arguments for
1794 | | vararg functions
1796 hard frame pointer -> --
1797 & argument pointer | | \
1798 | | previous hardware frame pointer
1800 | | callee-saved registers
1805 | | and incoming arguments
1812 stack pointer -> ----
1814 $SFP and $AP are used to represent frame pointer and arguments pointer,
1815 which will be both eliminated as hard frame pointer. */
1817 /* -- Eliminating Frame Pointer and Arg Pointer. */
1819 static bool nds32_can_eliminate (const int from_reg
, const int to_reg
)
1821 if (from_reg
== ARG_POINTER_REGNUM
&& to_reg
== STACK_POINTER_REGNUM
)
1824 if (from_reg
== ARG_POINTER_REGNUM
&& to_reg
== HARD_FRAME_POINTER_REGNUM
)
1827 if (from_reg
== FRAME_POINTER_REGNUM
&& to_reg
== STACK_POINTER_REGNUM
)
1830 if (from_reg
== FRAME_POINTER_REGNUM
&& to_reg
== HARD_FRAME_POINTER_REGNUM
)
1836 /* -- Passing Arguments in Registers. */
1839 nds32_function_arg (cumulative_args_t ca
, enum machine_mode mode
,
1840 const_tree type
, bool named
)
1842 CUMULATIVE_ARGS
*cum
= get_cumulative_args (ca
);
1844 /* The last time this hook is called,
1845 it is called with MODE == VOIDmode. */
1846 if (mode
== VOIDmode
)
1849 /* For nameless arguments, they are passed on the stack. */
1853 /* If there are still registers available, return it. */
1854 if (NDS32_ARG_PASS_IN_REG_P (cum
->reg_offset
, mode
, type
))
1856 /* Pick up the next available register number. */
1859 regno
= NDS32_AVAILABLE_REGNUM_FOR_ARG (cum
->reg_offset
, mode
, type
);
1860 return gen_rtx_REG (mode
, regno
);
1864 /* No register available, return NULL_RTX.
1865 The compiler will use stack to pass argument instead. */
1871 nds32_function_arg_advance (cumulative_args_t ca
, enum machine_mode mode
,
1872 const_tree type
, bool named
)
1874 CUMULATIVE_ARGS
*cum
= get_cumulative_args (ca
);
1876 /* Advance next register for use.
1877 Only named argument could be advanced. */
1881 = NDS32_AVAILABLE_REGNUM_FOR_ARG (cum
->reg_offset
, mode
, type
)
1882 - NDS32_GPR_ARG_FIRST_REGNUM
1883 + NDS32_NEED_N_REGS_FOR_ARG (mode
, type
);
1888 nds32_function_arg_boundary (enum machine_mode mode
, const_tree type
)
1890 return (nds32_needs_double_word_align (mode
, type
)
1891 ? NDS32_DOUBLE_WORD_ALIGNMENT
1895 /* -- How Scalar Function Values Are Returned. */
1898 nds32_function_value (const_tree ret_type
,
1899 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1900 bool outgoing ATTRIBUTE_UNUSED
)
1902 enum machine_mode mode
;
1905 mode
= TYPE_MODE (ret_type
);
1906 unsignedp
= TYPE_UNSIGNED (ret_type
);
1908 mode
= promote_mode (ret_type
, mode
, &unsignedp
);
1910 return gen_rtx_REG (mode
, NDS32_GPR_RET_FIRST_REGNUM
);
1914 nds32_libcall_value (enum machine_mode mode
,
1915 const_rtx fun ATTRIBUTE_UNUSED
)
1917 return gen_rtx_REG (mode
, NDS32_GPR_RET_FIRST_REGNUM
);
1921 nds32_function_value_regno_p (const unsigned int regno
)
1923 return (regno
== NDS32_GPR_RET_FIRST_REGNUM
);
1926 /* -- Function Entry and Exit. */
1928 /* The content produced from this function
1929 will be placed before prologue body. */
1931 nds32_asm_function_prologue (FILE *file
,
1932 HOST_WIDE_INT size ATTRIBUTE_UNUSED
)
1935 const char *func_name
;
1939 /* All stack frame information is supposed to be
1940 already computed when expanding prologue.
1941 The result is in cfun->machine.
1942 DO NOT call nds32_compute_stack_frame() here
1943 because it may corrupt the essential information. */
1945 fprintf (file
, "\t! BEGIN PROLOGUE\n");
1946 fprintf (file
, "\t! fp needed: %d\n", frame_pointer_needed
);
1947 fprintf (file
, "\t! pretend_args: %d\n", cfun
->machine
->va_args_size
);
1948 fprintf (file
, "\t! local_size: %d\n", cfun
->machine
->local_size
);
1949 fprintf (file
, "\t! out_args_size: %d\n", cfun
->machine
->out_args_size
);
1951 /* Use df_regs_ever_live_p() to detect if the register
1952 is ever used in the current function. */
1953 fprintf (file
, "\t! registers ever_live: ");
1954 for (r
= 0; r
< 32; r
++)
1956 if (df_regs_ever_live_p (r
))
1957 fprintf (file
, "%s, ", reg_names
[r
]);
1961 /* Display the attributes of this function. */
1962 fprintf (file
, "\t! function attributes: ");
1963 /* Get the attributes tree list.
1964 Note that GCC builds attributes list with reverse order. */
1965 attrs
= DECL_ATTRIBUTES (current_function_decl
);
1967 /* If there is no any attribute, print out "None". */
1969 fprintf (file
, "None");
1971 /* If there are some attributes, try if we need to
1972 construct isr vector information. */
1973 func_name
= IDENTIFIER_POINTER (DECL_NAME (current_function_decl
));
1974 nds32_construct_isr_vectors_information (attrs
, func_name
);
1976 /* Display all attributes of this function. */
1979 name
= TREE_PURPOSE (attrs
);
1980 fprintf (file
, "%s ", IDENTIFIER_POINTER (name
));
1982 /* Pick up the next attribute. */
1983 attrs
= TREE_CHAIN (attrs
);
1988 /* After rtl prologue has been expanded, this function is used. */
1990 nds32_asm_function_end_prologue (FILE *file
)
1992 fprintf (file
, "\t! END PROLOGUE\n");
1994 /* If frame pointer is NOT needed and -mfp-as-gp is issued,
1995 we can generate special directive: ".omit_fp_begin"
1996 to guide linker doing fp-as-gp optimization.
1997 However, for a naked function, which means
1998 it should not have prologue/epilogue,
1999 using fp-as-gp still requires saving $fp by push/pop behavior and
2000 there is no benefit to use fp-as-gp on such small function.
2001 So we need to make sure this function is NOT naked as well. */
2002 if (!frame_pointer_needed
2003 && !cfun
->machine
->naked_p
2004 && cfun
->machine
->fp_as_gp_p
)
2006 fprintf (file
, "\t! ----------------------------------------\n");
2007 fprintf (file
, "\t! Guide linker to do "
2008 "link time optimization: fp-as-gp\n");
2009 fprintf (file
, "\t! We add one more instruction to "
2010 "initialize $fp near to $gp location.\n");
2011 fprintf (file
, "\t! If linker fails to use fp-as-gp transformation,\n");
2012 fprintf (file
, "\t! this extra instruction should be "
2013 "eliminated at link stage.\n");
2014 fprintf (file
, "\t.omit_fp_begin\n");
2015 fprintf (file
, "\tla\t$fp,_FP_BASE_\n");
2016 fprintf (file
, "\t! ----------------------------------------\n");
2020 /* Before rtl epilogue has been expanded, this function is used. */
2022 nds32_asm_function_begin_epilogue (FILE *file
)
2024 /* If frame pointer is NOT needed and -mfp-as-gp is issued,
2025 we can generate special directive: ".omit_fp_end"
2026 to claim fp-as-gp optimization range.
2027 However, for a naked function,
2028 which means it should not have prologue/epilogue,
2029 using fp-as-gp still requires saving $fp by push/pop behavior and
2030 there is no benefit to use fp-as-gp on such small function.
2031 So we need to make sure this function is NOT naked as well. */
2032 if (!frame_pointer_needed
2033 && !cfun
->machine
->naked_p
2034 && cfun
->machine
->fp_as_gp_p
)
2036 fprintf (file
, "\t! ----------------------------------------\n");
2037 fprintf (file
, "\t! Claim the range of fp-as-gp "
2038 "link time optimization\n");
2039 fprintf (file
, "\t.omit_fp_end\n");
2040 fprintf (file
, "\t! ----------------------------------------\n");
2043 fprintf (file
, "\t! BEGIN EPILOGUE\n");
2046 /* The content produced from this function
2047 will be placed after epilogue body. */
2049 nds32_asm_function_epilogue (FILE *file
,
2050 HOST_WIDE_INT size ATTRIBUTE_UNUSED
)
2052 fprintf (file
, "\t! END EPILOGUE\n");
2056 nds32_asm_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
2057 HOST_WIDE_INT delta
,
2058 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED
,
2063 /* Make sure unwind info is emitted for the thunk if needed. */
2064 final_start_function (emit_barrier (), file
, 1);
2066 this_regno
= (aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
)
2072 if (satisfies_constraint_Is15 (GEN_INT (delta
)))
2074 fprintf (file
, "\taddi\t$r%d, $r%d, %ld\n",
2075 this_regno
, this_regno
, delta
);
2077 else if (satisfies_constraint_Is20 (GEN_INT (delta
)))
2079 fprintf (file
, "\tmovi\t$ta, %ld\n", delta
);
2080 fprintf (file
, "\tadd\t$r%d, $r%d, $ta\n", this_regno
, this_regno
);
2084 fprintf (file
, "\tsethi\t$ta, hi20(%ld)\n", delta
);
2085 fprintf (file
, "\tori\t$ta, $ta, lo12(%ld)\n", delta
);
2086 fprintf (file
, "\tadd\t$r%d, $r%d, $ta\n", this_regno
, this_regno
);
2090 fprintf (file
, "\tb\t");
2091 assemble_name (file
, XSTR (XEXP (DECL_RTL (function
), 0), 0));
2092 fprintf (file
, "\n");
2094 final_end_function ();
2097 /* -- Permitting tail calls. */
2099 /* Determine whether we need to enable warning for function return check. */
2101 nds32_warn_func_return (tree decl
)
2103 /* Naked functions are implemented entirely in assembly, including the
2104 return sequence, so suppress warnings about this. */
2105 return !nds32_naked_function_p (decl
);
2109 /* Implementing the Varargs Macros. */
2112 nds32_strict_argument_naming (cumulative_args_t ca ATTRIBUTE_UNUSED
)
2114 /* Return true so that all the named arguments for FUNCTION_ARG have named=1.
2115 If return false, for the variadic function, all named arguments EXCEPT
2116 the last are treated as named. */
2121 /* Trampolines for Nested Functions. */
2124 nds32_asm_trampoline_template (FILE *f
)
2126 if (TARGET_REDUCED_REGS
)
2128 /* Trampoline is not supported on reduced-set registers yet. */
2129 sorry ("a nested function is not supported for reduced registers");
2133 asm_fprintf (f
, "\t! Trampoline code template\n");
2134 asm_fprintf (f
, "\t! This code fragment will be copied "
2135 "into stack on demand\n");
2137 asm_fprintf (f
, "\tmfusr\t$r16,$pc\n");
2138 asm_fprintf (f
, "\tlwi\t$r15,[$r16 + 20] "
2139 "! load nested function address\n");
2140 asm_fprintf (f
, "\tlwi\t$r16,[$r16 + 16] "
2141 "! load chain_value\n");
2142 asm_fprintf (f
, "\tjr\t$r15\n");
2145 /* Preserve space ($pc + 16) for saving chain_value,
2146 nds32_trampoline_init will fill the value in this slot. */
2147 asm_fprintf (f
, "\t! space for saving chain_value\n");
2148 assemble_aligned_integer (UNITS_PER_WORD
, const0_rtx
);
2150 /* Preserve space ($pc + 20) for saving nested function address,
2151 nds32_trampoline_init will fill the value in this slot. */
2152 asm_fprintf (f
, "\t! space for saving nested function address\n");
2153 assemble_aligned_integer (UNITS_PER_WORD
, const0_rtx
);
2156 /* Emit RTL insns to initialize the variable parts of a trampoline. */
2158 nds32_trampoline_init (rtx m_tramp
, tree fndecl
, rtx chain_value
)
2162 /* Nested function address. */
2164 /* The memory rtx that is going to
2165 be filled with chain_value. */
2166 rtx chain_value_mem
;
2167 /* The memory rtx that is going to
2168 be filled with nested function address. */
2169 rtx nested_func_mem
;
2171 /* Start address of trampoline code in stack, for doing cache sync. */
2172 rtx sync_cache_addr
;
2173 /* Temporary register for sync instruction. */
2175 /* Instruction-cache sync instruction,
2176 requesting an argument as starting address. */
2178 /* For convenience reason of doing comparison. */
2179 int tramp_align_in_bytes
;
2181 /* Trampoline is not supported on reduced-set registers yet. */
2182 if (TARGET_REDUCED_REGS
)
2183 sorry ("a nested function is not supported for reduced registers");
2185 /* STEP 1: Copy trampoline code template into stack,
2186 fill up essential data into stack. */
2188 /* Extract nested function address rtx. */
2189 fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2191 /* m_tramp is memory rtx that is going to be filled with trampoline code.
2192 We have nds32_asm_trampoline_template() to emit template pattern. */
2193 emit_block_move (m_tramp
, assemble_trampoline_template (),
2194 GEN_INT (TRAMPOLINE_SIZE
), BLOCK_OP_NORMAL
);
2196 /* After copying trampoline code into stack,
2197 fill chain_value into stack. */
2198 chain_value_mem
= adjust_address (m_tramp
, SImode
, 16);
2199 emit_move_insn (chain_value_mem
, chain_value
);
2200 /* After copying trampoline code int stack,
2201 fill nested function address into stack. */
2202 nested_func_mem
= adjust_address (m_tramp
, SImode
, 20);
2203 emit_move_insn (nested_func_mem
, fnaddr
);
2205 /* STEP 2: Sync instruction-cache. */
2207 /* We have successfully filled trampoline code into stack.
2208 However, in order to execute code in stack correctly,
2209 we must sync instruction cache. */
2210 sync_cache_addr
= XEXP (m_tramp
, 0);
2211 tmp_reg
= gen_reg_rtx (SImode
);
2212 isync_insn
= gen_unspec_volatile_isync (tmp_reg
);
2214 /* Because nds32_cache_block_size is in bytes,
2215 we get trampoline alignment in bytes for convenient comparison. */
2216 tramp_align_in_bytes
= TRAMPOLINE_ALIGNMENT
/ BITS_PER_UNIT
;
2218 if (tramp_align_in_bytes
>= nds32_cache_block_size
2219 && (tramp_align_in_bytes
% nds32_cache_block_size
) == 0)
2221 /* Under this condition, the starting address of trampoline
2222 must be aligned to the starting address of each cache block
2223 and we do not have to worry about cross-boundary issue. */
2225 i
< (TRAMPOLINE_SIZE
+ nds32_cache_block_size
- 1)
2226 / nds32_cache_block_size
;
2229 emit_move_insn (tmp_reg
,
2230 plus_constant (Pmode
, sync_cache_addr
,
2231 nds32_cache_block_size
* i
));
2232 emit_insn (isync_insn
);
2235 else if (TRAMPOLINE_SIZE
> nds32_cache_block_size
)
2237 /* The starting address of trampoline code
2238 may not be aligned to the cache block,
2239 so the trampoline code may be across two cache block.
2240 We need to sync the last element, which is 4-byte size,
2241 of trampoline template. */
2243 i
< (TRAMPOLINE_SIZE
+ nds32_cache_block_size
- 1)
2244 / nds32_cache_block_size
;
2247 emit_move_insn (tmp_reg
,
2248 plus_constant (Pmode
, sync_cache_addr
,
2249 nds32_cache_block_size
* i
));
2250 emit_insn (isync_insn
);
2253 /* The last element of trampoline template is 4-byte size. */
2254 emit_move_insn (tmp_reg
,
2255 plus_constant (Pmode
, sync_cache_addr
,
2256 TRAMPOLINE_SIZE
- 4));
2257 emit_insn (isync_insn
);
2261 /* This is the simplest case.
2262 Because TRAMPOLINE_SIZE is less than or
2263 equal to nds32_cache_block_size,
2264 we can just sync start address and
2265 the last element of trampoline code. */
2267 /* Sync starting address of tampoline code. */
2268 emit_move_insn (tmp_reg
, sync_cache_addr
);
2269 emit_insn (isync_insn
);
2270 /* Sync the last element, which is 4-byte size,
2271 of trampoline template. */
2272 emit_move_insn (tmp_reg
,
2273 plus_constant (Pmode
, sync_cache_addr
,
2274 TRAMPOLINE_SIZE
- 4));
2275 emit_insn (isync_insn
);
2278 /* Set instruction serialization barrier
2279 to guarantee the correct operations. */
2280 emit_insn (gen_unspec_volatile_isb ());
2284 /* Addressing Modes. */
2287 nds32_legitimate_address_p (enum machine_mode mode
, rtx x
, bool strict
)
2289 /* For (mem:DI addr) or (mem:DF addr) case,
2290 we only allow 'addr' to be [reg], [symbol_ref],
2291 [const], or [reg + const_int] pattern. */
2292 if (mode
== DImode
|| mode
== DFmode
)
2294 /* Allow [Reg + const_int] addressing mode. */
2295 if (GET_CODE (x
) == PLUS
)
2297 if (nds32_address_register_rtx_p (XEXP (x
, 0), strict
)
2298 && nds32_legitimate_index_p (mode
, XEXP (x
, 1), strict
)
2299 && CONST_INT_P (XEXP (x
, 1)))
2302 else if (nds32_address_register_rtx_p (XEXP (x
, 1), strict
)
2303 && nds32_legitimate_index_p (mode
, XEXP (x
, 0), strict
)
2304 && CONST_INT_P (XEXP (x
, 0)))
2308 /* Now check [reg], [symbol_ref], and [const]. */
2309 if (GET_CODE (x
) != REG
2310 && GET_CODE (x
) != SYMBOL_REF
2311 && GET_CODE (x
) != CONST
)
2315 /* Check if 'x' is a valid address. */
2316 switch (GET_CODE (x
))
2319 /* (mem (reg A)) => [Ra] */
2320 return nds32_address_register_rtx_p (x
, strict
);
2324 if (!TARGET_GP_DIRECT
2325 && (reload_completed
2326 || reload_in_progress
2327 || lra_in_progress
))
2330 /* (mem (symbol_ref A)) => [symbol_ref] */
2331 return !currently_expanding_to_rtl
;
2335 if (!TARGET_GP_DIRECT
2336 && (reload_completed
2337 || reload_in_progress
2338 || lra_in_progress
))
2341 /* (mem (const (...)))
2342 => [ + const_addr ], where const_addr = symbol_ref + const_int */
2343 if (GET_CODE (XEXP (x
, 0)) == PLUS
)
2345 rtx plus_op
= XEXP (x
, 0);
2347 rtx op0
= XEXP (plus_op
, 0);
2348 rtx op1
= XEXP (plus_op
, 1);
2350 if (GET_CODE (op0
) == SYMBOL_REF
&& CONST_INT_P (op1
))
2359 /* (mem (post_modify (reg) (plus (reg) (reg))))
2361 /* (mem (post_modify (reg) (plus (reg) (const_int))))
2362 => [Ra], const_int */
2363 if (GET_CODE (XEXP (x
, 0)) == REG
2364 && GET_CODE (XEXP (x
, 1)) == PLUS
)
2366 rtx plus_op
= XEXP (x
, 1);
2368 rtx op0
= XEXP (plus_op
, 0);
2369 rtx op1
= XEXP (plus_op
, 1);
2371 if (nds32_address_register_rtx_p (op0
, strict
)
2372 && nds32_legitimate_index_p (mode
, op1
, strict
))
2382 /* (mem (post_inc reg)) => [Ra], 1/2/4 */
2383 /* (mem (post_dec reg)) => [Ra], -1/-2/-4 */
2384 /* The 1/2/4 or -1/-2/-4 have been displayed in nds32.md.
2385 We only need to deal with register Ra. */
2386 if (nds32_address_register_rtx_p (XEXP (x
, 0), strict
))
2392 /* (mem (plus reg const_int))
2394 /* (mem (plus reg reg))
2396 /* (mem (plus (mult reg const_int) reg))
2397 => [Ra + Rb << sv] */
2398 if (nds32_address_register_rtx_p (XEXP (x
, 0), strict
)
2399 && nds32_legitimate_index_p (mode
, XEXP (x
, 1), strict
))
2401 else if (nds32_address_register_rtx_p (XEXP (x
, 1), strict
)
2402 && nds32_legitimate_index_p (mode
, XEXP (x
, 0), strict
))
2408 if (!TARGET_GP_DIRECT
)
2417 /* Describing Relative Costs of Operations. */
2419 static int nds32_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED
,
2423 if (from
== HIGH_REGS
|| to
== HIGH_REGS
)
2429 static int nds32_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED
,
2430 reg_class_t rclass ATTRIBUTE_UNUSED
,
2431 bool in ATTRIBUTE_UNUSED
)
2436 /* This target hook describes the relative costs of RTL expressions.
2437 Return 'true' when all subexpressions of x have been processed.
2438 Return 'false' to sum the costs of sub-rtx, plus cost of this operation.
2439 Refer to gcc/rtlanal.c for more information. */
2441 nds32_rtx_costs (rtx x
,
2444 int opno ATTRIBUTE_UNUSED
,
2448 /* According to 'speed', goto suitable cost model section. */
2450 goto performance_cost
;
2456 /* This is section for performance cost model. */
2458 /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4.
2459 We treat it as 4-cycle cost for each instruction
2460 under performance consideration. */
2464 /* For 'SET' rtx, we need to return false
2465 so that it can recursively calculate costs. */
2469 /* Used in combine.c as a marker. */
2474 *total
= COSTS_N_INSNS (1);
2481 *total
= COSTS_N_INSNS (7);
2485 *total
= COSTS_N_INSNS (1);
2493 /* This is section for size cost model. */
2495 /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4.
2496 We treat it as 4-byte cost for each instruction
2497 under code size consideration. */
2501 /* For 'SET' rtx, we need to return false
2502 so that it can recursively calculate costs. */
2506 /* Used in combine.c as a marker. */
2511 /* All instructions involving constant operation
2512 need to be considered for cost evaluation. */
2513 if (outer_code
== SET
)
2515 /* (set X imm5s), use movi55, 2-byte cost.
2516 (set X imm20s), use movi, 4-byte cost.
2517 (set X BIG_INT), use sethi/ori, 8-byte cost. */
2518 if (satisfies_constraint_Is05 (x
))
2519 *total
= COSTS_N_INSNS (1) - 2;
2520 else if (satisfies_constraint_Is20 (x
))
2521 *total
= COSTS_N_INSNS (1);
2523 *total
= COSTS_N_INSNS (2);
2525 else if (outer_code
== PLUS
|| outer_code
== MINUS
)
2527 /* Possible addi333/subi333 or subi45/addi45, 2-byte cost.
2528 General case, cost 1 instruction with 4-byte. */
2529 if (satisfies_constraint_Iu05 (x
))
2530 *total
= COSTS_N_INSNS (1) - 2;
2532 *total
= COSTS_N_INSNS (1);
2534 else if (outer_code
== ASHIFT
)
2536 /* Possible slli333, 2-byte cost.
2537 General case, cost 1 instruction with 4-byte. */
2538 if (satisfies_constraint_Iu03 (x
))
2539 *total
= COSTS_N_INSNS (1) - 2;
2541 *total
= COSTS_N_INSNS (1);
2543 else if (outer_code
== ASHIFTRT
|| outer_code
== LSHIFTRT
)
2545 /* Possible srai45 or srli45, 2-byte cost.
2546 General case, cost 1 instruction with 4-byte. */
2547 if (satisfies_constraint_Iu05 (x
))
2548 *total
= COSTS_N_INSNS (1) - 2;
2550 *total
= COSTS_N_INSNS (1);
2554 /* For other cases, simply set it 4-byte cost. */
2555 *total
= COSTS_N_INSNS (1);
2560 /* It requires high part and low part processing, set it 8-byte cost. */
2561 *total
= COSTS_N_INSNS (2);
2565 /* For other cases, generally we set it 4-byte cost
2566 and stop resurively traversing. */
2567 *total
= COSTS_N_INSNS (1);
2574 static int nds32_address_cost (rtx address
,
2575 enum machine_mode mode ATTRIBUTE_UNUSED
,
2576 addr_space_t as ATTRIBUTE_UNUSED
,
2582 code
= GET_CODE (address
);
2584 /* According to 'speed', goto suitable cost model section. */
2586 goto performance_cost
;
2591 /* This is section for performance cost model. */
2593 /* FALLTHRU, currently we use same cost model as size_cost. */
2596 /* This is section for size cost model. */
2603 /* We encourage that rtx contains
2604 POST_MODIFY/POST_INC/POST_DEC behavior. */
2608 /* We can have gp-relative load/store for symbol_ref.
2609 Have it 4-byte cost. */
2610 return COSTS_N_INSNS (1);
2613 /* It is supposed to be the pattern (const (plus symbol_ref const_int)).
2614 Have it 4-byte cost. */
2615 return COSTS_N_INSNS (1);
2618 /* Simply return 4-byte costs. */
2619 return COSTS_N_INSNS (1);
2622 /* We do not need to check if the address is a legitimate address,
2623 because this hook is never called with an invalid address.
2624 But we better check the range of
2625 const_int value for cost, if it exists. */
2626 plus0
= XEXP (address
, 0);
2627 plus1
= XEXP (address
, 1);
2629 if (REG_P (plus0
) && CONST_INT_P (plus1
))
2631 /* If it is possible to be lwi333/swi333 form,
2632 make it 2-byte cost. */
2633 if (satisfies_constraint_Iu05 (plus1
))
2634 return (COSTS_N_INSNS (1) - 2);
2636 return COSTS_N_INSNS (1);
2639 /* For other 'plus' situation, make it cost 4-byte. */
2640 return COSTS_N_INSNS (1);
2646 return COSTS_N_INSNS (4);
2650 /* Defining the Output Assembler Language. */
2652 /* -- The Overall Framework of an Assembler File. */
2655 nds32_asm_file_start (void)
2659 default_file_start ();
2661 /* Tell assembler which ABI we are using. */
2662 fprintf (asm_out_file
, "\t! ABI version\n");
2663 fprintf (asm_out_file
, "\t.abi_2\n");
2665 /* Tell assembler that this asm code is generated by compiler. */
2666 fprintf (asm_out_file
, "\t! This asm file is generated by compiler\n");
2667 fprintf (asm_out_file
, "\t.flag\tverbatim\n");
2668 /* Give assembler the size of each vector for interrupt handler. */
2669 fprintf (asm_out_file
, "\t! This vector size directive is required "
2670 "for checking inconsistency on interrupt handler\n");
2671 fprintf (asm_out_file
, "\t.vec_size\t%d\n", nds32_isr_vector_size
);
2673 /* If user enables '-mforce-fp-as-gp' or compiles programs with -Os,
2674 the compiler may produce 'la $fp,_FP_BASE_' instruction
2675 at prologue for fp-as-gp optimization.
2676 We should emit weak reference of _FP_BASE_ to avoid undefined reference
2677 in case user does not pass '--relax' option to linker. */
2678 if (TARGET_FORCE_FP_AS_GP
|| optimize_size
)
2680 fprintf (asm_out_file
, "\t! This weak reference is required to do "
2681 "fp-as-gp link time optimization\n");
2682 fprintf (asm_out_file
, "\t.weak\t_FP_BASE_\n");
2684 /* If user enables '-mex9', we should emit relaxation directive
2685 to tell linker that this file is allowed to do ex9 optimization. */
2688 fprintf (asm_out_file
, "\t! This relaxation directive is required "
2689 "to do ex9 link time optimization\n");
2690 fprintf (asm_out_file
, "\t.relax\tex9\n");
2693 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2696 fprintf (asm_out_file
, "\t! ISA family\t\t: %s\n", "V2");
2698 fprintf (asm_out_file
, "\t! ISA family\t\t: %s\n", "V3");
2700 fprintf (asm_out_file
, "\t! ISA family\t\t: %s\n", "V3M");
2702 fprintf (asm_out_file
, "\t! Endian setting\t: %s\n",
2703 ((TARGET_BIG_ENDIAN
) ? "big-endian"
2704 : "little-endian"));
2706 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2708 fprintf (asm_out_file
, "\t! Use conditional move\t\t: %s\n",
2709 ((TARGET_CMOV
) ? "Yes"
2711 fprintf (asm_out_file
, "\t! Use performance extension\t: %s\n",
2712 ((TARGET_PERF_EXT
) ? "Yes"
2715 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2717 fprintf (asm_out_file
, "\t! V3PUSH instructions\t: %s\n",
2718 ((TARGET_V3PUSH
) ? "Yes"
2720 fprintf (asm_out_file
, "\t! 16-bit instructions\t: %s\n",
2721 ((TARGET_16_BIT
) ? "Yes"
2723 fprintf (asm_out_file
, "\t! GP base access\t: %s\n",
2724 ((TARGET_GP_DIRECT
) ? "Yes"
2726 fprintf (asm_out_file
, "\t! Reduced registers set\t: %s\n",
2727 ((TARGET_REDUCED_REGS
) ? "Yes"
2730 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2733 fprintf (asm_out_file
, "\t! Optimization level\t: -Os\n");
2735 fprintf (asm_out_file
, "\t! Optimization level\t: -O%d\n", optimize
);
2737 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2739 fprintf (asm_out_file
, "\t! Cache block size\t: %d\n",
2740 nds32_cache_block_size
);
2742 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2744 /* Initialize isr vector information array before compiling functions. */
2745 for (i
= 0; i
< NDS32_N_ISR_VECTORS
; i
++)
2747 nds32_isr_vectors
[i
].category
= NDS32_ISR_NONE
;
2748 strcpy (nds32_isr_vectors
[i
].func_name
, "");
2749 nds32_isr_vectors
[i
].save_reg
= NDS32_PARTIAL_SAVE
;
2750 nds32_isr_vectors
[i
].nested_type
= NDS32_NOT_NESTED
;
2751 nds32_isr_vectors
[i
].total_n_vectors
= 0;
2752 strcpy (nds32_isr_vectors
[i
].nmi_name
, "");
2753 strcpy (nds32_isr_vectors
[i
].warm_name
, "");
2758 nds32_asm_file_end (void)
2762 /* If all the vectors are NDS32_ISR_NONE, we can return immediately. */
2763 for (i
= 0; i
< NDS32_N_ISR_VECTORS
; i
++)
2764 if (nds32_isr_vectors
[i
].category
!= NDS32_ISR_NONE
)
2767 if (i
== NDS32_N_ISR_VECTORS
)
2770 /* At least one vector is NOT NDS32_ISR_NONE,
2771 we should output isr vector information. */
2772 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2773 fprintf (asm_out_file
, "\t! The isr vector information:\n");
2774 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2776 /* Check reset handler first. Its vector number is always 0. */
2777 if (nds32_isr_vectors
[0].category
== NDS32_ISR_RESET
)
2779 nds32_emit_isr_reset_content ();
2780 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2783 /* Check other vectors, starting from vector number 1. */
2784 for (i
= 1; i
< NDS32_N_ISR_VECTORS
; i
++)
2786 if (nds32_isr_vectors
[i
].category
== NDS32_ISR_INTERRUPT
2787 || nds32_isr_vectors
[i
].category
== NDS32_ISR_EXCEPTION
)
2789 /* Found one vector which is interupt or exception.
2790 Output its jmptbl and vector section content. */
2791 fprintf (asm_out_file
, "\t! interrupt/exception vector %02d\n", i
);
2792 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2793 nds32_emit_isr_jmptbl_section (i
);
2794 fprintf (asm_out_file
, "\t! ....................................\n");
2795 nds32_emit_isr_vector_section (i
);
2796 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2800 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2803 /* -- Output and Generation of Labels. */
2806 nds32_asm_globalize_label (FILE *stream
, const char *name
)
2808 fputs ("\t.global\t", stream
);
2809 assemble_name (stream
, name
);
2810 fputs ("\n", stream
);
2813 /* -- Output of Assembler Instructions. */
2816 nds32_print_operand (FILE *stream
, rtx x
, int code
)
2823 /* Do nothing special. */
2827 /* 'x' is supposed to be CONST_INT, get the value. */
2828 gcc_assert (CONST_INT_P (x
));
2829 op_value
= INTVAL (x
);
2831 /* According to the Andes architecture,
2832 the system/user register index range is 0 ~ 1023.
2833 In order to avoid conflict between user-specified-integer value
2834 and enum-specified-register value,
2835 the 'enum nds32_intrinsic_registers' value
2836 in nds32_intrinsic.h starts from 1024. */
2837 if (op_value
< 1024 && op_value
>= 0)
2839 /* If user gives integer value directly (0~1023),
2840 we just print out the value. */
2841 fprintf (stream
, "%d", op_value
);
2843 else if (op_value
< 0
2844 || op_value
>= ((int) ARRAY_SIZE (nds32_intrinsic_register_names
)
2847 /* The enum index value for array size is out of range. */
2848 error ("intrinsic register index is out of range");
2852 /* If user applies normal way with __NDS32_REG_XXX__ enum data,
2853 we can print out register name. Remember to substract 1024. */
2854 fprintf (stream
, "%s",
2855 nds32_intrinsic_register_names
[op_value
- 1024]);
2858 /* No need to handle following process, so return immediately. */
2863 output_operand_lossage ("invalid operand output code");
2867 switch (GET_CODE (x
))
2871 output_addr_const (stream
, x
);
2875 /* Forbid using static chain register ($r16)
2876 on reduced-set registers configuration. */
2877 if (TARGET_REDUCED_REGS
2878 && REGNO (x
) == STATIC_CHAIN_REGNUM
)
2879 sorry ("a nested function is not supported for reduced registers");
2881 /* Normal cases, print out register name. */
2882 fputs (reg_names
[REGNO (x
)], stream
);
2886 output_address (XEXP (x
, 0));
2892 output_addr_const (stream
, x
);
2896 /* Generally, output_addr_const () is able to handle most cases.
2897 We want to see what CODE could appear,
2898 so we use gcc_unreachable() to stop it. */
2906 nds32_print_operand_address (FILE *stream
, rtx x
)
2910 switch (GET_CODE (x
))
2914 /* [ + symbol_ref] */
2915 /* [ + const_addr], where const_addr = symbol_ref + const_int */
2916 fputs ("[ + ", stream
);
2917 output_addr_const (stream
, x
);
2918 fputs ("]", stream
);
2922 /* Forbid using static chain register ($r16)
2923 on reduced-set registers configuration. */
2924 if (TARGET_REDUCED_REGS
2925 && REGNO (x
) == STATIC_CHAIN_REGNUM
)
2926 sorry ("a nested function is not supported for reduced registers");
2929 fprintf (stream
, "[%s]", reg_names
[REGNO (x
)]);
2936 /* Checking op0, forbid using static chain register ($r16)
2937 on reduced-set registers configuration. */
2938 if (TARGET_REDUCED_REGS
2940 && REGNO (op0
) == STATIC_CHAIN_REGNUM
)
2941 sorry ("a nested function is not supported for reduced registers");
2942 /* Checking op1, forbid using static chain register ($r16)
2943 on reduced-set registers configuration. */
2944 if (TARGET_REDUCED_REGS
2946 && REGNO (op1
) == STATIC_CHAIN_REGNUM
)
2947 sorry ("a nested function is not supported for reduced registers");
2949 if (REG_P (op0
) && CONST_INT_P (op1
))
2952 fprintf (stream
, "[%s + (%d)]",
2953 reg_names
[REGNO (op0
)], (int)INTVAL (op1
));
2955 else if (REG_P (op0
) && REG_P (op1
))
2958 fprintf (stream
, "[%s + %s]",
2959 reg_names
[REGNO (op0
)], reg_names
[REGNO (op1
)]);
2961 else if (GET_CODE (op0
) == MULT
&& REG_P (op1
))
2964 From observation, the pattern looks like:
2965 (plus:SI (mult:SI (reg:SI 58)
2966 (const_int 4 [0x4]))
2970 /* We need to set sv to output shift value. */
2971 if (INTVAL (XEXP (op0
, 1)) == 1)
2973 else if (INTVAL (XEXP (op0
, 1)) == 2)
2975 else if (INTVAL (XEXP (op0
, 1)) == 4)
2980 fprintf (stream
, "[%s + %s << %d]",
2981 reg_names
[REGNO (op1
)],
2982 reg_names
[REGNO (XEXP (op0
, 0))],
2987 /* The control flow is not supposed to be here. */
2995 /* (post_modify (regA) (plus (regA) (regB)))
2996 (post_modify (regA) (plus (regA) (const_int)))
2997 We would like to extract
2998 regA and regB (or const_int) from plus rtx. */
2999 op0
= XEXP (XEXP (x
, 1), 0);
3000 op1
= XEXP (XEXP (x
, 1), 1);
3002 /* Checking op0, forbid using static chain register ($r16)
3003 on reduced-set registers configuration. */
3004 if (TARGET_REDUCED_REGS
3006 && REGNO (op0
) == STATIC_CHAIN_REGNUM
)
3007 sorry ("a nested function is not supported for reduced registers");
3008 /* Checking op1, forbid using static chain register ($r16)
3009 on reduced-set registers configuration. */
3010 if (TARGET_REDUCED_REGS
3012 && REGNO (op1
) == STATIC_CHAIN_REGNUM
)
3013 sorry ("a nested function is not supported for reduced registers");
3015 if (REG_P (op0
) && REG_P (op1
))
3018 fprintf (stream
, "[%s], %s",
3019 reg_names
[REGNO (op0
)], reg_names
[REGNO (op1
)]);
3021 else if (REG_P (op0
) && CONST_INT_P (op1
))
3024 fprintf (stream
, "[%s], %d",
3025 reg_names
[REGNO (op0
)], (int)INTVAL (op1
));
3029 /* The control flow is not supposed to be here. */
3040 /* Checking op0, forbid using static chain register ($r16)
3041 on reduced-set registers configuration. */
3042 if (TARGET_REDUCED_REGS
3044 && REGNO (op0
) == STATIC_CHAIN_REGNUM
)
3045 sorry ("a nested function is not supported for reduced registers");
3049 /* "[Ra], 1/2/4" or "[Ra], -1/-2/-4"
3050 The 1/2/4 or -1/-2/-4 have been displayed in nds32.md.
3051 We only need to deal with register Ra. */
3052 fprintf (stream
, "[%s]", reg_names
[REGNO (op0
)]);
3056 /* The control flow is not supposed to be here. */
3064 /* Generally, output_addr_const () is able to handle most cases.
3065 We want to see what CODE could appear,
3066 so we use gcc_unreachable() to stop it. */
3074 /* Defining target-specific uses of __attribute__. */
3076 /* Add some checking after merging attributes. */
3078 nds32_merge_decl_attributes (tree olddecl
, tree newdecl
)
3080 tree combined_attrs
;
3082 /* Create combined attributes. */
3083 combined_attrs
= merge_attributes (DECL_ATTRIBUTES (olddecl
),
3084 DECL_ATTRIBUTES (newdecl
));
3086 /* Since newdecl is acutally a duplicate of olddecl,
3087 we can take olddecl for some operations. */
3088 if (TREE_CODE (olddecl
) == FUNCTION_DECL
)
3090 /* Check isr-specific attributes conflict. */
3091 nds32_check_isr_attrs_conflict (olddecl
, combined_attrs
);
3094 return combined_attrs
;
3097 /* Add some checking when inserting attributes. */
3099 nds32_insert_attributes (tree decl
, tree
*attributes
)
3101 /* For function declaration, we need to check isr-specific attributes:
3102 1. Call nds32_check_isr_attrs_conflict() to check any conflict.
3103 2. Check valid integer value for interrupt/exception.
3104 3. Check valid integer value for reset.
3105 4. Check valid function for nmi/warm. */
3106 if (TREE_CODE (decl
) == FUNCTION_DECL
)
3109 tree intr
, excp
, reset
;
3111 /* Pick up function attributes. */
3112 func_attrs
= *attributes
;
3114 /* 1. Call nds32_check_isr_attrs_conflict() to check any conflict. */
3115 nds32_check_isr_attrs_conflict (decl
, func_attrs
);
3117 /* Now we are starting to check valid id value
3118 for interrupt/exception/reset.
3119 Note that we ONLY check its validity here.
3120 To construct isr vector information, it is still performed
3121 by nds32_construct_isr_vectors_information(). */
3122 intr
= lookup_attribute ("interrupt", func_attrs
);
3123 excp
= lookup_attribute ("exception", func_attrs
);
3124 reset
= lookup_attribute ("reset", func_attrs
);
3128 /* Deal with interrupt/exception. */
3130 unsigned int lower_bound
, upper_bound
;
3132 /* The way to handle interrupt or exception is the same,
3133 we just need to take care of actual vector number.
3134 For interrupt(0..63), the actual vector number is (9..72).
3135 For exception(1..8), the actual vector number is (1..8). */
3136 lower_bound
= (intr
) ? (0) : (1);
3137 upper_bound
= (intr
) ? (63) : (8);
3139 /* Prepare id list so that we can traverse id value. */
3140 id_list
= (intr
) ? (TREE_VALUE (intr
)) : (TREE_VALUE (excp
));
3142 /* 2. Check valid integer value for interrupt/exception. */
3147 /* Pick up each vector id value. */
3148 id
= TREE_VALUE (id_list
);
3149 /* Issue error if it is not a valid integer value. */
3150 if (TREE_CODE (id
) != INTEGER_CST
3151 || wi::ltu_p (id
, lower_bound
)
3152 || wi::gtu_p (id
, upper_bound
))
3153 error ("invalid id value for interrupt/exception attribute");
3155 /* Advance to next id. */
3156 id_list
= TREE_CHAIN (id_list
);
3161 /* Deal with reset. */
3165 unsigned int lower_bound
;
3166 unsigned int upper_bound
;
3168 /* Prepare id_list and identify id value so that
3169 we can check if total number of vectors is valid. */
3170 id_list
= TREE_VALUE (reset
);
3171 id
= TREE_VALUE (id_list
);
3173 /* The maximum numbers for user's interrupt is 64. */
3177 /* 3. Check valid integer value for reset. */
3178 if (TREE_CODE (id
) != INTEGER_CST
3179 || wi::ltu_p (id
, lower_bound
)
3180 || wi::gtu_p (id
, upper_bound
))
3181 error ("invalid id value for reset attribute");
3183 /* 4. Check valid function for nmi/warm. */
3184 nmi
= lookup_attribute ("nmi", func_attrs
);
3185 warm
= lookup_attribute ("warm", func_attrs
);
3187 if (nmi
!= NULL_TREE
)
3192 nmi_func_list
= TREE_VALUE (nmi
);
3193 nmi_func
= TREE_VALUE (nmi_func_list
);
3195 /* Issue error if it is not a valid nmi function. */
3196 if (TREE_CODE (nmi_func
) != IDENTIFIER_NODE
)
3197 error ("invalid nmi function for reset attribute");
3200 if (warm
!= NULL_TREE
)
3202 tree warm_func_list
;
3205 warm_func_list
= TREE_VALUE (warm
);
3206 warm_func
= TREE_VALUE (warm_func_list
);
3208 /* Issue error if it is not a valid warm function. */
3209 if (TREE_CODE (warm_func
) != IDENTIFIER_NODE
)
3210 error ("invalid warm function for reset attribute");
3215 /* No interrupt, exception, or reset attribute is set. */
3222 nds32_option_pragma_parse (tree args ATTRIBUTE_UNUSED
,
3223 tree pop_target ATTRIBUTE_UNUSED
)
3225 /* Currently, we do not parse any pragma target by ourself,
3226 so just simply return false. */
3231 nds32_option_override (void)
3233 /* After all the command options have been parsed,
3234 we shall deal with some flags for changing compiler settings. */
3236 /* At first, we check if we have to strictly
3237 set some flags based on ISA family. */
3240 /* Under V2 ISA, we need to strictly disable TARGET_V3PUSH. */
3241 target_flags
&= ~MASK_V3PUSH
;
3245 /* Under V3 ISA, currently nothing should be strictly set. */
3249 /* Under V3M ISA, we need to strictly enable TARGET_REDUCED_REGS. */
3250 target_flags
|= MASK_REDUCED_REGS
;
3251 /* Under V3M ISA, we need to strictly disable TARGET_PERF_EXT. */
3252 target_flags
&= ~MASK_PERF_EXT
;
3255 /* See if we are using reduced-set registers:
3256 $r0~$r5, $r6~$r10, $r15, $r28, $r29, $r30, $r31
3257 If so, we must forbid using $r11~$r14, $r16~$r27. */
3258 if (TARGET_REDUCED_REGS
)
3262 /* Prevent register allocator from
3263 choosing it as doing register allocation. */
3264 for (r
= 11; r
<= 14; r
++)
3265 fixed_regs
[r
] = call_used_regs
[r
] = 1;
3266 for (r
= 16; r
<= 27; r
++)
3267 fixed_regs
[r
] = call_used_regs
[r
] = 1;
3270 /* See if user explicitly would like to use fp-as-gp optimization.
3271 If so, we must prevent $fp from being allocated
3272 during register allocation. */
3273 if (TARGET_FORCE_FP_AS_GP
)
3274 fixed_regs
[FP_REGNUM
] = call_used_regs
[FP_REGNUM
] = 1;
3278 /* Under no 16 bit ISA, we need to strictly disable TARGET_V3PUSH. */
3279 target_flags
&= ~MASK_V3PUSH
;
3282 /* Currently, we don't support PIC code generation yet. */
3284 sorry ("not support -fpic");
3288 /* Miscellaneous Parameters. */
3291 nds32_init_builtins (void)
3293 tree pointer_type_node
= build_pointer_type (integer_type_node
);
3295 tree void_ftype_void
= build_function_type (void_type_node
,
3298 tree void_ftype_pint
= build_function_type_list (void_type_node
,
3302 tree int_ftype_int
= build_function_type_list (integer_type_node
,
3306 tree void_ftype_int_int
= build_function_type_list (void_type_node
,
3312 add_builtin_function ("__builtin_nds32_isync", void_ftype_pint
,
3313 NDS32_BUILTIN_ISYNC
,
3314 BUILT_IN_MD
, NULL
, NULL_TREE
);
3315 add_builtin_function ("__builtin_nds32_isb", void_ftype_void
,
3317 BUILT_IN_MD
, NULL
, NULL_TREE
);
3319 /* Register Transfer. */
3320 add_builtin_function ("__builtin_nds32_mfsr", int_ftype_int
,
3322 BUILT_IN_MD
, NULL
, NULL_TREE
);
3323 add_builtin_function ("__builtin_nds32_mfusr", int_ftype_int
,
3324 NDS32_BUILTIN_MFUSR
,
3325 BUILT_IN_MD
, NULL
, NULL_TREE
);
3326 add_builtin_function ("__builtin_nds32_mtsr", void_ftype_int_int
,
3328 BUILT_IN_MD
, NULL
, NULL_TREE
);
3329 add_builtin_function ("__builtin_nds32_mtusr", void_ftype_int_int
,
3330 NDS32_BUILTIN_MTUSR
,
3331 BUILT_IN_MD
, NULL
, NULL_TREE
);
3334 add_builtin_function ("__builtin_nds32_setgie_en", void_ftype_void
,
3335 NDS32_BUILTIN_SETGIE_EN
,
3336 BUILT_IN_MD
, NULL
, NULL_TREE
);
3337 add_builtin_function ("__builtin_nds32_setgie_dis", void_ftype_void
,
3338 NDS32_BUILTIN_SETGIE_DIS
,
3339 BUILT_IN_MD
, NULL
, NULL_TREE
);
3343 nds32_expand_builtin (tree exp
,
3345 rtx subtarget ATTRIBUTE_UNUSED
,
3346 enum machine_mode mode ATTRIBUTE_UNUSED
,
3347 int ignore ATTRIBUTE_UNUSED
)
3349 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
3351 int fcode
= DECL_FUNCTION_CODE (fndecl
);
3356 case NDS32_BUILTIN_ISYNC
:
3357 return nds32_expand_builtin_null_ftype_reg
3358 (CODE_FOR_unspec_volatile_isync
, exp
, target
);
3359 case NDS32_BUILTIN_ISB
:
3360 /* Since there are no result and operands for isb instruciton,
3361 we can simply emit this rtx. */
3362 emit_insn (gen_unspec_volatile_isb ());
3365 /* Register Transfer. */
3366 case NDS32_BUILTIN_MFSR
:
3367 return nds32_expand_builtin_reg_ftype_imm
3368 (CODE_FOR_unspec_volatile_mfsr
, exp
, target
);
3369 case NDS32_BUILTIN_MFUSR
:
3370 return nds32_expand_builtin_reg_ftype_imm
3371 (CODE_FOR_unspec_volatile_mfusr
, exp
, target
);
3372 case NDS32_BUILTIN_MTSR
:
3373 return nds32_expand_builtin_null_ftype_reg_imm
3374 (CODE_FOR_unspec_volatile_mtsr
, exp
, target
);
3375 case NDS32_BUILTIN_MTUSR
:
3376 return nds32_expand_builtin_null_ftype_reg_imm
3377 (CODE_FOR_unspec_volatile_mtusr
, exp
, target
);
3380 case NDS32_BUILTIN_SETGIE_EN
:
3381 /* Since there are no result and operands for setgie.e instruciton,
3382 we can simply emit this rtx. */
3383 emit_insn (gen_unspec_volatile_setgie_en ());
3385 case NDS32_BUILTIN_SETGIE_DIS
:
3386 /* Since there are no result and operands for setgie.d instruciton,
3387 we can simply emit this rtx. */
3388 emit_insn (gen_unspec_volatile_setgie_dis ());
3399 /* ------------------------------------------------------------------------ */
3401 /* PART 4: Implemet extern function definitions,
3402 the prototype is in nds32-protos.h. */
3404 /* Defining Data Structures for Per-function Information. */
3407 nds32_init_expanders (void)
3409 /* Arrange to initialize and mark the machine per-function status. */
3410 init_machine_status
= nds32_init_machine_status
;
3414 /* Register Usage. */
3416 /* -- How Values Fit in Registers. */
3419 nds32_hard_regno_nregs (int regno ATTRIBUTE_UNUSED
,
3420 enum machine_mode mode
)
3422 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
);
3426 nds32_hard_regno_mode_ok (int regno
, enum machine_mode mode
)
3428 /* Restrict double-word quantities to even register pairs. */
3429 if (HARD_REGNO_NREGS (regno
, mode
) == 1
3437 /* Register Classes. */
3440 nds32_regno_reg_class (int regno
)
3442 /* Refer to nds32.h for more register class details. */
3444 if (regno
>= 0 && regno
<= 7)
3446 else if (regno
>= 8 && regno
<= 11)
3448 else if (regno
>= 12 && regno
<= 14)
3450 else if (regno
== 15)
3452 else if (regno
>= 16 && regno
<= 19)
3454 else if (regno
>= 20 && regno
<= 31)
3456 else if (regno
== 32 || regno
== 33)
3463 /* Stack Layout and Calling Conventions. */
3465 /* -- Basic Stack Layout. */
3468 nds32_return_addr_rtx (int count
,
3469 rtx frameaddr ATTRIBUTE_UNUSED
)
3471 /* There is no way to determine the return address
3472 if frameaddr is the frame that has 'count' steps
3473 up from current frame. */
3477 /* If count == 0, it means we are at current frame,
3478 the return address is $r30 ($lp). */
3479 return get_hard_reg_initial_val (Pmode
, LP_REGNUM
);
3482 /* -- Eliminating Frame Pointer and Arg Pointer. */
3485 nds32_initial_elimination_offset (unsigned int from_reg
, unsigned int to_reg
)
3487 HOST_WIDE_INT offset
;
3489 /* Compute and setup stack frame size.
3490 The result will be in cfun->machine. */
3491 nds32_compute_stack_frame ();
3493 /* Remember to consider
3494 cfun->machine->callee_saved_area_padding_bytes
3495 when calculating offset. */
3496 if (from_reg
== ARG_POINTER_REGNUM
&& to_reg
== STACK_POINTER_REGNUM
)
3498 offset
= (cfun
->machine
->fp_size
3499 + cfun
->machine
->gp_size
3500 + cfun
->machine
->lp_size
3501 + cfun
->machine
->callee_saved_regs_size
3502 + cfun
->machine
->callee_saved_area_padding_bytes
3503 + cfun
->machine
->local_size
3504 + cfun
->machine
->out_args_size
);
3506 else if (from_reg
== ARG_POINTER_REGNUM
3507 && to_reg
== HARD_FRAME_POINTER_REGNUM
)
3511 else if (from_reg
== FRAME_POINTER_REGNUM
3512 && to_reg
== STACK_POINTER_REGNUM
)
3514 offset
= (cfun
->machine
->local_size
+ cfun
->machine
->out_args_size
);
3516 else if (from_reg
== FRAME_POINTER_REGNUM
3517 && to_reg
== HARD_FRAME_POINTER_REGNUM
)
3519 offset
= (-1) * (cfun
->machine
->fp_size
3520 + cfun
->machine
->gp_size
3521 + cfun
->machine
->lp_size
3522 + cfun
->machine
->callee_saved_regs_size
3523 + cfun
->machine
->callee_saved_area_padding_bytes
);
3533 /* -- Passing Arguments in Registers. */
3536 nds32_init_cumulative_args (CUMULATIVE_ARGS
*cum
,
3537 tree fntype ATTRIBUTE_UNUSED
,
3538 rtx libname ATTRIBUTE_UNUSED
,
3539 tree fndecl ATTRIBUTE_UNUSED
,
3540 int n_named_args ATTRIBUTE_UNUSED
)
3542 /* Initial available registers
3543 (in offset, corresponding to NDS32_GPR_ARG_FIRST_REGNUM)
3544 for passing arguments. */
3545 cum
->reg_offset
= 0;
3548 /* -- Function Entry and Exit. */
3550 /* Function for normal multiple push prologue. */
3552 nds32_expand_prologue (void)
3560 rtx fp_adjust_insn
, sp_adjust_insn
;
3562 /* Before computing everything for stack frame size,
3563 we check if it is still worth to use fp_as_gp optimization.
3564 If it is, the 'df_regs_ever_live_p (FP_REGNUM)' will be set
3565 so that $fp will be saved on stack. */
3566 cfun
->machine
->fp_as_gp_p
= nds32_fp_as_gp_check_available ();
3568 /* Compute and setup stack frame size.
3569 The result will be in cfun->machine. */
3570 nds32_compute_stack_frame ();
3572 /* If the function is 'naked',
3573 we do not have to generate prologue code fragment. */
3574 if (cfun
->machine
->naked_p
)
3577 /* Get callee_first_regno and callee_last_regno. */
3578 Rb
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_first_regno
);
3579 Re
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_last_regno
);
3581 /* push_insn = gen_stack_push_multiple(first_regno, last_regno),
3582 the pattern 'stack_push_multiple' is implemented in nds32.md.
3583 For En4 field, we have to calculate its constant value.
3584 Refer to Andes ISA for more information. */
3586 if (cfun
->machine
->fp_size
)
3588 if (cfun
->machine
->gp_size
)
3590 if (cfun
->machine
->lp_size
)
3593 /* If $fp, $gp, $lp, and all callee-save registers are NOT required
3594 to be saved, we don't have to create multiple push instruction.
3595 Otherwise, a multiple push instruction is needed. */
3596 if (!(REGNO (Rb
) == SP_REGNUM
&& REGNO (Re
) == SP_REGNUM
&& en4_const
== 0))
3598 /* Create multiple push instruction rtx. */
3599 push_insn
= nds32_gen_stack_push_multiple (Rb
, Re
, GEN_INT (en4_const
));
3600 /* Emit rtx into instructions list and receive INSN rtx form. */
3601 push_insn
= emit_insn (push_insn
);
3603 /* The insn rtx 'push_insn' will change frame layout.
3604 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3605 generate CFI (Call Frame Information) stuff. */
3606 RTX_FRAME_RELATED_P (push_insn
) = 1;
3609 /* Check frame_pointer_needed to see
3610 if we shall emit fp adjustment instruction. */
3611 if (frame_pointer_needed
)
3613 /* adjust $fp = $sp + ($fp size) + ($gp size) + ($lp size)
3614 + (4 * callee-saved-registers)
3615 Note: No need to adjust
3616 cfun->machine->callee_saved_area_padding_bytes,
3617 because, at this point, stack pointer is just
3618 at the position after push instruction. */
3619 fp_adjust
= cfun
->machine
->fp_size
3620 + cfun
->machine
->gp_size
3621 + cfun
->machine
->lp_size
3622 + cfun
->machine
->callee_saved_regs_size
;
3623 fp_adjust_insn
= gen_addsi3 (hard_frame_pointer_rtx
,
3625 GEN_INT (fp_adjust
));
3626 /* Emit rtx into instructions list and receive INSN rtx form. */
3627 fp_adjust_insn
= emit_insn (fp_adjust_insn
);
3630 /* Adjust $sp = $sp - local_size - out_args_size
3631 - callee_saved_area_padding_bytes. */
3632 sp_adjust
= cfun
->machine
->local_size
3633 + cfun
->machine
->out_args_size
3634 + cfun
->machine
->callee_saved_area_padding_bytes
;
3635 /* sp_adjust value may be out of range of the addi instruction,
3636 create alternative add behavior with TA_REGNUM if necessary,
3637 using NEGATIVE value to tell that we are decreasing address. */
3638 sp_adjust
= nds32_force_addi_stack_int ( (-1) * sp_adjust
);
3641 /* Generate sp adjustment instruction if and only if sp_adjust != 0. */
3642 sp_adjust_insn
= gen_addsi3 (stack_pointer_rtx
,
3644 GEN_INT (-1 * sp_adjust
));
3645 /* Emit rtx into instructions list and receive INSN rtx form. */
3646 sp_adjust_insn
= emit_insn (sp_adjust_insn
);
3648 /* The insn rtx 'sp_adjust_insn' will change frame layout.
3649 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3650 generate CFI (Call Frame Information) stuff. */
3651 RTX_FRAME_RELATED_P (sp_adjust_insn
) = 1;
3654 /* Prevent the instruction scheduler from
3655 moving instructions across the boundary. */
3656 emit_insn (gen_blockage ());
3659 /* Function for normal multiple pop epilogue. */
3661 nds32_expand_epilogue (void)
3670 /* Compute and setup stack frame size.
3671 The result will be in cfun->machine. */
3672 nds32_compute_stack_frame ();
3674 /* Prevent the instruction scheduler from
3675 moving instructions across the boundary. */
3676 emit_insn (gen_blockage ());
3678 /* If the function is 'naked', we do not have to generate
3679 epilogue code fragment BUT 'ret' instruction. */
3680 if (cfun
->machine
->naked_p
)
3682 /* Generate return instruction by using
3683 unspec_volatile_func_return pattern.
3684 Make sure this instruction is after gen_blockage().
3685 NOTE that $lp will become 'live'
3686 after this instruction has been emitted. */
3687 emit_insn (gen_unspec_volatile_func_return ());
3691 if (frame_pointer_needed
)
3693 /* adjust $sp = $fp - ($fp size) - ($gp size) - ($lp size)
3694 - (4 * callee-saved-registers)
3695 Note: No need to adjust
3696 cfun->machine->callee_saved_area_padding_bytes,
3697 because we want to adjust stack pointer
3698 to the position for pop instruction. */
3699 sp_adjust
= cfun
->machine
->fp_size
3700 + cfun
->machine
->gp_size
3701 + cfun
->machine
->lp_size
3702 + cfun
->machine
->callee_saved_regs_size
;
3703 sp_adjust_insn
= gen_addsi3 (stack_pointer_rtx
,
3704 hard_frame_pointer_rtx
,
3705 GEN_INT (-1 * sp_adjust
));
3706 /* Emit rtx into instructions list and receive INSN rtx form. */
3707 sp_adjust_insn
= emit_insn (sp_adjust_insn
);
3711 /* If frame pointer is NOT needed,
3712 we cannot calculate the sp adjustment from frame pointer.
3713 Instead, we calculate the adjustment by local_size,
3714 out_args_size, and callee_saved_area_padding_bytes.
3715 Notice that such sp adjustment value may be out of range,
3716 so we have to deal with it as well. */
3718 /* Adjust $sp = $sp + local_size + out_args_size
3719 + callee_saved_area_padding_bytes. */
3720 sp_adjust
= cfun
->machine
->local_size
3721 + cfun
->machine
->out_args_size
3722 + cfun
->machine
->callee_saved_area_padding_bytes
;
3723 /* sp_adjust value may be out of range of the addi instruction,
3724 create alternative add behavior with TA_REGNUM if necessary,
3725 using POSITIVE value to tell that we are increasing address. */
3726 sp_adjust
= nds32_force_addi_stack_int (sp_adjust
);
3729 /* Generate sp adjustment instruction
3730 if and only if sp_adjust != 0. */
3731 sp_adjust_insn
= gen_addsi3 (stack_pointer_rtx
,
3733 GEN_INT (sp_adjust
));
3734 /* Emit rtx into instructions list and receive INSN rtx form. */
3735 sp_adjust_insn
= emit_insn (sp_adjust_insn
);
3739 /* Get callee_first_regno and callee_last_regno. */
3740 Rb
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_first_regno
);
3741 Re
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_last_regno
);
3743 /* pop_insn = gen_stack_pop_multiple(first_regno, last_regno),
3744 the pattern 'stack_pop_multiple' is implementad in nds32.md.
3745 For En4 field, we have to calculate its constant value.
3746 Refer to Andes ISA for more information. */
3748 if (cfun
->machine
->fp_size
)
3750 if (cfun
->machine
->gp_size
)
3752 if (cfun
->machine
->lp_size
)
3755 /* If $fp, $gp, $lp, and all callee-save registers are NOT required
3756 to be saved, we don't have to create multiple pop instruction.
3757 Otherwise, a multiple pop instruction is needed. */
3758 if (!(REGNO (Rb
) == SP_REGNUM
&& REGNO (Re
) == SP_REGNUM
&& en4_const
== 0))
3760 /* Create multiple pop instruction rtx. */
3761 pop_insn
= nds32_gen_stack_pop_multiple (Rb
, Re
, GEN_INT (en4_const
));
3762 /* Emit pop instruction. */
3763 emit_insn (pop_insn
);
3766 /* Generate return instruction by using
3767 unspec_volatile_func_return pattern. */
3768 emit_insn (gen_unspec_volatile_func_return ());
3771 /* Function for v3push prologue. */
3773 nds32_expand_prologue_v3push (void)
3780 rtx fp_adjust_insn
, sp_adjust_insn
;
3782 /* Before computing everything for stack frame size,
3783 we check if it is still worth to use fp_as_gp optimization.
3784 If it is, the 'df_regs_ever_live_p (FP_REGNUM)' will be set
3785 so that $fp will be saved on stack. */
3786 cfun
->machine
->fp_as_gp_p
= nds32_fp_as_gp_check_available ();
3788 /* Compute and setup stack frame size.
3789 The result will be in cfun->machine. */
3790 nds32_compute_stack_frame ();
3792 /* If the function is 'naked',
3793 we do not have to generate prologue code fragment. */
3794 if (cfun
->machine
->naked_p
)
3797 /* Get callee_first_regno and callee_last_regno. */
3798 Rb
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_first_regno
);
3799 Re
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_last_regno
);
3801 /* Calculate sp_adjust first to test if 'push25 Re,imm8u' is available,
3802 where imm8u has to be 8-byte alignment. */
3803 sp_adjust
= cfun
->machine
->local_size
3804 + cfun
->machine
->out_args_size
3805 + cfun
->machine
->callee_saved_area_padding_bytes
;
3807 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust
))
3808 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust
))
3810 /* We can use 'push25 Re,imm8u'. */
3812 /* push_insn = gen_stack_v3push(last_regno, sp_adjust),
3813 the pattern 'stack_v3push' is implemented in nds32.md.
3814 The (const_int 14) means v3push always push { $fp $gp $lp }. */
3815 push_insn
= nds32_gen_stack_v3push (Rb
, Re
,
3816 GEN_INT (14), GEN_INT (sp_adjust
));
3817 /* emit rtx into instructions list and receive INSN rtx form */
3818 push_insn
= emit_insn (push_insn
);
3820 /* The insn rtx 'push_insn' will change frame layout.
3821 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3822 generate CFI (Call Frame Information) stuff. */
3823 RTX_FRAME_RELATED_P (push_insn
) = 1;
3825 /* Check frame_pointer_needed to see
3826 if we shall emit fp adjustment instruction. */
3827 if (frame_pointer_needed
)
3829 /* adjust $fp = $sp + 4 ($fp size)
3832 + (4 * n) (callee-saved registers)
3833 + sp_adjust ('push25 Re,imm8u')
3834 Note: Since we use 'push25 Re,imm8u',
3835 the position of stack pointer is further
3836 changed after push instruction.
3837 Hence, we need to take sp_adjust value
3838 into consideration. */
3839 fp_adjust
= cfun
->machine
->fp_size
3840 + cfun
->machine
->gp_size
3841 + cfun
->machine
->lp_size
3842 + cfun
->machine
->callee_saved_regs_size
3844 fp_adjust_insn
= gen_addsi3 (hard_frame_pointer_rtx
,
3846 GEN_INT (fp_adjust
));
3847 /* Emit rtx into instructions list and receive INSN rtx form. */
3848 fp_adjust_insn
= emit_insn (fp_adjust_insn
);
3853 /* We have to use 'push25 Re,0' and
3854 expand one more instruction to adjust $sp later. */
3856 /* push_insn = gen_stack_v3push(last_regno, sp_adjust),
3857 the pattern 'stack_v3push' is implemented in nds32.md.
3858 The (const_int 14) means v3push always push { $fp $gp $lp }. */
3859 push_insn
= nds32_gen_stack_v3push (Rb
, Re
,
3860 GEN_INT (14), GEN_INT (0));
3861 /* Emit rtx into instructions list and receive INSN rtx form. */
3862 push_insn
= emit_insn (push_insn
);
3864 /* The insn rtx 'push_insn' will change frame layout.
3865 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3866 generate CFI (Call Frame Information) stuff. */
3867 RTX_FRAME_RELATED_P (push_insn
) = 1;
3869 /* Check frame_pointer_needed to see
3870 if we shall emit fp adjustment instruction. */
3871 if (frame_pointer_needed
)
3873 /* adjust $fp = $sp + 4 ($fp size)
3876 + (4 * n) (callee-saved registers)
3877 Note: Since we use 'push25 Re,0',
3878 the stack pointer is just at the position
3879 after push instruction.
3880 No need to take sp_adjust into consideration. */
3881 fp_adjust
= cfun
->machine
->fp_size
3882 + cfun
->machine
->gp_size
3883 + cfun
->machine
->lp_size
3884 + cfun
->machine
->callee_saved_regs_size
;
3885 fp_adjust_insn
= gen_addsi3 (hard_frame_pointer_rtx
,
3887 GEN_INT (fp_adjust
));
3888 /* Emit rtx into instructions list and receive INSN rtx form. */
3889 fp_adjust_insn
= emit_insn (fp_adjust_insn
);
3892 /* Because we use 'push25 Re,0',
3893 we need to expand one more instruction to adjust $sp.
3894 However, sp_adjust value may be out of range of the addi instruction,
3895 create alternative add behavior with TA_REGNUM if necessary,
3896 using NEGATIVE value to tell that we are decreasing address. */
3897 sp_adjust
= nds32_force_addi_stack_int ( (-1) * sp_adjust
);
3900 /* Generate sp adjustment instruction
3901 if and only if sp_adjust != 0. */
3902 sp_adjust_insn
= gen_addsi3 (stack_pointer_rtx
,
3904 GEN_INT (-1 * sp_adjust
));
3905 /* Emit rtx into instructions list and receive INSN rtx form. */
3906 sp_adjust_insn
= emit_insn (sp_adjust_insn
);
3908 /* The insn rtx 'sp_adjust_insn' will change frame layout.
3909 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3910 generate CFI (Call Frame Information) stuff. */
3911 RTX_FRAME_RELATED_P (sp_adjust_insn
) = 1;
3915 /* Prevent the instruction scheduler from
3916 moving instructions across the boundary. */
3917 emit_insn (gen_blockage ());
3920 /* Function for v3pop epilogue. */
3922 nds32_expand_epilogue_v3pop (void)
3930 /* Compute and setup stack frame size.
3931 The result will be in cfun->machine. */
3932 nds32_compute_stack_frame ();
3934 /* Prevent the instruction scheduler from
3935 moving instructions across the boundary. */
3936 emit_insn (gen_blockage ());
3938 /* If the function is 'naked', we do not have to generate
3939 epilogue code fragment BUT 'ret' instruction. */
3940 if (cfun
->machine
->naked_p
)
3942 /* Generate return instruction by using
3943 unspec_volatile_func_return pattern.
3944 Make sure this instruction is after gen_blockage().
3945 NOTE that $lp will become 'live'
3946 after this instruction has been emitted. */
3947 emit_insn (gen_unspec_volatile_func_return ());
3951 /* Get callee_first_regno and callee_last_regno. */
3952 Rb
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_first_regno
);
3953 Re
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_last_regno
);
3955 /* Calculate sp_adjust first to test if 'pop25 Re,imm8u' is available,
3956 where imm8u has to be 8-byte alignment. */
3957 sp_adjust
= cfun
->machine
->local_size
3958 + cfun
->machine
->out_args_size
3959 + cfun
->machine
->callee_saved_area_padding_bytes
;
3961 /* We have to consider alloca issue as well.
3962 If the function does call alloca(), the stack pointer is not fixed.
3963 In that case, we cannot use 'pop25 Re,imm8u' directly.
3964 We have to caculate stack pointer from frame pointer
3965 and then use 'pop25 Re,0'.
3966 Of course, the frame_pointer_needed should be nonzero
3967 if the function calls alloca(). */
3968 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust
))
3969 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust
)
3970 && !cfun
->calls_alloca
)
3972 /* We can use 'pop25 Re,imm8u'. */
3974 /* pop_insn = gen_stack_v3pop(last_regno, sp_adjust),
3975 the pattern 'stack_v3pop' is implementad in nds32.md.
3976 The (const_int 14) means v3pop always pop { $fp $gp $lp }. */
3977 pop_insn
= nds32_gen_stack_v3pop (Rb
, Re
,
3978 GEN_INT (14), GEN_INT (sp_adjust
));
3980 /* Emit pop instruction. */
3981 emit_insn (pop_insn
);
3985 /* We have to use 'pop25 Re,0', and prior to it,
3986 we must expand one more instruction to adjust $sp. */
3988 if (frame_pointer_needed
)
3990 /* adjust $sp = $fp - 4 ($fp size)
3993 - (4 * n) (callee-saved registers)
3994 Note: No need to adjust
3995 cfun->machine->callee_saved_area_padding_bytes,
3996 because we want to adjust stack pointer
3997 to the position for pop instruction. */
3998 sp_adjust
= cfun
->machine
->fp_size
3999 + cfun
->machine
->gp_size
4000 + cfun
->machine
->lp_size
4001 + cfun
->machine
->callee_saved_regs_size
;
4002 sp_adjust_insn
= gen_addsi3 (stack_pointer_rtx
,
4003 hard_frame_pointer_rtx
,
4004 GEN_INT (-1 * sp_adjust
));
4005 /* Emit rtx into instructions list and receive INSN rtx form. */
4006 sp_adjust_insn
= emit_insn (sp_adjust_insn
);
4010 /* If frame pointer is NOT needed,
4011 we cannot calculate the sp adjustment from frame pointer.
4012 Instead, we calculate the adjustment by local_size,
4013 out_args_size, and callee_saved_area_padding_bytes.
4014 Notice that such sp adjustment value may be out of range,
4015 so we have to deal with it as well. */
4017 /* Adjust $sp = $sp + local_size + out_args_size
4018 + callee_saved_area_padding_bytes. */
4019 sp_adjust
= cfun
->machine
->local_size
4020 + cfun
->machine
->out_args_size
4021 + cfun
->machine
->callee_saved_area_padding_bytes
;
4022 /* sp_adjust value may be out of range of the addi instruction,
4023 create alternative add behavior with TA_REGNUM if necessary,
4024 using POSITIVE value to tell that we are increasing address. */
4025 sp_adjust
= nds32_force_addi_stack_int (sp_adjust
);
4028 /* Generate sp adjustment instruction
4029 if and only if sp_adjust != 0. */
4030 sp_adjust_insn
= gen_addsi3 (stack_pointer_rtx
,
4032 GEN_INT (sp_adjust
));
4033 /* Emit rtx into instructions list and receive INSN rtx form. */
4034 sp_adjust_insn
= emit_insn (sp_adjust_insn
);
4038 /* pop_insn = gen_stack_v3pop(last_regno, sp_adjust),
4039 the pattern 'stack_v3pop' is implementad in nds32.md. */
4040 /* The (const_int 14) means v3pop always pop { $fp $gp $lp }. */
4041 pop_insn
= nds32_gen_stack_v3pop (Rb
, Re
,
4042 GEN_INT (14), GEN_INT (0));
4044 /* Emit pop instruction. */
4045 emit_insn (pop_insn
);
4049 /* ------------------------------------------------------------------------ */
4051 /* Function to test 333-form for load/store instructions.
4052 This is auxiliary extern function for auxiliary macro in nds32.h.
4053 Because it is a little complicated, we use function instead of macro. */
4055 nds32_ls_333_p (rtx rt
, rtx ra
, rtx imm
, enum machine_mode mode
)
4057 if (REGNO_REG_CLASS (REGNO (rt
)) == LOW_REGS
4058 && REGNO_REG_CLASS (REGNO (ra
)) == LOW_REGS
)
4060 if (GET_MODE_SIZE (mode
) == 4)
4061 return satisfies_constraint_Iu05 (imm
);
4063 if (GET_MODE_SIZE (mode
) == 2)
4064 return satisfies_constraint_Iu04 (imm
);
4066 if (GET_MODE_SIZE (mode
) == 1)
4067 return satisfies_constraint_Iu03 (imm
);
4074 /* Functions to expand load_multiple and store_multiple.
4075 They are auxiliary extern functions to help create rtx template.
4076 Check nds32-multiple.md file for the patterns. */
4078 nds32_expand_load_multiple (int base_regno
, int count
,
4079 rtx base_addr
, rtx basemem
)
4084 rtx new_addr
, mem
, reg
;
4086 /* Create the pattern that is presented in nds32-multiple.md. */
4088 result
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (count
));
4090 for (par_index
= 0; par_index
< count
; par_index
++)
4092 offset
= par_index
* 4;
4093 /* 4-byte for loading data to each register. */
4094 new_addr
= plus_constant (Pmode
, base_addr
, offset
);
4095 mem
= adjust_automodify_address_nv (basemem
, SImode
,
4097 reg
= gen_rtx_REG (SImode
, base_regno
+ par_index
);
4099 XVECEXP (result
, 0, par_index
) = gen_rtx_SET (VOIDmode
, reg
, mem
);
4106 nds32_expand_store_multiple (int base_regno
, int count
,
4107 rtx base_addr
, rtx basemem
)
4112 rtx new_addr
, mem
, reg
;
4114 /* Create the pattern that is presented in nds32-multiple.md. */
4116 result
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (count
));
4118 for (par_index
= 0; par_index
< count
; par_index
++)
4120 offset
= par_index
* 4;
4121 /* 4-byte for storing data to memory. */
4122 new_addr
= plus_constant (Pmode
, base_addr
, offset
);
4123 mem
= adjust_automodify_address_nv (basemem
, SImode
,
4125 reg
= gen_rtx_REG (SImode
, base_regno
+ par_index
);
4127 XVECEXP (result
, 0, par_index
) = gen_rtx_SET (VOIDmode
, mem
, reg
);
4133 /* Function to move block memory content by
4134 using load_multiple and store_multiple.
4135 This is auxiliary extern function to help create rtx template.
4136 Check nds32-multiple.md file for the patterns. */
4138 nds32_expand_movmemqi (rtx dstmem
, rtx srcmem
, rtx total_bytes
, rtx alignment
)
4140 HOST_WIDE_INT in_words
, out_words
;
4141 rtx dst_base_reg
, src_base_reg
;
4144 /* Because reduced-set regsiters has few registers
4145 (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31'
4146 cannot be used for register allocation),
4147 using 8 registers (32 bytes) for moving memory block
4148 may easily consume all of them.
4149 It makes register allocation/spilling hard to work.
4150 So we only allow maximum=4 registers (16 bytes) for
4151 moving memory block under reduced-set registers. */
4152 if (TARGET_REDUCED_REGS
)
4157 /* 1. Total_bytes is integer for sure.
4158 2. Alignment is integer for sure.
4159 3. Maximum 4 or 8 registers, 4 * 4 = 16 bytes, 8 * 4 = 32 bytes.
4160 4. Requires (n * 4) block size.
4161 5. Requires 4-byte alignment. */
4162 if (GET_CODE (total_bytes
) != CONST_INT
4163 || GET_CODE (alignment
) != CONST_INT
4164 || INTVAL (total_bytes
) > maximum_bytes
4165 || INTVAL (total_bytes
) & 3
4166 || INTVAL (alignment
) & 3)
4169 dst_base_reg
= copy_to_mode_reg (SImode
, XEXP (dstmem
, 0));
4170 src_base_reg
= copy_to_mode_reg (SImode
, XEXP (srcmem
, 0));
4172 out_words
= in_words
= INTVAL (total_bytes
) / UNITS_PER_WORD
;
4174 emit_insn (nds32_expand_load_multiple (0, in_words
, src_base_reg
, srcmem
));
4175 emit_insn (nds32_expand_store_multiple (0, out_words
, dst_base_reg
, dstmem
));
4177 /* Successfully create patterns, return 1. */
4181 /* Function to check whether the OP is a valid load/store operation.
4182 This is a helper function for the predicates:
4183 'nds32_load_multiple_operation' and 'nds32_store_multiple_operation'
4184 in predicates.md file.
4186 The OP is supposed to be a parallel rtx.
4187 For each element within this parallel rtx:
4188 (set (reg) (mem addr)) is the form for load operation.
4189 (set (mem addr) (reg)) is the form for store operation.
4190 We have to extract reg and mem of every element and
4191 check if the information is valid for multiple load/store operation. */
4193 nds32_valid_multiple_load_store (rtx op
, bool load_p
)
4196 int first_elt_regno
;
4199 /* Get the counts of elements in the parallel rtx. */
4200 count
= XVECLEN (op
, 0);
4201 /* Pick up the first element. */
4202 elt
= XVECEXP (op
, 0, 0);
4204 /* Perform some quick check for the first element in the parallel rtx. */
4205 if (GET_CODE (elt
) != SET
4210 /* Pick up regno of first element for further detail checking.
4211 Note that the form is different between load and store operation. */
4214 if (GET_CODE (SET_DEST (elt
)) != REG
4215 || GET_CODE (SET_SRC (elt
)) != MEM
)
4218 first_elt_regno
= REGNO (SET_DEST (elt
));
4222 if (GET_CODE (SET_SRC (elt
)) != REG
4223 || GET_CODE (SET_DEST (elt
)) != MEM
)
4226 first_elt_regno
= REGNO (SET_SRC (elt
));
4229 /* Perform detail check for each element.
4230 Refer to nds32-multiple.md for more information
4231 about following checking.
4232 The starting element of parallel rtx is index 0. */
4233 if (!nds32_consecutive_registers_load_store_p (op
, load_p
, 0,
4238 /* Pass all test, this is a valid rtx. */
4242 /* Function to check whether the OP is a valid stack push/pop operation.
4243 For a valid stack operation, it must satisfy following conditions:
4244 1. Consecutive registers push/pop operations.
4245 2. Valid $fp/$gp/$lp push/pop operations.
4246 3. The last element must be stack adjustment rtx.
4247 See the prologue/epilogue implementation for details. */
4249 nds32_valid_stack_push_pop (rtx op
, bool push_p
)
4260 /* Get the counts of elements in the parallel rtx. */
4261 total_count
= XVECLEN (op
, 0);
4263 /* Perform some quick check for that every element should be 'set'. */
4264 for (index
= 0; index
< total_count
; index
++)
4266 elt
= XVECEXP (op
, 0, index
);
4267 if (GET_CODE (elt
) != SET
)
4271 /* For push operation, the parallel rtx looks like:
4272 (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
4274 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
4277 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
4279 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
4281 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
4283 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
4285 (set (reg:SI SP_REGNUM)
4286 (plus (reg:SI SP_REGNUM) (const_int -32)))])
4288 For pop operation, the parallel rtx looks like:
4289 (parallel [(set (reg:SI Rb)
4290 (mem (reg:SI SP_REGNUM)))
4292 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
4295 (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
4296 (set (reg:SI FP_REGNUM)
4297 (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
4298 (set (reg:SI GP_REGNUM)
4299 (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
4300 (set (reg:SI LP_REGNUM)
4301 (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
4302 (set (reg:SI SP_REGNUM)
4303 (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
4305 /* 1. Consecutive registers push/pop operations.
4306 We need to calculate how many registers should be consecutive.
4307 The $sp adjustment rtx, $fp push rtx, $gp push rtx,
4308 and $lp push rtx are excluded. */
4310 /* Exclude last $sp adjustment rtx. */
4311 rest_count
= total_count
- 1;
4312 /* Exclude $fp, $gp, and $lp if they are in the parallel rtx. */
4313 if (cfun
->machine
->fp_size
)
4315 if (cfun
->machine
->gp_size
)
4317 if (cfun
->machine
->lp_size
)
4322 elt
= XVECEXP (op
, 0, 0);
4323 /* Pick up register element. */
4324 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
4325 first_regno
= REGNO (elt_reg
);
4327 /* The 'push' operation is a kind of store operation.
4328 The 'pop' operation is a kind of load operation.
4329 Pass corresponding false/true as second argument (bool load_p).
4330 The par_index is supposed to start with index 0. */
4331 if (!nds32_consecutive_registers_load_store_p (op
,
4332 !push_p
? true : false,
4339 /* 2. Valid $fp/$gp/$lp push/pop operations.
4340 Remember to set start index for checking them. */
4342 /* The rest_count is the start index for checking $fp/$gp/$lp. */
4344 /* If index < 0, this parallel rtx is definitely
4345 not a valid stack push/pop operation. */
4349 /* Check $fp/$gp/$lp one by one.
4350 We use 'push_p' to pick up reg rtx and mem rtx. */
4351 if (cfun
->machine
->fp_size
)
4353 elt
= XVECEXP (op
, 0, index
);
4354 elt_mem
= push_p
? SET_DEST (elt
) : SET_SRC (elt
);
4355 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
4358 if (GET_CODE (elt_mem
) != MEM
4359 || GET_CODE (elt_reg
) != REG
4360 || REGNO (elt_reg
) != FP_REGNUM
)
4363 if (cfun
->machine
->gp_size
)
4365 elt
= XVECEXP (op
, 0, index
);
4366 elt_mem
= push_p
? SET_DEST (elt
) : SET_SRC (elt
);
4367 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
4370 if (GET_CODE (elt_mem
) != MEM
4371 || GET_CODE (elt_reg
) != REG
4372 || REGNO (elt_reg
) != GP_REGNUM
)
4375 if (cfun
->machine
->lp_size
)
4377 elt
= XVECEXP (op
, 0, index
);
4378 elt_mem
= push_p
? SET_DEST (elt
) : SET_SRC (elt
);
4379 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
4382 if (GET_CODE (elt_mem
) != MEM
4383 || GET_CODE (elt_reg
) != REG
4384 || REGNO (elt_reg
) != LP_REGNUM
)
4388 /* 3. The last element must be stack adjustment rtx.
4389 Its form of rtx should be:
4390 (set (reg:SI SP_REGNUM)
4391 (plus (reg:SI SP_REGNUM) (const_int X)))
4392 The X could be positive or negative value. */
4394 /* Pick up the last element. */
4395 elt
= XVECEXP (op
, 0, total_count
- 1);
4397 /* Extract its destination and source rtx. */
4398 elt_reg
= SET_DEST (elt
);
4399 elt_plus
= SET_SRC (elt
);
4401 /* Check this is (set (stack_reg) (plus stack_reg const)) pattern. */
4402 if (GET_CODE (elt_reg
) != REG
4403 || GET_CODE (elt_plus
) != PLUS
4404 || REGNO (elt_reg
) != SP_REGNUM
)
4407 /* Pass all test, this is a valid rtx. */
4411 /* Computing the Length of an Insn.
4412 Modifies the length assigned to instruction INSN.
4413 LEN is the initially computed length of the insn. */
4415 nds32_adjust_insn_length (rtx insn
, int length
)
4419 switch (recog_memoized (insn
))
4421 case CODE_FOR_move_df
:
4422 case CODE_FOR_move_di
:
4423 /* Adjust length of movd44 to 2. */
4424 src
= XEXP (PATTERN (insn
), 1);
4425 dst
= XEXP (PATTERN (insn
), 0);
4429 && (REGNO (src
) % 2) == 0
4430 && (REGNO (dst
) % 2) == 0)
4442 /* Function to check if 'bclr' instruction can be used with IVAL. */
4444 nds32_can_use_bclr_p (int ival
)
4448 /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit,
4449 it means the original ival has only one 0-bit,
4450 So it is ok to perform 'bclr' operation. */
4452 one_bit_count
= popcount_hwi ((unsigned HOST_WIDE_INT
) (~ival
));
4454 /* 'bclr' is a performance extension instruction. */
4455 return (TARGET_PERF_EXT
&& (one_bit_count
== 1));
4458 /* Function to check if 'bset' instruction can be used with IVAL. */
4460 nds32_can_use_bset_p (int ival
)
4464 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
4465 it is ok to perform 'bset' operation. */
4467 one_bit_count
= popcount_hwi ((unsigned HOST_WIDE_INT
) (ival
));
4469 /* 'bset' is a performance extension instruction. */
4470 return (TARGET_PERF_EXT
&& (one_bit_count
== 1));
4473 /* Function to check if 'btgl' instruction can be used with IVAL. */
4475 nds32_can_use_btgl_p (int ival
)
4479 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
4480 it is ok to perform 'btgl' operation. */
4482 one_bit_count
= popcount_hwi ((unsigned HOST_WIDE_INT
) (ival
));
4484 /* 'btgl' is a performance extension instruction. */
4485 return (TARGET_PERF_EXT
&& (one_bit_count
== 1));
4488 /* Function to check if 'bitci' instruction can be used with IVAL. */
4490 nds32_can_use_bitci_p (int ival
)
4492 /* If we are using V3 ISA, we have 'bitci' instruction.
4493 Try to see if we can present 'andi' semantic with
4494 such 'bit-clear-immediate' operation.
4495 For example, 'andi $r0,$r0,0xfffffffc' can be
4496 presented with 'bitci $r0,$r0,3'. */
4497 return (TARGET_ISA_V3
4499 && satisfies_constraint_Iu15 (gen_int_mode (~ival
, SImode
)));
4503 /* Return true if is load/store with SYMBOL_REF addressing mode
4504 and memory mode is SImode. */
4506 nds32_symbol_load_store_p (rtx insn
)
4508 rtx mem_src
= NULL_RTX
;
4510 switch (get_attr_type (insn
))
4513 mem_src
= SET_SRC (PATTERN (insn
));
4516 mem_src
= SET_DEST (PATTERN (insn
));
4522 /* Find load/store insn with addressing mode is SYMBOL_REF. */
4523 if (mem_src
!= NULL_RTX
)
4525 if ((GET_CODE (mem_src
) == ZERO_EXTEND
)
4526 || (GET_CODE (mem_src
) == SIGN_EXTEND
))
4527 mem_src
= XEXP (mem_src
, 0);
4529 if ((GET_CODE (XEXP (mem_src
, 0)) == SYMBOL_REF
)
4530 || (GET_CODE (XEXP (mem_src
, 0)) == LO_SUM
))
4537 /* Function to determine whether it is worth to do fp_as_gp optimization.
4538 Return 0: It is NOT worth to do fp_as_gp optimization.
4539 Return 1: It is APPROXIMATELY worth to do fp_as_gp optimization.
4540 Note that if it is worth to do fp_as_gp optimization,
4541 we MUST set FP_REGNUM ever live in this function. */
4543 nds32_fp_as_gp_check_available (void)
4545 /* If there exists ANY of following conditions,
4546 we DO NOT perform fp_as_gp optimization:
4547 1. TARGET_FORBID_FP_AS_GP is set
4548 regardless of the TARGET_FORCE_FP_AS_GP.
4549 2. User explicitly uses 'naked' attribute.
4550 3. Not optimize for size.
4551 4. Need frame pointer.
4552 5. If $fp is already required to be saved,
4553 it means $fp is already choosen by register allocator.
4554 Thus we better not to use it for fp_as_gp optimization.
4555 6. This function is a vararg function.
4556 DO NOT apply fp_as_gp optimization on this function
4557 because it may change and break stack frame.
4558 7. The epilogue is empty.
4559 This happens when the function uses exit()
4560 or its attribute is no_return.
4561 In that case, compiler will not expand epilogue
4562 so that we have no chance to output .omit_fp_end directive. */
4563 if (TARGET_FORBID_FP_AS_GP
4564 || lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl
))
4566 || frame_pointer_needed
4567 || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM
)
4568 || (cfun
->stdarg
== 1)
4569 || (find_fallthru_edge (EXIT_BLOCK_PTR_FOR_FN (cfun
)->preds
) == NULL
))
4572 /* Now we can check the possibility of using fp_as_gp optimization. */
4573 if (TARGET_FORCE_FP_AS_GP
)
4575 /* User explicitly issues -mforce-fp-as-gp option. */
4576 df_set_regs_ever_live (FP_REGNUM
, 1);
4581 /* In the following we are going to evaluate whether
4582 it is worth to do fp_as_gp optimization. */
4584 int symbol_count
= 0;
4589 /* We check if there already requires prologue.
4590 Note that $gp will be saved in prologue for PIC code generation.
4591 After that, we can set threshold by the existence of prologue.
4592 Each fp-implied instruction will gain 2-byte code size
4593 from gp-aware instruction, so we have following heuristics. */
4595 || nds32_have_prologue_p ())
4598 Compiler already intends to generate prologue content,
4599 so the fp_as_gp optimization will only insert
4600 'la $fp,_FP_BASE_' instruction, which will be
4601 converted into 4-byte instruction at link time.
4602 The threshold is "3" symbol accesses, 2 + 2 + 2 > 4. */
4608 Compiler originally does not generate prologue content,
4609 so the fp_as_gp optimization will NOT ONLY insert
4610 'la $fp,_FP_BASE' instruction, but also causes
4611 push/pop instructions.
4612 If we are using v3push (push25/pop25),
4613 the threshold is "5" symbol accesses, 5*2 > 4 + 2 + 2;
4614 If we are using normal push (smw/lmw),
4615 the threshold is "5+2" symbol accesses 7*2 > 4 + 4 + 4. */
4616 threshold
= 5 + (TARGET_V3PUSH
? 0 : 2);
4619 /* We would like to traverse every instruction in this function.
4620 So we need to have push_topmost_sequence()/pop_topmost_sequence()
4621 surrounding our for-loop evaluation. */
4622 push_topmost_sequence ();
4623 /* Counting the insn number which the addressing mode is symbol. */
4624 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
4626 if (single_set (insn
) && nds32_symbol_load_store_p (insn
))
4629 if (symbol_count
== threshold
)
4635 pop_topmost_sequence ();
4637 /* Enable fp_as_gp optimization when potential gain is good enough. */
4640 df_set_regs_ever_live (FP_REGNUM
, 1);
4645 /* By default we return 0. */
4650 /* Function to generate PC relative jump table.
4651 Refer to nds32.md for more details.
4653 The following is the sample for the case that diff value
4654 can be presented in '.short' size.
4656 addi $r1, $r1, -(case_lower_bound)
4657 slti $ta, $r1, (case_number)
4658 beqz $ta, .L_skip_label
4660 la $ta, .L35 ! get jump table address
4661 lh $r1, [$ta + $r1 << 1] ! load symbol diff from jump table entry
4678 nds32_output_casesi_pc_relative (rtx
*operands
)
4680 enum machine_mode mode
;
4683 diff_vec
= PATTERN (NEXT_INSN (operands
[1]));
4685 gcc_assert (GET_CODE (diff_vec
) == ADDR_DIFF_VEC
);
4687 /* Step C: "t <-- operands[1]". */
4688 output_asm_insn ("la\t$ta, %l1", operands
);
4690 /* Get the mode of each element in the difference vector. */
4691 mode
= GET_MODE (diff_vec
);
4693 /* Step D: "z <-- (mem (plus (operands[0] << m) t))",
4694 where m is 0, 1, or 2 to load address-diff value from table. */
4698 output_asm_insn ("lb\t%2, [$ta + %0 << 0]", operands
);
4701 output_asm_insn ("lh\t%2, [$ta + %0 << 1]", operands
);
4704 output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands
);
4710 /* Step E: "t <-- z + t".
4711 Add table label_ref with address-diff value to
4712 obtain target case address. */
4713 output_asm_insn ("add\t$ta, %2, $ta", operands
);
4715 /* Step F: jump to target with register t. */
4722 /* Function to generate normal jump table. */
4724 nds32_output_casesi (rtx
*operands
)
4726 /* Step C: "t <-- operands[1]". */
4727 output_asm_insn ("la\t$ta, %l1", operands
);
4729 /* Step D: "z <-- (mem (plus (operands[0] << 2) t))". */
4730 output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands
);
4732 /* No need to perform Step E, which is only used for
4733 pc relative jump table. */
4735 /* Step F: jump to target with register z. */
4743 /* Function to return memory format. */
4744 enum nds32_16bit_address_type
4745 nds32_mem_format (rtx op
)
4747 enum machine_mode mode_test
;
4752 return ADDRESS_NOT_16BIT_FORMAT
;
4754 mode_test
= GET_MODE (op
);
4759 if (GET_CODE (op
) == REG
&& (mode_test
== SImode
))
4762 /* 333 format for QI/HImode. */
4763 if (GET_CODE (op
) == REG
&& (REGNO (op
) < R8_REGNUM
))
4764 return ADDRESS_LO_REG_IMM3U
;
4766 /* post_inc 333 format. */
4767 if ((GET_CODE (op
) == POST_INC
) && (mode_test
== SImode
))
4769 regno
= REGNO(XEXP (op
, 0));
4772 return ADDRESS_POST_INC_LO_REG_IMM3U
;
4775 /* post_inc 333 format. */
4776 if ((GET_CODE (op
) == POST_MODIFY
)
4777 && (mode_test
== SImode
)
4778 && (REG_P (XEXP (XEXP (op
, 1), 0)))
4779 && (CONST_INT_P (XEXP (XEXP (op
, 1), 1))))
4781 regno
= REGNO (XEXP (XEXP (op
, 1), 0));
4782 val
= INTVAL (XEXP (XEXP (op
, 1), 1));
4783 if (regno
< 8 && val
< 32)
4784 return ADDRESS_POST_INC_LO_REG_IMM3U
;
4787 if ((GET_CODE (op
) == PLUS
)
4788 && (GET_CODE (XEXP (op
, 0)) == REG
)
4789 && (GET_CODE (XEXP (op
, 1)) == CONST_INT
))
4791 val
= INTVAL (XEXP (op
, 1));
4793 regno
= REGNO(XEXP (op
, 0));
4796 && regno
!= SP_REGNUM
4797 && regno
!= FP_REGNUM
)
4798 return ADDRESS_NOT_16BIT_FORMAT
;
4804 if (val
>= 0 && val
< 8 && regno
< 8)
4805 return ADDRESS_LO_REG_IMM3U
;
4810 if (val
>= 0 && val
< 16 && (val
% 2 == 0) && regno
< 8)
4811 return ADDRESS_LO_REG_IMM3U
;
4817 /* fp imply 37 format. */
4818 if ((regno
== FP_REGNUM
) &&
4819 (val
>= 0 && val
< 512 && (val
% 4 == 0)))
4820 return ADDRESS_FP_IMM7U
;
4821 /* sp imply 37 format. */
4822 else if ((regno
== SP_REGNUM
) &&
4823 (val
>= 0 && val
< 512 && (val
% 4 == 0)))
4824 return ADDRESS_SP_IMM7U
;
4826 else if (val
>= 0 && val
< 32 && (val
% 4 == 0) && regno
< 8)
4827 return ADDRESS_LO_REG_IMM3U
;
4835 return ADDRESS_NOT_16BIT_FORMAT
;
4838 /* Output 16-bit store. */
4840 nds32_output_16bit_store (rtx
*operands
, int byte
)
4844 rtx code
= XEXP (operands
[0], 0);
4846 size
= nds32_byte_to_size (byte
);
4848 switch (nds32_mem_format (operands
[0]))
4852 output_asm_insn ("swi450\t%1, [%0]", operands
);
4854 case ADDRESS_LO_REG_IMM3U
:
4855 snprintf (pattern
, sizeof (pattern
), "s%ci333\t%%1, %%0", size
);
4856 output_asm_insn (pattern
, operands
);
4858 case ADDRESS_POST_INC_LO_REG_IMM3U
:
4859 snprintf (pattern
, sizeof (pattern
), "s%ci333.bi\t%%1, %%0", size
);
4860 output_asm_insn (pattern
, operands
);
4862 case ADDRESS_FP_IMM7U
:
4863 output_asm_insn ("swi37\t%1, %0", operands
);
4865 case ADDRESS_SP_IMM7U
:
4866 /* Get immediate value and set back to operands[1]. */
4867 operands
[0] = XEXP (code
, 1);
4868 output_asm_insn ("swi37.sp\t%1, [ + (%0)]", operands
);
4877 /* Output 16-bit load. */
4879 nds32_output_16bit_load (rtx
*operands
, int byte
)
4883 rtx code
= XEXP (operands
[1], 0);
4885 size
= nds32_byte_to_size (byte
);
4887 switch (nds32_mem_format (operands
[1]))
4891 output_asm_insn ("lwi450\t%0, [%1]", operands
);
4893 case ADDRESS_LO_REG_IMM3U
:
4894 snprintf (pattern
, sizeof (pattern
), "l%ci333\t%%0, %%1", size
);
4895 output_asm_insn (pattern
, operands
);
4897 case ADDRESS_POST_INC_LO_REG_IMM3U
:
4898 snprintf (pattern
, sizeof (pattern
), "l%ci333.bi\t%%0, %%1", size
);
4899 output_asm_insn (pattern
, operands
);
4901 case ADDRESS_FP_IMM7U
:
4902 output_asm_insn ("lwi37\t%0, %1", operands
);
4904 case ADDRESS_SP_IMM7U
:
4905 /* Get immediate value and set back to operands[0]. */
4906 operands
[1] = XEXP (code
, 1);
4907 output_asm_insn ("lwi37.sp\t%0, [ + (%1)]", operands
);
4916 /* Output 32-bit store. */
4918 nds32_output_32bit_store (rtx
*operands
, int byte
)
4922 rtx code
= XEXP (operands
[0], 0);
4924 size
= nds32_byte_to_size (byte
);
4926 switch (GET_CODE (code
))
4930 => access location by using register,
4931 use "sbi / shi / swi" */
4932 snprintf (pattern
, sizeof (pattern
), "s%ci\t%%1, %%0", size
);
4937 /* (mem (symbol_ref X))
4939 => access global variables,
4940 use "sbi.gp / shi.gp / swi.gp" */
4941 operands
[0] = XEXP (operands
[0], 0);
4942 snprintf (pattern
, sizeof (pattern
), "s%ci.gp\t%%1, [ + %%0]", size
);
4946 /* (mem (post_inc reg))
4947 => access location by using register which will be post increment,
4948 use "sbi.bi / shi.bi / swi.bi" */
4949 snprintf (pattern
, sizeof (pattern
),
4950 "s%ci.bi\t%%1, %%0, %d", size
, byte
);
4954 /* (mem (post_dec reg))
4955 => access location by using register which will be post decrement,
4956 use "sbi.bi / shi.bi / swi.bi" */
4957 snprintf (pattern
, sizeof (pattern
),
4958 "s%ci.bi\t%%1, %%0, -%d", size
, byte
);
4962 switch (GET_CODE (XEXP (XEXP (code
, 1), 1)))
4966 /* (mem (post_modify (reg) (plus (reg) (reg))))
4967 => access location by using register which will be
4968 post modified with reg,
4969 use "sb.bi/ sh.bi / sw.bi" */
4970 snprintf (pattern
, sizeof (pattern
), "s%c.bi\t%%1, %%0", size
);
4973 /* (mem (post_modify (reg) (plus (reg) (const_int))))
4974 => access location by using register which will be
4975 post modified with const_int,
4976 use "sbi.bi/ shi.bi / swi.bi" */
4977 snprintf (pattern
, sizeof (pattern
), "s%ci.bi\t%%1, %%0", size
);
4985 switch (GET_CODE (XEXP (code
, 1)))
4989 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
4990 => access location by adding two registers,
4991 use "sb / sh / sw" */
4992 snprintf (pattern
, sizeof (pattern
), "s%c\t%%1, %%0", size
);
4995 /* (mem (plus reg const_int))
4996 => access location by adding one register with const_int,
4997 use "sbi / shi / swi" */
4998 snprintf (pattern
, sizeof (pattern
), "s%ci\t%%1, %%0", size
);
5006 operands
[2] = XEXP (code
, 1);
5007 operands
[0] = XEXP (code
, 0);
5008 snprintf (pattern
, sizeof (pattern
),
5009 "s%ci\t%%1, [%%0 + lo12(%%2)]", size
);
5016 output_asm_insn (pattern
, operands
);
5020 /* Output 32-bit load. */
5022 nds32_output_32bit_load (rtx
*operands
, int byte
)
5028 code
= XEXP (operands
[1], 0);
5030 size
= nds32_byte_to_size (byte
);
5032 switch (GET_CODE (code
))
5036 => access location by using register,
5037 use "lbi / lhi / lwi" */
5038 snprintf (pattern
, sizeof (pattern
), "l%ci\t%%0, %%1", size
);
5043 /* (mem (symbol_ref X))
5045 => access global variables,
5046 use "lbi.gp / lhi.gp / lwi.gp" */
5047 operands
[1] = XEXP (operands
[1], 0);
5048 snprintf (pattern
, sizeof (pattern
), "l%ci.gp\t%%0, [ + %%1]", size
);
5052 /* (mem (post_inc reg))
5053 => access location by using register which will be post increment,
5054 use "lbi.bi / lhi.bi / lwi.bi" */
5055 snprintf (pattern
, sizeof (pattern
),
5056 "l%ci.bi\t%%0, %%1, %d", size
, byte
);
5060 /* (mem (post_dec reg))
5061 => access location by using register which will be post decrement,
5062 use "lbi.bi / lhi.bi / lwi.bi" */
5063 snprintf (pattern
, sizeof (pattern
),
5064 "l%ci.bi\t%%0, %%1, -%d", size
, byte
);
5068 switch (GET_CODE (XEXP (XEXP (code
, 1), 1)))
5072 /* (mem (post_modify (reg) (plus (reg) (reg))))
5073 => access location by using register which will be
5074 post modified with reg,
5075 use "lb.bi/ lh.bi / lw.bi" */
5076 snprintf (pattern
, sizeof (pattern
), "l%c.bi\t%%0, %%1", size
);
5079 /* (mem (post_modify (reg) (plus (reg) (const_int))))
5080 => access location by using register which will be
5081 post modified with const_int,
5082 use "lbi.bi/ lhi.bi / lwi.bi" */
5083 snprintf (pattern
, sizeof (pattern
), "l%ci.bi\t%%0, %%1", size
);
5091 switch (GET_CODE (XEXP (code
, 1)))
5095 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
5096 use "lb / lh / lw" */
5097 snprintf (pattern
, sizeof (pattern
), "l%c\t%%0, %%1", size
);
5100 /* (mem (plus reg const_int))
5101 => access location by adding one register with const_int,
5102 use "lbi / lhi / lwi" */
5103 snprintf (pattern
, sizeof (pattern
), "l%ci\t%%0, %%1", size
);
5111 operands
[2] = XEXP (code
, 1);
5112 operands
[1] = XEXP (code
, 0);
5113 snprintf (pattern
, sizeof (pattern
),
5114 "l%ci\t%%0, [%%1 + lo12(%%2)]", size
);
5121 output_asm_insn (pattern
, operands
);
5125 /* Output 32-bit load with signed extension. */
5127 nds32_output_32bit_load_s (rtx
*operands
, int byte
)
5133 code
= XEXP (operands
[1], 0);
5135 size
= nds32_byte_to_size (byte
);
5137 switch (GET_CODE (code
))
5141 => access location by using register,
5142 use "lbsi / lhsi" */
5143 snprintf (pattern
, sizeof (pattern
), "l%csi\t%%0, %%1", size
);
5148 /* (mem (symbol_ref X))
5150 => access global variables,
5151 use "lbsi.gp / lhsi.gp" */
5152 operands
[1] = XEXP (operands
[1], 0);
5153 snprintf (pattern
, sizeof (pattern
), "l%csi.gp\t%%0, [ + %%1]", size
);
5157 /* (mem (post_inc reg))
5158 => access location by using register which will be post increment,
5159 use "lbsi.bi / lhsi.bi" */
5160 snprintf (pattern
, sizeof (pattern
),
5161 "l%csi.bi\t%%0, %%1, %d", size
, byte
);
5165 /* (mem (post_dec reg))
5166 => access location by using register which will be post decrement,
5167 use "lbsi.bi / lhsi.bi" */
5168 snprintf (pattern
, sizeof (pattern
),
5169 "l%csi.bi\t%%0, %%1, -%d", size
, byte
);
5173 switch (GET_CODE (XEXP (XEXP (code
, 1), 1)))
5177 /* (mem (post_modify (reg) (plus (reg) (reg))))
5178 => access location by using register which will be
5179 post modified with reg,
5180 use "lbs.bi/ lhs.bi" */
5181 snprintf (pattern
, sizeof (pattern
), "l%cs.bi\t%%0, %%1", size
);
5184 /* (mem (post_modify (reg) (plus (reg) (const_int))))
5185 => access location by using register which will be
5186 post modified with const_int,
5187 use "lbsi.bi/ lhsi.bi" */
5188 snprintf (pattern
, sizeof (pattern
), "l%csi.bi\t%%0, %%1", size
);
5196 switch (GET_CODE (XEXP (code
, 1)))
5200 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
5202 snprintf (pattern
, sizeof (pattern
), "l%cs\t%%0, %%1", size
);
5205 /* (mem (plus reg const_int))
5206 => access location by adding one register with const_int,
5207 use "lbsi / lhsi" */
5208 snprintf (pattern
, sizeof (pattern
), "l%csi\t%%0, %%1", size
);
5216 operands
[2] = XEXP (code
, 1);
5217 operands
[1] = XEXP (code
, 0);
5218 snprintf (pattern
, sizeof (pattern
),
5219 "l%csi\t%%0, [%%1 + lo12(%%2)]", size
);
5226 output_asm_insn (pattern
, operands
);
5230 /* Function to output stack push operation.
5231 We need to deal with normal stack push multiple or stack v3push. */
5233 nds32_output_stack_push (void)
5235 /* A string pattern for output_asm_insn(). */
5237 /* The operands array which will be used in output_asm_insn(). */
5239 /* Pick up callee-saved first regno and last regno for further use. */
5240 int rb_regno
= cfun
->machine
->callee_saved_regs_first_regno
;
5241 int re_regno
= cfun
->machine
->callee_saved_regs_last_regno
;
5245 /* For stack v3push:
5247 operands[1]: imm8u */
5249 /* This variable is to check if 'push25 Re,imm8u' is available. */
5252 /* Set operands[0]. */
5253 operands
[0] = gen_rtx_REG (SImode
, re_regno
);
5255 /* Check if we can generate 'push25 Re,imm8u',
5256 otherwise, generate 'push25 Re,0'. */
5257 sp_adjust
= cfun
->machine
->local_size
5258 + cfun
->machine
->out_args_size
5259 + cfun
->machine
->callee_saved_area_padding_bytes
;
5260 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust
))
5261 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust
))
5262 operands
[1] = GEN_INT (sp_adjust
);
5264 operands
[1] = GEN_INT (0);
5266 /* Create assembly code pattern. */
5267 snprintf (pattern
, sizeof (pattern
), "push25\t%%0, %%1");
5271 /* For normal stack push multiple:
5276 /* This variable is used to check if we only need to generate En4 field.
5277 As long as Rb==Re=SP_REGNUM, we set this variable to 1. */
5278 int push_en4_only_p
= 0;
5280 /* Set operands[0] and operands[1]. */
5281 operands
[0] = gen_rtx_REG (SImode
, rb_regno
);
5282 operands
[1] = gen_rtx_REG (SImode
, re_regno
);
5284 /* 'smw.adm $sp,[$sp],$sp,0' means push nothing. */
5285 if (!cfun
->machine
->fp_size
5286 && !cfun
->machine
->gp_size
5287 && !cfun
->machine
->lp_size
5288 && REGNO (operands
[0]) == SP_REGNUM
5289 && REGNO (operands
[1]) == SP_REGNUM
)
5291 /* No need to generate instruction. */
5296 /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */
5297 if (REGNO (operands
[0]) == SP_REGNUM
5298 && REGNO (operands
[1]) == SP_REGNUM
)
5299 push_en4_only_p
= 1;
5301 /* Create assembly code pattern.
5302 We need to handle the form: "Rb, Re, { $fp $gp $lp }". */
5303 snprintf (pattern
, sizeof (pattern
),
5304 "push.s\t%s{%s%s%s }",
5305 push_en4_only_p
? "" : "%0, %1, ",
5306 cfun
->machine
->fp_size
? " $fp" : "",
5307 cfun
->machine
->gp_size
? " $gp" : "",
5308 cfun
->machine
->lp_size
? " $lp" : "");
5312 /* We use output_asm_insn() to output assembly code by ourself. */
5313 output_asm_insn (pattern
, operands
);
5317 /* Function to output stack pop operation.
5318 We need to deal with normal stack pop multiple or stack v3pop. */
5320 nds32_output_stack_pop (void)
5322 /* A string pattern for output_asm_insn(). */
5324 /* The operands array which will be used in output_asm_insn(). */
5326 /* Pick up callee-saved first regno and last regno for further use. */
5327 int rb_regno
= cfun
->machine
->callee_saved_regs_first_regno
;
5328 int re_regno
= cfun
->machine
->callee_saved_regs_last_regno
;
5334 operands[1]: imm8u */
5336 /* This variable is to check if 'pop25 Re,imm8u' is available. */
5339 /* Set operands[0]. */
5340 operands
[0] = gen_rtx_REG (SImode
, re_regno
);
5342 /* Check if we can generate 'pop25 Re,imm8u',
5343 otherwise, generate 'pop25 Re,0'.
5344 We have to consider alloca issue as well.
5345 If the function does call alloca(), the stack pointer is not fixed.
5346 In that case, we cannot use 'pop25 Re,imm8u' directly.
5347 We have to caculate stack pointer from frame pointer
5348 and then use 'pop25 Re,0'. */
5349 sp_adjust
= cfun
->machine
->local_size
5350 + cfun
->machine
->out_args_size
5351 + cfun
->machine
->callee_saved_area_padding_bytes
;
5352 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust
))
5353 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust
)
5354 && !cfun
->calls_alloca
)
5355 operands
[1] = GEN_INT (sp_adjust
);
5357 operands
[1] = GEN_INT (0);
5359 /* Create assembly code pattern. */
5360 snprintf (pattern
, sizeof (pattern
), "pop25\t%%0, %%1");
5364 /* For normal stack pop multiple:
5369 /* This variable is used to check if we only need to generate En4 field.
5370 As long as Rb==Re=SP_REGNUM, we set this variable to 1. */
5371 int pop_en4_only_p
= 0;
5373 /* Set operands[0] and operands[1]. */
5374 operands
[0] = gen_rtx_REG (SImode
, rb_regno
);
5375 operands
[1] = gen_rtx_REG (SImode
, re_regno
);
5377 /* 'lmw.bim $sp,[$sp],$sp,0' means pop nothing. */
5378 if (!cfun
->machine
->fp_size
5379 && !cfun
->machine
->gp_size
5380 && !cfun
->machine
->lp_size
5381 && REGNO (operands
[0]) == SP_REGNUM
5382 && REGNO (operands
[1]) == SP_REGNUM
)
5384 /* No need to generate instruction. */
5389 /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */
5390 if (REGNO (operands
[0]) == SP_REGNUM
5391 && REGNO (operands
[1]) == SP_REGNUM
)
5394 /* Create assembly code pattern.
5395 We need to handle the form: "Rb, Re, { $fp $gp $lp }". */
5396 snprintf (pattern
, sizeof (pattern
),
5397 "pop.s\t%s{%s%s%s }",
5398 pop_en4_only_p
? "" : "%0, %1, ",
5399 cfun
->machine
->fp_size
? " $fp" : "",
5400 cfun
->machine
->gp_size
? " $gp" : "",
5401 cfun
->machine
->lp_size
? " $lp" : "");
5405 /* We use output_asm_insn() to output assembly code by ourself. */
5406 output_asm_insn (pattern
, operands
);
5410 /* Return align 2 (log base 2) if the next instruction of LABEL is 4 byte. */
5412 nds32_target_alignment (rtx label
)
5419 insn
= next_active_insn (label
);
5423 else if ((get_attr_length (insn
) % 4) == 0)
5429 /* ------------------------------------------------------------------------ */
5431 /* PART 5: Initialize target hook structure and definitions. */
5433 /* Controlling the Compilation Driver. */
5436 /* Run-time Target Specification. */
5439 /* Defining Data Structures for Per-function Information. */
5442 /* Storage Layout. */
5444 #undef TARGET_PROMOTE_FUNCTION_MODE
5445 #define TARGET_PROMOTE_FUNCTION_MODE \
5446 default_promote_function_mode_always_promote
5449 /* Layout of Source Language Data Types. */
5452 /* Register Usage. */
5454 /* -- Basic Characteristics of Registers. */
5456 /* -- Order of Allocation of Registers. */
5458 /* -- How Values Fit in Registers. */
5460 /* -- Handling Leaf Functions. */
5462 /* -- Registers That Form a Stack. */
5465 /* Register Classes. */
5467 #undef TARGET_CLASS_MAX_NREGS
5468 #define TARGET_CLASS_MAX_NREGS nds32_class_max_nregs
5471 #define TARGET_LRA_P hook_bool_void_true
5473 #undef TARGET_REGISTER_PRIORITY
5474 #define TARGET_REGISTER_PRIORITY nds32_register_priority
5477 /* Obsolete Macros for Defining Constraints. */
5480 /* Stack Layout and Calling Conventions. */
5482 /* -- Basic Stack Layout. */
5484 /* -- Exception Handling Support. */
5486 /* -- Specifying How Stack Checking is Done. */
5488 /* -- Registers That Address the Stack Frame. */
5490 /* -- Eliminating Frame Pointer and Arg Pointer. */
5492 #undef TARGET_CAN_ELIMINATE
5493 #define TARGET_CAN_ELIMINATE nds32_can_eliminate
5495 /* -- Passing Function Arguments on the Stack. */
5497 /* -- Passing Arguments in Registers. */
5499 #undef TARGET_FUNCTION_ARG
5500 #define TARGET_FUNCTION_ARG nds32_function_arg
5502 #undef TARGET_FUNCTION_ARG_ADVANCE
5503 #define TARGET_FUNCTION_ARG_ADVANCE nds32_function_arg_advance
5505 #undef TARGET_FUNCTION_ARG_BOUNDARY
5506 #define TARGET_FUNCTION_ARG_BOUNDARY nds32_function_arg_boundary
5508 /* -- How Scalar Function Values Are Returned. */
5510 #undef TARGET_FUNCTION_VALUE
5511 #define TARGET_FUNCTION_VALUE nds32_function_value
5513 #undef TARGET_LIBCALL_VALUE
5514 #define TARGET_LIBCALL_VALUE nds32_libcall_value
5516 #undef TARGET_FUNCTION_VALUE_REGNO_P
5517 #define TARGET_FUNCTION_VALUE_REGNO_P nds32_function_value_regno_p
5519 /* -- How Large Values Are Returned. */
5521 /* -- Caller-Saves Register Allocation. */
5523 /* -- Function Entry and Exit. */
5525 #undef TARGET_ASM_FUNCTION_PROLOGUE
5526 #define TARGET_ASM_FUNCTION_PROLOGUE nds32_asm_function_prologue
5528 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
5529 #define TARGET_ASM_FUNCTION_END_PROLOGUE nds32_asm_function_end_prologue
5531 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
5532 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE nds32_asm_function_begin_epilogue
5534 #undef TARGET_ASM_FUNCTION_EPILOGUE
5535 #define TARGET_ASM_FUNCTION_EPILOGUE nds32_asm_function_epilogue
5537 #undef TARGET_ASM_OUTPUT_MI_THUNK
5538 #define TARGET_ASM_OUTPUT_MI_THUNK nds32_asm_output_mi_thunk
5540 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5541 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
5543 /* -- Generating Code for Profiling. */
5545 /* -- Permitting tail calls. */
5547 #undef TARGET_WARN_FUNC_RETURN
5548 #define TARGET_WARN_FUNC_RETURN nds32_warn_func_return
5550 /* Stack smashing protection. */
5553 /* Implementing the Varargs Macros. */
5555 #undef TARGET_STRICT_ARGUMENT_NAMING
5556 #define TARGET_STRICT_ARGUMENT_NAMING nds32_strict_argument_naming
5559 /* Trampolines for Nested Functions. */
5561 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
5562 #define TARGET_ASM_TRAMPOLINE_TEMPLATE nds32_asm_trampoline_template
5564 #undef TARGET_TRAMPOLINE_INIT
5565 #define TARGET_TRAMPOLINE_INIT nds32_trampoline_init
5568 /* Implicit Calls to Library Routines. */
5571 /* Addressing Modes. */
5573 #undef TARGET_LEGITIMATE_ADDRESS_P
5574 #define TARGET_LEGITIMATE_ADDRESS_P nds32_legitimate_address_p
5577 /* Anchored Addresses. */
5580 /* Condition Code Status. */
5582 /* -- Representation of condition codes using (cc0). */
5584 /* -- Representation of condition codes using registers. */
5586 /* -- Macros to control conditional execution. */
5589 /* Describing Relative Costs of Operations. */
5591 #undef TARGET_REGISTER_MOVE_COST
5592 #define TARGET_REGISTER_MOVE_COST nds32_register_move_cost
5594 #undef TARGET_MEMORY_MOVE_COST
5595 #define TARGET_MEMORY_MOVE_COST nds32_memory_move_cost
5597 #undef TARGET_RTX_COSTS
5598 #define TARGET_RTX_COSTS nds32_rtx_costs
5600 #undef TARGET_ADDRESS_COST
5601 #define TARGET_ADDRESS_COST nds32_address_cost
5604 /* Adjusting the Instruction Scheduler. */
5607 /* Dividing the Output into Sections (Texts, Data, . . . ). */
5610 /* Position Independent Code. */
5613 /* Defining the Output Assembler Language. */
5615 /* -- The Overall Framework of an Assembler File. */
5617 #undef TARGET_ASM_FILE_START
5618 #define TARGET_ASM_FILE_START nds32_asm_file_start
5619 #undef TARGET_ASM_FILE_END
5620 #define TARGET_ASM_FILE_END nds32_asm_file_end
5622 /* -- Output of Data. */
5624 #undef TARGET_ASM_ALIGNED_HI_OP
5625 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
5627 #undef TARGET_ASM_ALIGNED_SI_OP
5628 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
5630 /* -- Output of Uninitialized Variables. */
5632 /* -- Output and Generation of Labels. */
5634 #undef TARGET_ASM_GLOBALIZE_LABEL
5635 #define TARGET_ASM_GLOBALIZE_LABEL nds32_asm_globalize_label
5637 /* -- How Initialization Functions Are Handled. */
5639 /* -- Macros Controlling Initialization Routines. */
5641 /* -- Output of Assembler Instructions. */
5643 #undef TARGET_PRINT_OPERAND
5644 #define TARGET_PRINT_OPERAND nds32_print_operand
5645 #undef TARGET_PRINT_OPERAND_ADDRESS
5646 #define TARGET_PRINT_OPERAND_ADDRESS nds32_print_operand_address
5648 /* -- Output of Dispatch Tables. */
5650 /* -- Assembler Commands for Exception Regions. */
5652 /* -- Assembler Commands for Alignment. */
5655 /* Controlling Debugging Information Format. */
5657 /* -- Macros Affecting All Debugging Formats. */
5659 /* -- Specific Options for DBX Output. */
5661 /* -- Open-Ended Hooks for DBX Format. */
5663 /* -- File Names in DBX Format. */
5665 /* -- Macros for SDB and DWARF Output. */
5667 /* -- Macros for VMS Debug Format. */
5670 /* Cross Compilation and Floating Point. */
5673 /* Mode Switching Instructions. */
5676 /* Defining target-specific uses of __attribute__. */
5678 #undef TARGET_ATTRIBUTE_TABLE
5679 #define TARGET_ATTRIBUTE_TABLE nds32_attribute_table
5681 #undef TARGET_MERGE_DECL_ATTRIBUTES
5682 #define TARGET_MERGE_DECL_ATTRIBUTES nds32_merge_decl_attributes
5684 #undef TARGET_INSERT_ATTRIBUTES
5685 #define TARGET_INSERT_ATTRIBUTES nds32_insert_attributes
5687 #undef TARGET_OPTION_PRAGMA_PARSE
5688 #define TARGET_OPTION_PRAGMA_PARSE nds32_option_pragma_parse
5690 #undef TARGET_OPTION_OVERRIDE
5691 #define TARGET_OPTION_OVERRIDE nds32_option_override
5694 /* Emulating TLS. */
5697 /* Defining coprocessor specifics for MIPS targets. */
5700 /* Parameters for Precompiled Header Validity Checking. */
5703 /* C++ ABI parameters. */
5706 /* Adding support for named address spaces. */
5709 /* Miscellaneous Parameters. */
5711 #undef TARGET_INIT_BUILTINS
5712 #define TARGET_INIT_BUILTINS nds32_init_builtins
5714 #undef TARGET_EXPAND_BUILTIN
5715 #define TARGET_EXPAND_BUILTIN nds32_expand_builtin
5718 /* ------------------------------------------------------------------------ */
5720 /* Initialize the GCC target structure. */
5722 struct gcc_target targetm
= TARGET_INITIALIZER
;
5724 /* ------------------------------------------------------------------------ */