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_alloc_cleared_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 /* GCC build attributes list with reverse order,
1964 so we use nreverse() to make it looks like
1965 the order that user specifies. */
1966 attrs
= nreverse (DECL_ATTRIBUTES (current_function_decl
));
1968 /* If there is no any attribute, print out "None". */
1970 fprintf (file
, "None");
1972 /* If there are some attributes, try if we need to
1973 construct isr vector information. */
1974 func_name
= IDENTIFIER_POINTER (DECL_NAME (current_function_decl
));
1975 nds32_construct_isr_vectors_information (attrs
, func_name
);
1977 /* Display all attributes of this function. */
1980 name
= TREE_PURPOSE (attrs
);
1981 fprintf (file
, "%s ", IDENTIFIER_POINTER (name
));
1983 /* Pick up the next attribute. */
1984 attrs
= TREE_CHAIN (attrs
);
1989 /* After rtl prologue has been expanded, this function is used. */
1991 nds32_asm_function_end_prologue (FILE *file
)
1993 fprintf (file
, "\t! END PROLOGUE\n");
1995 /* If frame pointer is NOT needed and -mfp-as-gp is issued,
1996 we can generate special directive: ".omit_fp_begin"
1997 to guide linker doing fp-as-gp optimization.
1998 However, for a naked function, which means
1999 it should not have prologue/epilogue,
2000 using fp-as-gp still requires saving $fp by push/pop behavior and
2001 there is no benefit to use fp-as-gp on such small function.
2002 So we need to make sure this function is NOT naked as well. */
2003 if (!frame_pointer_needed
2004 && !cfun
->machine
->naked_p
2005 && cfun
->machine
->fp_as_gp_p
)
2007 fprintf (file
, "\t! ----------------------------------------\n");
2008 fprintf (file
, "\t! Guide linker to do "
2009 "link time optimization: fp-as-gp\n");
2010 fprintf (file
, "\t! We add one more instruction to "
2011 "initialize $fp near to $gp location.\n");
2012 fprintf (file
, "\t! If linker fails to use fp-as-gp transformation,\n");
2013 fprintf (file
, "\t! this extra instruction should be "
2014 "eliminated at link stage.\n");
2015 fprintf (file
, "\t.omit_fp_begin\n");
2016 fprintf (file
, "\tla\t$fp,_FP_BASE_\n");
2017 fprintf (file
, "\t! ----------------------------------------\n");
2021 /* Before rtl epilogue has been expanded, this function is used. */
2023 nds32_asm_function_begin_epilogue (FILE *file
)
2025 /* If frame pointer is NOT needed and -mfp-as-gp is issued,
2026 we can generate special directive: ".omit_fp_end"
2027 to claim fp-as-gp optimization range.
2028 However, for a naked function,
2029 which means it should not have prologue/epilogue,
2030 using fp-as-gp still requires saving $fp by push/pop behavior and
2031 there is no benefit to use fp-as-gp on such small function.
2032 So we need to make sure this function is NOT naked as well. */
2033 if (!frame_pointer_needed
2034 && !cfun
->machine
->naked_p
2035 && cfun
->machine
->fp_as_gp_p
)
2037 fprintf (file
, "\t! ----------------------------------------\n");
2038 fprintf (file
, "\t! Claim the range of fp-as-gp "
2039 "link time optimization\n");
2040 fprintf (file
, "\t.omit_fp_end\n");
2041 fprintf (file
, "\t! ----------------------------------------\n");
2044 fprintf (file
, "\t! BEGIN EPILOGUE\n");
2047 /* The content produced from this function
2048 will be placed after epilogue body. */
2050 nds32_asm_function_epilogue (FILE *file
,
2051 HOST_WIDE_INT size ATTRIBUTE_UNUSED
)
2053 fprintf (file
, "\t! END EPILOGUE\n");
2057 nds32_asm_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
2058 HOST_WIDE_INT delta
,
2059 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED
,
2064 /* Make sure unwind info is emitted for the thunk if needed. */
2065 final_start_function (emit_barrier (), file
, 1);
2067 this_regno
= (aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
)
2073 if (satisfies_constraint_Is15 (GEN_INT (delta
)))
2075 fprintf (file
, "\taddi\t$r%d, $r%d, %ld\n",
2076 this_regno
, this_regno
, delta
);
2078 else if (satisfies_constraint_Is20 (GEN_INT (delta
)))
2080 fprintf (file
, "\tmovi\t$ta, %ld\n", delta
);
2081 fprintf (file
, "\tadd\t$r%d, $r%d, $ta\n", this_regno
, this_regno
);
2085 fprintf (file
, "\tsethi\t$ta, hi20(%ld)\n", delta
);
2086 fprintf (file
, "\tori\t$ta, $ta, lo12(%ld)\n", delta
);
2087 fprintf (file
, "\tadd\t$r%d, $r%d, $ta\n", this_regno
, this_regno
);
2091 fprintf (file
, "\tb\t");
2092 assemble_name (file
, XSTR (XEXP (DECL_RTL (function
), 0), 0));
2093 fprintf (file
, "\n");
2095 final_end_function ();
2098 /* -- Permitting tail calls. */
2100 /* Determine whether we need to enable warning for function return check. */
2102 nds32_warn_func_return (tree decl
)
2104 /* Naked functions are implemented entirely in assembly, including the
2105 return sequence, so suppress warnings about this. */
2106 return !nds32_naked_function_p (decl
);
2110 /* Implementing the Varargs Macros. */
2113 nds32_strict_argument_naming (cumulative_args_t ca ATTRIBUTE_UNUSED
)
2115 /* Return true so that all the named arguments for FUNCTION_ARG have named=1.
2116 If return false, for the variadic function, all named arguments EXCEPT
2117 the last are treated as named. */
2122 /* Trampolines for Nested Functions. */
2125 nds32_asm_trampoline_template (FILE *f
)
2127 if (TARGET_REDUCED_REGS
)
2129 /* Trampoline is not supported on reduced-set registers yet. */
2130 sorry ("a nested function is not supported for reduced registers");
2134 asm_fprintf (f
, "\t! Trampoline code template\n");
2135 asm_fprintf (f
, "\t! This code fragment will be copied "
2136 "into stack on demand\n");
2138 asm_fprintf (f
, "\tmfusr\t$r16,$pc\n");
2139 asm_fprintf (f
, "\tlwi\t$r15,[$r16 + 20] "
2140 "! load nested function address\n");
2141 asm_fprintf (f
, "\tlwi\t$r16,[$r16 + 16] "
2142 "! load chain_value\n");
2143 asm_fprintf (f
, "\tjr\t$r15\n");
2146 /* Preserve space ($pc + 16) for saving chain_value,
2147 nds32_trampoline_init will fill the value in this slot. */
2148 asm_fprintf (f
, "\t! space for saving chain_value\n");
2149 assemble_aligned_integer (UNITS_PER_WORD
, const0_rtx
);
2151 /* Preserve space ($pc + 20) for saving nested function address,
2152 nds32_trampoline_init will fill the value in this slot. */
2153 asm_fprintf (f
, "\t! space for saving nested function address\n");
2154 assemble_aligned_integer (UNITS_PER_WORD
, const0_rtx
);
2157 /* Emit RTL insns to initialize the variable parts of a trampoline. */
2159 nds32_trampoline_init (rtx m_tramp
, tree fndecl
, rtx chain_value
)
2163 /* Nested function address. */
2165 /* The memory rtx that is going to
2166 be filled with chain_value. */
2167 rtx chain_value_mem
;
2168 /* The memory rtx that is going to
2169 be filled with nested function address. */
2170 rtx nested_func_mem
;
2172 /* Start address of trampoline code in stack, for doing cache sync. */
2173 rtx sync_cache_addr
;
2174 /* Temporary register for sync instruction. */
2176 /* Instruction-cache sync instruction,
2177 requesting an argument as starting address. */
2179 /* For convenience reason of doing comparison. */
2180 int tramp_align_in_bytes
;
2182 /* Trampoline is not supported on reduced-set registers yet. */
2183 if (TARGET_REDUCED_REGS
)
2184 sorry ("a nested function is not supported for reduced registers");
2186 /* STEP 1: Copy trampoline code template into stack,
2187 fill up essential data into stack. */
2189 /* Extract nested function address rtx. */
2190 fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2192 /* m_tramp is memory rtx that is going to be filled with trampoline code.
2193 We have nds32_asm_trampoline_template() to emit template pattern. */
2194 emit_block_move (m_tramp
, assemble_trampoline_template (),
2195 GEN_INT (TRAMPOLINE_SIZE
), BLOCK_OP_NORMAL
);
2197 /* After copying trampoline code into stack,
2198 fill chain_value into stack. */
2199 chain_value_mem
= adjust_address (m_tramp
, SImode
, 16);
2200 emit_move_insn (chain_value_mem
, chain_value
);
2201 /* After copying trampoline code int stack,
2202 fill nested function address into stack. */
2203 nested_func_mem
= adjust_address (m_tramp
, SImode
, 20);
2204 emit_move_insn (nested_func_mem
, fnaddr
);
2206 /* STEP 2: Sync instruction-cache. */
2208 /* We have successfully filled trampoline code into stack.
2209 However, in order to execute code in stack correctly,
2210 we must sync instruction cache. */
2211 sync_cache_addr
= XEXP (m_tramp
, 0);
2212 tmp_reg
= gen_reg_rtx (SImode
);
2213 isync_insn
= gen_unspec_volatile_isync (tmp_reg
);
2215 /* Because nds32_cache_block_size is in bytes,
2216 we get trampoline alignment in bytes for convenient comparison. */
2217 tramp_align_in_bytes
= TRAMPOLINE_ALIGNMENT
/ BITS_PER_UNIT
;
2219 if (tramp_align_in_bytes
>= nds32_cache_block_size
2220 && (tramp_align_in_bytes
% nds32_cache_block_size
) == 0)
2222 /* Under this condition, the starting address of trampoline
2223 must be aligned to the starting address of each cache block
2224 and we do not have to worry about cross-boundary issue. */
2226 i
< (TRAMPOLINE_SIZE
+ nds32_cache_block_size
- 1)
2227 / nds32_cache_block_size
;
2230 emit_move_insn (tmp_reg
,
2231 plus_constant (Pmode
, sync_cache_addr
,
2232 nds32_cache_block_size
* i
));
2233 emit_insn (isync_insn
);
2236 else if (TRAMPOLINE_SIZE
> nds32_cache_block_size
)
2238 /* The starting address of trampoline code
2239 may not be aligned to the cache block,
2240 so the trampoline code may be across two cache block.
2241 We need to sync the last element, which is 4-byte size,
2242 of trampoline template. */
2244 i
< (TRAMPOLINE_SIZE
+ nds32_cache_block_size
- 1)
2245 / nds32_cache_block_size
;
2248 emit_move_insn (tmp_reg
,
2249 plus_constant (Pmode
, sync_cache_addr
,
2250 nds32_cache_block_size
* i
));
2251 emit_insn (isync_insn
);
2254 /* The last element of trampoline template is 4-byte size. */
2255 emit_move_insn (tmp_reg
,
2256 plus_constant (Pmode
, sync_cache_addr
,
2257 TRAMPOLINE_SIZE
- 4));
2258 emit_insn (isync_insn
);
2262 /* This is the simplest case.
2263 Because TRAMPOLINE_SIZE is less than or
2264 equal to nds32_cache_block_size,
2265 we can just sync start address and
2266 the last element of trampoline code. */
2268 /* Sync starting address of tampoline code. */
2269 emit_move_insn (tmp_reg
, sync_cache_addr
);
2270 emit_insn (isync_insn
);
2271 /* Sync the last element, which is 4-byte size,
2272 of trampoline template. */
2273 emit_move_insn (tmp_reg
,
2274 plus_constant (Pmode
, sync_cache_addr
,
2275 TRAMPOLINE_SIZE
- 4));
2276 emit_insn (isync_insn
);
2279 /* Set instruction serialization barrier
2280 to guarantee the correct operations. */
2281 emit_insn (gen_unspec_volatile_isb ());
2285 /* Addressing Modes. */
2288 nds32_legitimate_address_p (enum machine_mode mode
, rtx x
, bool strict
)
2290 /* For (mem:DI addr) or (mem:DF addr) case,
2291 we only allow 'addr' to be [reg], [symbol_ref],
2292 [const], or [reg + const_int] pattern. */
2293 if (mode
== DImode
|| mode
== DFmode
)
2295 /* Allow [Reg + const_int] addressing mode. */
2296 if (GET_CODE (x
) == PLUS
)
2298 if (nds32_address_register_rtx_p (XEXP (x
, 0), strict
)
2299 && nds32_legitimate_index_p (mode
, XEXP (x
, 1), strict
)
2300 && CONST_INT_P (XEXP (x
, 1)))
2303 else if (nds32_address_register_rtx_p (XEXP (x
, 1), strict
)
2304 && nds32_legitimate_index_p (mode
, XEXP (x
, 0), strict
)
2305 && CONST_INT_P (XEXP (x
, 0)))
2309 /* Now check [reg], [symbol_ref], and [const]. */
2310 if (GET_CODE (x
) != REG
2311 && GET_CODE (x
) != SYMBOL_REF
2312 && GET_CODE (x
) != CONST
)
2316 /* Check if 'x' is a valid address. */
2317 switch (GET_CODE (x
))
2320 /* (mem (reg A)) => [Ra] */
2321 return nds32_address_register_rtx_p (x
, strict
);
2325 if (!TARGET_GP_DIRECT
2326 && (reload_completed
2327 || reload_in_progress
2328 || lra_in_progress
))
2331 /* (mem (symbol_ref A)) => [symbol_ref] */
2332 return !currently_expanding_to_rtl
;
2336 if (!TARGET_GP_DIRECT
2337 && (reload_completed
2338 || reload_in_progress
2339 || lra_in_progress
))
2342 /* (mem (const (...)))
2343 => [ + const_addr ], where const_addr = symbol_ref + const_int */
2344 if (GET_CODE (XEXP (x
, 0)) == PLUS
)
2346 rtx plus_op
= XEXP (x
, 0);
2348 rtx op0
= XEXP (plus_op
, 0);
2349 rtx op1
= XEXP (plus_op
, 1);
2351 if (GET_CODE (op0
) == SYMBOL_REF
&& CONST_INT_P (op1
))
2360 /* (mem (post_modify (reg) (plus (reg) (reg))))
2362 /* (mem (post_modify (reg) (plus (reg) (const_int))))
2363 => [Ra], const_int */
2364 if (GET_CODE (XEXP (x
, 0)) == REG
2365 && GET_CODE (XEXP (x
, 1)) == PLUS
)
2367 rtx plus_op
= XEXP (x
, 1);
2369 rtx op0
= XEXP (plus_op
, 0);
2370 rtx op1
= XEXP (plus_op
, 1);
2372 if (nds32_address_register_rtx_p (op0
, strict
)
2373 && nds32_legitimate_index_p (mode
, op1
, strict
))
2383 /* (mem (post_inc reg)) => [Ra], 1/2/4 */
2384 /* (mem (post_dec reg)) => [Ra], -1/-2/-4 */
2385 /* The 1/2/4 or -1/-2/-4 have been displayed in nds32.md.
2386 We only need to deal with register Ra. */
2387 if (nds32_address_register_rtx_p (XEXP (x
, 0), strict
))
2393 /* (mem (plus reg const_int))
2395 /* (mem (plus reg reg))
2397 /* (mem (plus (mult reg const_int) reg))
2398 => [Ra + Rb << sv] */
2399 if (nds32_address_register_rtx_p (XEXP (x
, 0), strict
)
2400 && nds32_legitimate_index_p (mode
, XEXP (x
, 1), strict
))
2402 else if (nds32_address_register_rtx_p (XEXP (x
, 1), strict
)
2403 && nds32_legitimate_index_p (mode
, XEXP (x
, 0), strict
))
2409 if (!TARGET_GP_DIRECT
)
2418 /* Describing Relative Costs of Operations. */
2420 static int nds32_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED
,
2424 if (from
== HIGH_REGS
|| to
== HIGH_REGS
)
2430 static int nds32_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED
,
2431 reg_class_t rclass ATTRIBUTE_UNUSED
,
2432 bool in ATTRIBUTE_UNUSED
)
2437 /* This target hook describes the relative costs of RTL expressions.
2438 Return 'true' when all subexpressions of x have been processed.
2439 Return 'false' to sum the costs of sub-rtx, plus cost of this operation.
2440 Refer to gcc/rtlanal.c for more information. */
2442 nds32_rtx_costs (rtx x
,
2445 int opno ATTRIBUTE_UNUSED
,
2449 /* According to 'speed', goto suitable cost model section. */
2451 goto performance_cost
;
2457 /* This is section for performance cost model. */
2459 /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4.
2460 We treat it as 4-cycle cost for each instruction
2461 under performance consideration. */
2465 /* For 'SET' rtx, we need to return false
2466 so that it can recursively calculate costs. */
2470 /* Used in combine.c as a marker. */
2475 *total
= COSTS_N_INSNS (1);
2482 *total
= COSTS_N_INSNS (7);
2486 *total
= COSTS_N_INSNS (1);
2494 /* This is section for size cost model. */
2496 /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4.
2497 We treat it as 4-byte cost for each instruction
2498 under code size consideration. */
2502 /* For 'SET' rtx, we need to return false
2503 so that it can recursively calculate costs. */
2507 /* Used in combine.c as a marker. */
2512 /* All instructions involving constant operation
2513 need to be considered for cost evaluation. */
2514 if (outer_code
== SET
)
2516 /* (set X imm5s), use movi55, 2-byte cost.
2517 (set X imm20s), use movi, 4-byte cost.
2518 (set X BIG_INT), use sethi/ori, 8-byte cost. */
2519 if (satisfies_constraint_Is05 (x
))
2520 *total
= COSTS_N_INSNS (1) - 2;
2521 else if (satisfies_constraint_Is20 (x
))
2522 *total
= COSTS_N_INSNS (1);
2524 *total
= COSTS_N_INSNS (2);
2526 else if (outer_code
== PLUS
|| outer_code
== MINUS
)
2528 /* Possible addi333/subi333 or subi45/addi45, 2-byte cost.
2529 General case, cost 1 instruction with 4-byte. */
2530 if (satisfies_constraint_Iu05 (x
))
2531 *total
= COSTS_N_INSNS (1) - 2;
2533 *total
= COSTS_N_INSNS (1);
2535 else if (outer_code
== ASHIFT
)
2537 /* Possible slli333, 2-byte cost.
2538 General case, cost 1 instruction with 4-byte. */
2539 if (satisfies_constraint_Iu03 (x
))
2540 *total
= COSTS_N_INSNS (1) - 2;
2542 *total
= COSTS_N_INSNS (1);
2544 else if (outer_code
== ASHIFTRT
|| outer_code
== LSHIFTRT
)
2546 /* Possible srai45 or srli45, 2-byte cost.
2547 General case, cost 1 instruction with 4-byte. */
2548 if (satisfies_constraint_Iu05 (x
))
2549 *total
= COSTS_N_INSNS (1) - 2;
2551 *total
= COSTS_N_INSNS (1);
2555 /* For other cases, simply set it 4-byte cost. */
2556 *total
= COSTS_N_INSNS (1);
2561 /* It requires high part and low part processing, set it 8-byte cost. */
2562 *total
= COSTS_N_INSNS (2);
2566 /* For other cases, generally we set it 4-byte cost
2567 and stop resurively traversing. */
2568 *total
= COSTS_N_INSNS (1);
2575 static int nds32_address_cost (rtx address
,
2576 enum machine_mode mode ATTRIBUTE_UNUSED
,
2577 addr_space_t as ATTRIBUTE_UNUSED
,
2583 code
= GET_CODE (address
);
2585 /* According to 'speed', goto suitable cost model section. */
2587 goto performance_cost
;
2592 /* This is section for performance cost model. */
2594 /* FALLTHRU, currently we use same cost model as size_cost. */
2597 /* This is section for size cost model. */
2604 /* We encourage that rtx contains
2605 POST_MODIFY/POST_INC/POST_DEC behavior. */
2609 /* We can have gp-relative load/store for symbol_ref.
2610 Have it 4-byte cost. */
2611 return COSTS_N_INSNS (1);
2614 /* It is supposed to be the pattern (const (plus symbol_ref const_int)).
2615 Have it 4-byte cost. */
2616 return COSTS_N_INSNS (1);
2619 /* Simply return 4-byte costs. */
2620 return COSTS_N_INSNS (1);
2623 /* We do not need to check if the address is a legitimate address,
2624 because this hook is never called with an invalid address.
2625 But we better check the range of
2626 const_int value for cost, if it exists. */
2627 plus0
= XEXP (address
, 0);
2628 plus1
= XEXP (address
, 1);
2630 if (REG_P (plus0
) && CONST_INT_P (plus1
))
2632 /* If it is possible to be lwi333/swi333 form,
2633 make it 2-byte cost. */
2634 if (satisfies_constraint_Iu05 (plus1
))
2635 return (COSTS_N_INSNS (1) - 2);
2637 return COSTS_N_INSNS (1);
2640 /* For other 'plus' situation, make it cost 4-byte. */
2641 return COSTS_N_INSNS (1);
2647 return COSTS_N_INSNS (4);
2651 /* Defining the Output Assembler Language. */
2653 /* -- The Overall Framework of an Assembler File. */
2656 nds32_asm_file_start (void)
2660 default_file_start ();
2662 /* Tell assembler which ABI we are using. */
2663 fprintf (asm_out_file
, "\t! ABI version\n");
2664 fprintf (asm_out_file
, "\t.abi_2\n");
2666 /* Tell assembler that this asm code is generated by compiler. */
2667 fprintf (asm_out_file
, "\t! This asm file is generated by compiler\n");
2668 fprintf (asm_out_file
, "\t.flag\tverbatim\n");
2669 /* Give assembler the size of each vector for interrupt handler. */
2670 fprintf (asm_out_file
, "\t! This vector size directive is required "
2671 "for checking inconsistency on interrupt handler\n");
2672 fprintf (asm_out_file
, "\t.vec_size\t%d\n", nds32_isr_vector_size
);
2674 /* If user enables '-mforce-fp-as-gp' or compiles programs with -Os,
2675 the compiler may produce 'la $fp,_FP_BASE_' instruction
2676 at prologue for fp-as-gp optimization.
2677 We should emit weak reference of _FP_BASE_ to avoid undefined reference
2678 in case user does not pass '--relax' option to linker. */
2679 if (TARGET_FORCE_FP_AS_GP
|| optimize_size
)
2681 fprintf (asm_out_file
, "\t! This weak reference is required to do "
2682 "fp-as-gp link time optimization\n");
2683 fprintf (asm_out_file
, "\t.weak\t_FP_BASE_\n");
2685 /* If user enables '-mex9', we should emit relaxation directive
2686 to tell linker that this file is allowed to do ex9 optimization. */
2689 fprintf (asm_out_file
, "\t! This relaxation directive is required "
2690 "to do ex9 link time optimization\n");
2691 fprintf (asm_out_file
, "\t.relax\tex9\n");
2694 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2697 fprintf (asm_out_file
, "\t! ISA family\t\t: %s\n", "V2");
2699 fprintf (asm_out_file
, "\t! ISA family\t\t: %s\n", "V3");
2701 fprintf (asm_out_file
, "\t! ISA family\t\t: %s\n", "V3M");
2703 fprintf (asm_out_file
, "\t! Endian setting\t: %s\n",
2704 ((TARGET_BIG_ENDIAN
) ? "big-endian"
2705 : "little-endian"));
2707 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2709 fprintf (asm_out_file
, "\t! Use conditional move\t\t: %s\n",
2710 ((TARGET_CMOV
) ? "Yes"
2712 fprintf (asm_out_file
, "\t! Use performance extension\t: %s\n",
2713 ((TARGET_PERF_EXT
) ? "Yes"
2716 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2718 fprintf (asm_out_file
, "\t! V3PUSH instructions\t: %s\n",
2719 ((TARGET_V3PUSH
) ? "Yes"
2721 fprintf (asm_out_file
, "\t! 16-bit instructions\t: %s\n",
2722 ((TARGET_16_BIT
) ? "Yes"
2724 fprintf (asm_out_file
, "\t! GP base access\t: %s\n",
2725 ((TARGET_GP_DIRECT
) ? "Yes"
2727 fprintf (asm_out_file
, "\t! Reduced registers set\t: %s\n",
2728 ((TARGET_REDUCED_REGS
) ? "Yes"
2731 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2734 fprintf (asm_out_file
, "\t! Optimization level\t: -Os\n");
2736 fprintf (asm_out_file
, "\t! Optimization level\t: -O%d\n", optimize
);
2738 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2740 fprintf (asm_out_file
, "\t! Cache block size\t: %d\n",
2741 nds32_cache_block_size
);
2743 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2745 /* Initialize isr vector information array before compiling functions. */
2746 for (i
= 0; i
< NDS32_N_ISR_VECTORS
; i
++)
2748 nds32_isr_vectors
[i
].category
= NDS32_ISR_NONE
;
2749 strcpy (nds32_isr_vectors
[i
].func_name
, "");
2750 nds32_isr_vectors
[i
].save_reg
= NDS32_PARTIAL_SAVE
;
2751 nds32_isr_vectors
[i
].nested_type
= NDS32_NOT_NESTED
;
2752 nds32_isr_vectors
[i
].total_n_vectors
= 0;
2753 strcpy (nds32_isr_vectors
[i
].nmi_name
, "");
2754 strcpy (nds32_isr_vectors
[i
].warm_name
, "");
2759 nds32_asm_file_end (void)
2763 /* If all the vectors are NDS32_ISR_NONE, we can return immediately. */
2764 for (i
= 0; i
< NDS32_N_ISR_VECTORS
; i
++)
2765 if (nds32_isr_vectors
[i
].category
!= NDS32_ISR_NONE
)
2768 if (i
== NDS32_N_ISR_VECTORS
)
2771 /* At least one vector is NOT NDS32_ISR_NONE,
2772 we should output isr vector information. */
2773 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2774 fprintf (asm_out_file
, "\t! The isr vector information:\n");
2775 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2777 /* Check reset handler first. Its vector number is always 0. */
2778 if (nds32_isr_vectors
[0].category
== NDS32_ISR_RESET
)
2780 nds32_emit_isr_reset_content ();
2781 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2784 /* Check other vectors, starting from vector number 1. */
2785 for (i
= 1; i
< NDS32_N_ISR_VECTORS
; i
++)
2787 if (nds32_isr_vectors
[i
].category
== NDS32_ISR_INTERRUPT
2788 || nds32_isr_vectors
[i
].category
== NDS32_ISR_EXCEPTION
)
2790 /* Found one vector which is interupt or exception.
2791 Output its jmptbl and vector section content. */
2792 fprintf (asm_out_file
, "\t! interrupt/exception vector %02d\n", i
);
2793 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2794 nds32_emit_isr_jmptbl_section (i
);
2795 fprintf (asm_out_file
, "\t! ....................................\n");
2796 nds32_emit_isr_vector_section (i
);
2797 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2801 fprintf (asm_out_file
, "\t! ------------------------------------\n");
2804 /* -- Output and Generation of Labels. */
2807 nds32_asm_globalize_label (FILE *stream
, const char *name
)
2809 fputs ("\t.global\t", stream
);
2810 assemble_name (stream
, name
);
2811 fputs ("\n", stream
);
2814 /* -- Output of Assembler Instructions. */
2817 nds32_print_operand (FILE *stream
, rtx x
, int code
)
2824 /* Do nothing special. */
2828 /* 'x' is supposed to be CONST_INT, get the value. */
2829 gcc_assert (CONST_INT_P (x
));
2830 op_value
= INTVAL (x
);
2832 /* According to the Andes architecture,
2833 the system/user register index range is 0 ~ 1023.
2834 In order to avoid conflict between user-specified-integer value
2835 and enum-specified-register value,
2836 the 'enum nds32_intrinsic_registers' value
2837 in nds32_intrinsic.h starts from 1024. */
2838 if (op_value
< 1024 && op_value
>= 0)
2840 /* If user gives integer value directly (0~1023),
2841 we just print out the value. */
2842 fprintf (stream
, "%d", op_value
);
2844 else if (op_value
< 0
2845 || op_value
>= ((int) ARRAY_SIZE (nds32_intrinsic_register_names
)
2848 /* The enum index value for array size is out of range. */
2849 error ("intrinsic register index is out of range");
2853 /* If user applies normal way with __NDS32_REG_XXX__ enum data,
2854 we can print out register name. Remember to substract 1024. */
2855 fprintf (stream
, "%s",
2856 nds32_intrinsic_register_names
[op_value
- 1024]);
2859 /* No need to handle following process, so return immediately. */
2864 output_operand_lossage ("invalid operand output code");
2868 switch (GET_CODE (x
))
2872 output_addr_const (stream
, x
);
2876 /* Forbid using static chain register ($r16)
2877 on reduced-set registers configuration. */
2878 if (TARGET_REDUCED_REGS
2879 && REGNO (x
) == STATIC_CHAIN_REGNUM
)
2880 sorry ("a nested function is not supported for reduced registers");
2882 /* Normal cases, print out register name. */
2883 fputs (reg_names
[REGNO (x
)], stream
);
2887 output_address (XEXP (x
, 0));
2893 output_addr_const (stream
, x
);
2897 /* Generally, output_addr_const () is able to handle most cases.
2898 We want to see what CODE could appear,
2899 so we use gcc_unreachable() to stop it. */
2907 nds32_print_operand_address (FILE *stream
, rtx x
)
2911 switch (GET_CODE (x
))
2915 /* [ + symbol_ref] */
2916 /* [ + const_addr], where const_addr = symbol_ref + const_int */
2917 fputs ("[ + ", stream
);
2918 output_addr_const (stream
, x
);
2919 fputs ("]", stream
);
2923 /* Forbid using static chain register ($r16)
2924 on reduced-set registers configuration. */
2925 if (TARGET_REDUCED_REGS
2926 && REGNO (x
) == STATIC_CHAIN_REGNUM
)
2927 sorry ("a nested function is not supported for reduced registers");
2930 fprintf (stream
, "[%s]", reg_names
[REGNO (x
)]);
2937 /* Checking op0, forbid using static chain register ($r16)
2938 on reduced-set registers configuration. */
2939 if (TARGET_REDUCED_REGS
2941 && REGNO (op0
) == STATIC_CHAIN_REGNUM
)
2942 sorry ("a nested function is not supported for reduced registers");
2943 /* Checking op1, forbid using static chain register ($r16)
2944 on reduced-set registers configuration. */
2945 if (TARGET_REDUCED_REGS
2947 && REGNO (op1
) == STATIC_CHAIN_REGNUM
)
2948 sorry ("a nested function is not supported for reduced registers");
2950 if (REG_P (op0
) && CONST_INT_P (op1
))
2953 fprintf (stream
, "[%s + (%d)]",
2954 reg_names
[REGNO (op0
)], (int)INTVAL (op1
));
2956 else if (REG_P (op0
) && REG_P (op1
))
2959 fprintf (stream
, "[%s + %s]",
2960 reg_names
[REGNO (op0
)], reg_names
[REGNO (op1
)]);
2962 else if (GET_CODE (op0
) == MULT
&& REG_P (op1
))
2965 From observation, the pattern looks like:
2966 (plus:SI (mult:SI (reg:SI 58)
2967 (const_int 4 [0x4]))
2971 /* We need to set sv to output shift value. */
2972 if (INTVAL (XEXP (op0
, 1)) == 1)
2974 else if (INTVAL (XEXP (op0
, 1)) == 2)
2976 else if (INTVAL (XEXP (op0
, 1)) == 4)
2981 fprintf (stream
, "[%s + %s << %d]",
2982 reg_names
[REGNO (op1
)],
2983 reg_names
[REGNO (XEXP (op0
, 0))],
2988 /* The control flow is not supposed to be here. */
2996 /* (post_modify (regA) (plus (regA) (regB)))
2997 (post_modify (regA) (plus (regA) (const_int)))
2998 We would like to extract
2999 regA and regB (or const_int) from plus rtx. */
3000 op0
= XEXP (XEXP (x
, 1), 0);
3001 op1
= XEXP (XEXP (x
, 1), 1);
3003 /* Checking op0, forbid using static chain register ($r16)
3004 on reduced-set registers configuration. */
3005 if (TARGET_REDUCED_REGS
3007 && REGNO (op0
) == STATIC_CHAIN_REGNUM
)
3008 sorry ("a nested function is not supported for reduced registers");
3009 /* Checking op1, forbid using static chain register ($r16)
3010 on reduced-set registers configuration. */
3011 if (TARGET_REDUCED_REGS
3013 && REGNO (op1
) == STATIC_CHAIN_REGNUM
)
3014 sorry ("a nested function is not supported for reduced registers");
3016 if (REG_P (op0
) && REG_P (op1
))
3019 fprintf (stream
, "[%s], %s",
3020 reg_names
[REGNO (op0
)], reg_names
[REGNO (op1
)]);
3022 else if (REG_P (op0
) && CONST_INT_P (op1
))
3025 fprintf (stream
, "[%s], %d",
3026 reg_names
[REGNO (op0
)], (int)INTVAL (op1
));
3030 /* The control flow is not supposed to be here. */
3041 /* Checking op0, forbid using static chain register ($r16)
3042 on reduced-set registers configuration. */
3043 if (TARGET_REDUCED_REGS
3045 && REGNO (op0
) == STATIC_CHAIN_REGNUM
)
3046 sorry ("a nested function is not supported for reduced registers");
3050 /* "[Ra], 1/2/4" or "[Ra], -1/-2/-4"
3051 The 1/2/4 or -1/-2/-4 have been displayed in nds32.md.
3052 We only need to deal with register Ra. */
3053 fprintf (stream
, "[%s]", reg_names
[REGNO (op0
)]);
3057 /* The control flow is not supposed to be here. */
3065 /* Generally, output_addr_const () is able to handle most cases.
3066 We want to see what CODE could appear,
3067 so we use gcc_unreachable() to stop it. */
3075 /* Defining target-specific uses of __attribute__. */
3077 /* Add some checking after merging attributes. */
3079 nds32_merge_decl_attributes (tree olddecl
, tree newdecl
)
3081 tree combined_attrs
;
3083 /* Create combined attributes. */
3084 combined_attrs
= merge_attributes (DECL_ATTRIBUTES (olddecl
),
3085 DECL_ATTRIBUTES (newdecl
));
3087 /* Sinc newdecl is acutally a duplicate of olddecl,
3088 we can take olddecl for some operations. */
3089 if (TREE_CODE (olddecl
) == FUNCTION_DECL
)
3091 /* Check isr-specific attributes conflict. */
3092 nds32_check_isr_attrs_conflict (olddecl
, combined_attrs
);
3095 return combined_attrs
;
3098 /* Add some checking when inserting attributes. */
3100 nds32_insert_attributes (tree decl
, tree
*attributes
)
3102 /* For function declaration, we need to check isr-specific attributes:
3103 1. Call nds32_check_isr_attrs_conflict() to check any conflict.
3104 2. Check valid integer value for interrupt/exception.
3105 3. Check valid integer value for reset.
3106 4. Check valid function for nmi/warm. */
3107 if (TREE_CODE (decl
) == FUNCTION_DECL
)
3110 tree intr
, excp
, reset
;
3112 /* Pick up function attributes. */
3113 func_attrs
= *attributes
;
3115 /* 1. Call nds32_check_isr_attrs_conflict() to check any conflict. */
3116 nds32_check_isr_attrs_conflict (decl
, func_attrs
);
3118 /* Now we are starting to check valid id value
3119 for interrupt/exception/reset.
3120 Note that we ONLY check its validity here.
3121 To construct isr vector information, it is still performed
3122 by nds32_construct_isr_vectors_information(). */
3123 intr
= lookup_attribute ("interrupt", func_attrs
);
3124 excp
= lookup_attribute ("exception", func_attrs
);
3125 reset
= lookup_attribute ("reset", func_attrs
);
3129 /* Deal with interrupt/exception. */
3131 unsigned int lower_bound
, upper_bound
;
3133 /* The way to handle interrupt or exception is the same,
3134 we just need to take care of actual vector number.
3135 For interrupt(0..63), the actual vector number is (9..72).
3136 For exception(1..8), the actual vector number is (1..8). */
3137 lower_bound
= (intr
) ? (0) : (1);
3138 upper_bound
= (intr
) ? (63) : (8);
3140 /* Prepare id list so that we can traverse id value. */
3141 id_list
= (intr
) ? (TREE_VALUE (intr
)) : (TREE_VALUE (excp
));
3143 /* 2. Check valid integer value for interrupt/exception. */
3148 /* Pick up each vector id value. */
3149 id
= TREE_VALUE (id_list
);
3150 /* Issue error if it is not a valid integer value. */
3151 if (TREE_CODE (id
) != INTEGER_CST
3152 || TREE_INT_CST_LOW (id
) < lower_bound
3153 || TREE_INT_CST_LOW (id
) > upper_bound
)
3154 error ("invalid id value for interrupt/exception attribute");
3156 /* Advance to next id. */
3157 id_list
= TREE_CHAIN (id_list
);
3162 /* Deal with reset. */
3166 unsigned int lower_bound
;
3167 unsigned int upper_bound
;
3169 /* Prepare id_list and identify id value so that
3170 we can check if total number of vectors is valid. */
3171 id_list
= TREE_VALUE (reset
);
3172 id
= TREE_VALUE (id_list
);
3174 /* The maximum numbers for user's interrupt is 64. */
3178 /* 3. Check valid integer value for reset. */
3179 if (TREE_CODE (id
) != INTEGER_CST
3180 || TREE_INT_CST_LOW (id
) < lower_bound
3181 || TREE_INT_CST_LOW (id
) > upper_bound
)
3182 error ("invalid id value for reset attribute");
3184 /* 4. Check valid function for nmi/warm. */
3185 nmi
= lookup_attribute ("nmi", func_attrs
);
3186 warm
= lookup_attribute ("warm", func_attrs
);
3188 if (nmi
!= NULL_TREE
)
3193 nmi_func_list
= TREE_VALUE (nmi
);
3194 nmi_func
= TREE_VALUE (nmi_func_list
);
3196 /* Issue error if it is not a valid nmi function. */
3197 if (TREE_CODE (nmi_func
) != IDENTIFIER_NODE
)
3198 error ("invalid nmi function for reset attribute");
3201 if (warm
!= NULL_TREE
)
3203 tree warm_func_list
;
3206 warm_func_list
= TREE_VALUE (warm
);
3207 warm_func
= TREE_VALUE (warm_func_list
);
3209 /* Issue error if it is not a valid warm function. */
3210 if (TREE_CODE (warm_func
) != IDENTIFIER_NODE
)
3211 error ("invalid warm function for reset attribute");
3216 /* No interrupt, exception, or reset attribute is set. */
3223 nds32_option_pragma_parse (tree args ATTRIBUTE_UNUSED
,
3224 tree pop_target ATTRIBUTE_UNUSED
)
3226 /* Currently, we do not parse any pragma target by ourself,
3227 so just simply return false. */
3232 nds32_option_override (void)
3234 /* After all the command options have been parsed,
3235 we shall deal with some flags for changing compiler settings. */
3237 /* At first, we check if we have to strictly
3238 set some flags based on ISA family. */
3241 /* Under V2 ISA, we need to strictly disable TARGET_V3PUSH. */
3242 target_flags
&= ~MASK_V3PUSH
;
3246 /* Under V3 ISA, currently nothing should be strictly set. */
3250 /* Under V3M ISA, we need to strictly enable TARGET_REDUCED_REGS. */
3251 target_flags
|= MASK_REDUCED_REGS
;
3252 /* Under V3M ISA, we need to strictly disable TARGET_PERF_EXT. */
3253 target_flags
&= ~MASK_PERF_EXT
;
3256 /* See if we are using reduced-set registers:
3257 $r0~$r5, $r6~$r10, $r15, $r28, $r29, $r30, $r31
3258 If so, we must forbid using $r11~$r14, $r16~$r27. */
3259 if (TARGET_REDUCED_REGS
)
3263 /* Prevent register allocator from
3264 choosing it as doing register allocation. */
3265 for (r
= 11; r
<= 14; r
++)
3266 fixed_regs
[r
] = call_used_regs
[r
] = 1;
3267 for (r
= 16; r
<= 27; r
++)
3268 fixed_regs
[r
] = call_used_regs
[r
] = 1;
3271 /* See if user explicitly would like to use fp-as-gp optimization.
3272 If so, we must prevent $fp from being allocated
3273 during register allocation. */
3274 if (TARGET_FORCE_FP_AS_GP
)
3275 fixed_regs
[FP_REGNUM
] = call_used_regs
[FP_REGNUM
] = 1;
3279 /* Under no 16 bit ISA, we need to strictly disable TARGET_V3PUSH. */
3280 target_flags
&= ~MASK_V3PUSH
;
3283 /* Currently, we don't support PIC code generation yet. */
3285 sorry ("not support -fpic");
3289 /* Miscellaneous Parameters. */
3292 nds32_init_builtins (void)
3294 tree pointer_type_node
= build_pointer_type (integer_type_node
);
3296 tree void_ftype_void
= build_function_type (void_type_node
,
3299 tree void_ftype_pint
= build_function_type_list (void_type_node
,
3303 tree int_ftype_int
= build_function_type_list (integer_type_node
,
3307 tree void_ftype_int_int
= build_function_type_list (void_type_node
,
3313 add_builtin_function ("__builtin_nds32_isync", void_ftype_pint
,
3314 NDS32_BUILTIN_ISYNC
,
3315 BUILT_IN_MD
, NULL
, NULL_TREE
);
3316 add_builtin_function ("__builtin_nds32_isb", void_ftype_void
,
3318 BUILT_IN_MD
, NULL
, NULL_TREE
);
3320 /* Register Transfer. */
3321 add_builtin_function ("__builtin_nds32_mfsr", int_ftype_int
,
3323 BUILT_IN_MD
, NULL
, NULL_TREE
);
3324 add_builtin_function ("__builtin_nds32_mfusr", int_ftype_int
,
3325 NDS32_BUILTIN_MFUSR
,
3326 BUILT_IN_MD
, NULL
, NULL_TREE
);
3327 add_builtin_function ("__builtin_nds32_mtsr", void_ftype_int_int
,
3329 BUILT_IN_MD
, NULL
, NULL_TREE
);
3330 add_builtin_function ("__builtin_nds32_mtusr", void_ftype_int_int
,
3331 NDS32_BUILTIN_MTUSR
,
3332 BUILT_IN_MD
, NULL
, NULL_TREE
);
3335 add_builtin_function ("__builtin_nds32_setgie_en", void_ftype_void
,
3336 NDS32_BUILTIN_SETGIE_EN
,
3337 BUILT_IN_MD
, NULL
, NULL_TREE
);
3338 add_builtin_function ("__builtin_nds32_setgie_dis", void_ftype_void
,
3339 NDS32_BUILTIN_SETGIE_DIS
,
3340 BUILT_IN_MD
, NULL
, NULL_TREE
);
3344 nds32_expand_builtin (tree exp
,
3346 rtx subtarget ATTRIBUTE_UNUSED
,
3347 enum machine_mode mode ATTRIBUTE_UNUSED
,
3348 int ignore ATTRIBUTE_UNUSED
)
3350 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
3352 int fcode
= DECL_FUNCTION_CODE (fndecl
);
3357 case NDS32_BUILTIN_ISYNC
:
3358 return nds32_expand_builtin_null_ftype_reg
3359 (CODE_FOR_unspec_volatile_isync
, exp
, target
);
3360 case NDS32_BUILTIN_ISB
:
3361 /* Since there are no result and operands for isb instruciton,
3362 we can simply emit this rtx. */
3363 emit_insn (gen_unspec_volatile_isb ());
3366 /* Register Transfer. */
3367 case NDS32_BUILTIN_MFSR
:
3368 return nds32_expand_builtin_reg_ftype_imm
3369 (CODE_FOR_unspec_volatile_mfsr
, exp
, target
);
3370 case NDS32_BUILTIN_MFUSR
:
3371 return nds32_expand_builtin_reg_ftype_imm
3372 (CODE_FOR_unspec_volatile_mfusr
, exp
, target
);
3373 case NDS32_BUILTIN_MTSR
:
3374 return nds32_expand_builtin_null_ftype_reg_imm
3375 (CODE_FOR_unspec_volatile_mtsr
, exp
, target
);
3376 case NDS32_BUILTIN_MTUSR
:
3377 return nds32_expand_builtin_null_ftype_reg_imm
3378 (CODE_FOR_unspec_volatile_mtusr
, exp
, target
);
3381 case NDS32_BUILTIN_SETGIE_EN
:
3382 /* Since there are no result and operands for setgie.e instruciton,
3383 we can simply emit this rtx. */
3384 emit_insn (gen_unspec_volatile_setgie_en ());
3386 case NDS32_BUILTIN_SETGIE_DIS
:
3387 /* Since there are no result and operands for setgie.d instruciton,
3388 we can simply emit this rtx. */
3389 emit_insn (gen_unspec_volatile_setgie_dis ());
3400 /* ------------------------------------------------------------------------ */
3402 /* PART 4: Implemet extern function definitions,
3403 the prototype is in nds32-protos.h. */
3405 /* Defining Data Structures for Per-function Information. */
3408 nds32_init_expanders (void)
3410 /* Arrange to initialize and mark the machine per-function status. */
3411 init_machine_status
= nds32_init_machine_status
;
3415 /* Register Usage. */
3417 /* -- How Values Fit in Registers. */
3420 nds32_hard_regno_nregs (int regno ATTRIBUTE_UNUSED
,
3421 enum machine_mode mode
)
3423 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
);
3427 nds32_hard_regno_mode_ok (int regno
, enum machine_mode mode
)
3429 /* Restrict double-word quantities to even register pairs. */
3430 if (HARD_REGNO_NREGS (regno
, mode
) == 1
3438 /* Register Classes. */
3441 nds32_regno_reg_class (int regno
)
3443 /* Refer to nds32.h for more register class details. */
3445 if (regno
>= 0 && regno
<= 7)
3447 else if (regno
>= 8 && regno
<= 11)
3449 else if (regno
>= 12 && regno
<= 14)
3451 else if (regno
== 15)
3453 else if (regno
>= 16 && regno
<= 19)
3455 else if (regno
>= 20 && regno
<= 31)
3457 else if (regno
== 32 || regno
== 33)
3464 /* Stack Layout and Calling Conventions. */
3466 /* -- Basic Stack Layout. */
3469 nds32_return_addr_rtx (int count
,
3470 rtx frameaddr ATTRIBUTE_UNUSED
)
3472 /* There is no way to determine the return address
3473 if frameaddr is the frame that has 'count' steps
3474 up from current frame. */
3478 /* If count == 0, it means we are at current frame,
3479 the return address is $r30 ($lp). */
3480 return get_hard_reg_initial_val (Pmode
, LP_REGNUM
);
3483 /* -- Eliminating Frame Pointer and Arg Pointer. */
3486 nds32_initial_elimination_offset (unsigned int from_reg
, unsigned int to_reg
)
3488 HOST_WIDE_INT offset
;
3490 /* Compute and setup stack frame size.
3491 The result will be in cfun->machine. */
3492 nds32_compute_stack_frame ();
3494 /* Remember to consider
3495 cfun->machine->callee_saved_area_padding_bytes
3496 when calculating offset. */
3497 if (from_reg
== ARG_POINTER_REGNUM
&& to_reg
== STACK_POINTER_REGNUM
)
3499 offset
= (cfun
->machine
->fp_size
3500 + cfun
->machine
->gp_size
3501 + cfun
->machine
->lp_size
3502 + cfun
->machine
->callee_saved_regs_size
3503 + cfun
->machine
->callee_saved_area_padding_bytes
3504 + cfun
->machine
->local_size
3505 + cfun
->machine
->out_args_size
);
3507 else if (from_reg
== ARG_POINTER_REGNUM
3508 && to_reg
== HARD_FRAME_POINTER_REGNUM
)
3512 else if (from_reg
== FRAME_POINTER_REGNUM
3513 && to_reg
== STACK_POINTER_REGNUM
)
3515 offset
= (cfun
->machine
->local_size
+ cfun
->machine
->out_args_size
);
3517 else if (from_reg
== FRAME_POINTER_REGNUM
3518 && to_reg
== HARD_FRAME_POINTER_REGNUM
)
3520 offset
= (-1) * (cfun
->machine
->fp_size
3521 + cfun
->machine
->gp_size
3522 + cfun
->machine
->lp_size
3523 + cfun
->machine
->callee_saved_regs_size
3524 + cfun
->machine
->callee_saved_area_padding_bytes
);
3534 /* -- Passing Arguments in Registers. */
3537 nds32_init_cumulative_args (CUMULATIVE_ARGS
*cum
,
3538 tree fntype ATTRIBUTE_UNUSED
,
3539 rtx libname ATTRIBUTE_UNUSED
,
3540 tree fndecl ATTRIBUTE_UNUSED
,
3541 int n_named_args ATTRIBUTE_UNUSED
)
3543 /* Initial available registers
3544 (in offset, corresponding to NDS32_GPR_ARG_FIRST_REGNUM)
3545 for passing arguments. */
3546 cum
->reg_offset
= 0;
3549 /* -- Function Entry and Exit. */
3551 /* Function for normal multiple push prologue. */
3553 nds32_expand_prologue (void)
3561 rtx fp_adjust_insn
, sp_adjust_insn
;
3563 /* Before computing everything for stack frame size,
3564 we check if it is still worth to use fp_as_gp optimization.
3565 If it is, the 'df_regs_ever_live_p (FP_REGNUM)' will be set
3566 so that $fp will be saved on stack. */
3567 cfun
->machine
->fp_as_gp_p
= nds32_fp_as_gp_check_available ();
3569 /* Compute and setup stack frame size.
3570 The result will be in cfun->machine. */
3571 nds32_compute_stack_frame ();
3573 /* If the function is 'naked',
3574 we do not have to generate prologue code fragment. */
3575 if (cfun
->machine
->naked_p
)
3578 /* Get callee_first_regno and callee_last_regno. */
3579 Rb
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_first_regno
);
3580 Re
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_last_regno
);
3582 /* push_insn = gen_stack_push_multiple(first_regno, last_regno),
3583 the pattern 'stack_push_multiple' is implemented in nds32.md.
3584 For En4 field, we have to calculate its constant value.
3585 Refer to Andes ISA for more information. */
3587 if (cfun
->machine
->fp_size
)
3589 if (cfun
->machine
->gp_size
)
3591 if (cfun
->machine
->lp_size
)
3594 /* If $fp, $gp, $lp, and all callee-save registers are NOT required
3595 to be saved, we don't have to create multiple push instruction.
3596 Otherwise, a multiple push instruction is needed. */
3597 if (!(REGNO (Rb
) == SP_REGNUM
&& REGNO (Re
) == SP_REGNUM
&& en4_const
== 0))
3599 /* Create multiple push instruction rtx. */
3600 push_insn
= nds32_gen_stack_push_multiple (Rb
, Re
, GEN_INT (en4_const
));
3601 /* Emit rtx into instructions list and receive INSN rtx form. */
3602 push_insn
= emit_insn (push_insn
);
3604 /* The insn rtx 'push_insn' will change frame layout.
3605 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3606 generate CFI (Call Frame Information) stuff. */
3607 RTX_FRAME_RELATED_P (push_insn
) = 1;
3610 /* Check frame_pointer_needed to see
3611 if we shall emit fp adjustment instruction. */
3612 if (frame_pointer_needed
)
3614 /* adjust $fp = $sp + ($fp size) + ($gp size) + ($lp size)
3615 + (4 * callee-saved-registers)
3616 Note: No need to adjust
3617 cfun->machine->callee_saved_area_padding_bytes,
3618 because, at this point, stack pointer is just
3619 at the position after push instruction. */
3620 fp_adjust
= cfun
->machine
->fp_size
3621 + cfun
->machine
->gp_size
3622 + cfun
->machine
->lp_size
3623 + cfun
->machine
->callee_saved_regs_size
;
3624 fp_adjust_insn
= gen_addsi3 (hard_frame_pointer_rtx
,
3626 GEN_INT (fp_adjust
));
3627 /* Emit rtx into instructions list and receive INSN rtx form. */
3628 fp_adjust_insn
= emit_insn (fp_adjust_insn
);
3631 /* Adjust $sp = $sp - local_size - out_args_size
3632 - callee_saved_area_padding_bytes. */
3633 sp_adjust
= cfun
->machine
->local_size
3634 + cfun
->machine
->out_args_size
3635 + cfun
->machine
->callee_saved_area_padding_bytes
;
3636 /* sp_adjust value may be out of range of the addi instruction,
3637 create alternative add behavior with TA_REGNUM if necessary,
3638 using NEGATIVE value to tell that we are decreasing address. */
3639 sp_adjust
= nds32_force_addi_stack_int ( (-1) * sp_adjust
);
3642 /* Generate sp adjustment instruction if and only if sp_adjust != 0. */
3643 sp_adjust_insn
= gen_addsi3 (stack_pointer_rtx
,
3645 GEN_INT (-1 * sp_adjust
));
3646 /* Emit rtx into instructions list and receive INSN rtx form. */
3647 sp_adjust_insn
= emit_insn (sp_adjust_insn
);
3649 /* The insn rtx 'sp_adjust_insn' will change frame layout.
3650 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3651 generate CFI (Call Frame Information) stuff. */
3652 RTX_FRAME_RELATED_P (sp_adjust_insn
) = 1;
3655 /* Prevent the instruction scheduler from
3656 moving instructions across the boundary. */
3657 emit_insn (gen_blockage ());
3660 /* Function for normal multiple pop epilogue. */
3662 nds32_expand_epilogue (void)
3671 /* Compute and setup stack frame size.
3672 The result will be in cfun->machine. */
3673 nds32_compute_stack_frame ();
3675 /* Prevent the instruction scheduler from
3676 moving instructions across the boundary. */
3677 emit_insn (gen_blockage ());
3679 /* If the function is 'naked', we do not have to generate
3680 epilogue code fragment BUT 'ret' instruction. */
3681 if (cfun
->machine
->naked_p
)
3683 /* Generate return instruction by using
3684 unspec_volatile_func_return pattern.
3685 Make sure this instruction is after gen_blockage().
3686 NOTE that $lp will become 'live'
3687 after this instruction has been emitted. */
3688 emit_insn (gen_unspec_volatile_func_return ());
3692 if (frame_pointer_needed
)
3694 /* adjust $sp = $fp - ($fp size) - ($gp size) - ($lp size)
3695 - (4 * callee-saved-registers)
3696 Note: No need to adjust
3697 cfun->machine->callee_saved_area_padding_bytes,
3698 because we want to adjust stack pointer
3699 to the position for pop instruction. */
3700 sp_adjust
= cfun
->machine
->fp_size
3701 + cfun
->machine
->gp_size
3702 + cfun
->machine
->lp_size
3703 + cfun
->machine
->callee_saved_regs_size
;
3704 sp_adjust_insn
= gen_addsi3 (stack_pointer_rtx
,
3705 hard_frame_pointer_rtx
,
3706 GEN_INT (-1 * sp_adjust
));
3707 /* Emit rtx into instructions list and receive INSN rtx form. */
3708 sp_adjust_insn
= emit_insn (sp_adjust_insn
);
3712 /* If frame pointer is NOT needed,
3713 we cannot calculate the sp adjustment from frame pointer.
3714 Instead, we calculate the adjustment by local_size,
3715 out_args_size, and callee_saved_area_padding_bytes.
3716 Notice that such sp adjustment value may be out of range,
3717 so we have to deal with it as well. */
3719 /* Adjust $sp = $sp + local_size + out_args_size
3720 + callee_saved_area_padding_bytes. */
3721 sp_adjust
= cfun
->machine
->local_size
3722 + cfun
->machine
->out_args_size
3723 + cfun
->machine
->callee_saved_area_padding_bytes
;
3724 /* sp_adjust value may be out of range of the addi instruction,
3725 create alternative add behavior with TA_REGNUM if necessary,
3726 using POSITIVE value to tell that we are increasing address. */
3727 sp_adjust
= nds32_force_addi_stack_int (sp_adjust
);
3730 /* Generate sp adjustment instruction
3731 if and only if sp_adjust != 0. */
3732 sp_adjust_insn
= gen_addsi3 (stack_pointer_rtx
,
3734 GEN_INT (sp_adjust
));
3735 /* Emit rtx into instructions list and receive INSN rtx form. */
3736 sp_adjust_insn
= emit_insn (sp_adjust_insn
);
3740 /* Get callee_first_regno and callee_last_regno. */
3741 Rb
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_first_regno
);
3742 Re
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_last_regno
);
3744 /* pop_insn = gen_stack_pop_multiple(first_regno, last_regno),
3745 the pattern 'stack_pop_multiple' is implementad in nds32.md.
3746 For En4 field, we have to calculate its constant value.
3747 Refer to Andes ISA for more information. */
3749 if (cfun
->machine
->fp_size
)
3751 if (cfun
->machine
->gp_size
)
3753 if (cfun
->machine
->lp_size
)
3756 /* If $fp, $gp, $lp, and all callee-save registers are NOT required
3757 to be saved, we don't have to create multiple pop instruction.
3758 Otherwise, a multiple pop instruction is needed. */
3759 if (!(REGNO (Rb
) == SP_REGNUM
&& REGNO (Re
) == SP_REGNUM
&& en4_const
== 0))
3761 /* Create multiple pop instruction rtx. */
3762 pop_insn
= nds32_gen_stack_pop_multiple (Rb
, Re
, GEN_INT (en4_const
));
3763 /* Emit pop instruction. */
3764 emit_insn (pop_insn
);
3767 /* Generate return instruction by using
3768 unspec_volatile_func_return pattern. */
3769 emit_insn (gen_unspec_volatile_func_return ());
3772 /* Function for v3push prologue. */
3774 nds32_expand_prologue_v3push (void)
3781 rtx fp_adjust_insn
, sp_adjust_insn
;
3783 /* Before computing everything for stack frame size,
3784 we check if it is still worth to use fp_as_gp optimization.
3785 If it is, the 'df_regs_ever_live_p (FP_REGNUM)' will be set
3786 so that $fp will be saved on stack. */
3787 cfun
->machine
->fp_as_gp_p
= nds32_fp_as_gp_check_available ();
3789 /* Compute and setup stack frame size.
3790 The result will be in cfun->machine. */
3791 nds32_compute_stack_frame ();
3793 /* If the function is 'naked',
3794 we do not have to generate prologue code fragment. */
3795 if (cfun
->machine
->naked_p
)
3798 /* Get callee_first_regno and callee_last_regno. */
3799 Rb
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_first_regno
);
3800 Re
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_last_regno
);
3802 /* Calculate sp_adjust first to test if 'push25 Re,imm8u' is available,
3803 where imm8u has to be 8-byte alignment. */
3804 sp_adjust
= cfun
->machine
->local_size
3805 + cfun
->machine
->out_args_size
3806 + cfun
->machine
->callee_saved_area_padding_bytes
;
3808 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust
))
3809 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust
))
3811 /* We can use 'push25 Re,imm8u'. */
3813 /* push_insn = gen_stack_v3push(last_regno, sp_adjust),
3814 the pattern 'stack_v3push' is implemented in nds32.md.
3815 The (const_int 14) means v3push always push { $fp $gp $lp }. */
3816 push_insn
= nds32_gen_stack_v3push (Rb
, Re
,
3817 GEN_INT (14), GEN_INT (sp_adjust
));
3818 /* emit rtx into instructions list and receive INSN rtx form */
3819 push_insn
= emit_insn (push_insn
);
3821 /* The insn rtx 'push_insn' will change frame layout.
3822 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3823 generate CFI (Call Frame Information) stuff. */
3824 RTX_FRAME_RELATED_P (push_insn
) = 1;
3826 /* Check frame_pointer_needed to see
3827 if we shall emit fp adjustment instruction. */
3828 if (frame_pointer_needed
)
3830 /* adjust $fp = $sp + 4 ($fp size)
3833 + (4 * n) (callee-saved registers)
3834 + sp_adjust ('push25 Re,imm8u')
3835 Note: Since we use 'push25 Re,imm8u',
3836 the position of stack pointer is further
3837 changed after push instruction.
3838 Hence, we need to take sp_adjust value
3839 into consideration. */
3840 fp_adjust
= cfun
->machine
->fp_size
3841 + cfun
->machine
->gp_size
3842 + cfun
->machine
->lp_size
3843 + cfun
->machine
->callee_saved_regs_size
3845 fp_adjust_insn
= gen_addsi3 (hard_frame_pointer_rtx
,
3847 GEN_INT (fp_adjust
));
3848 /* Emit rtx into instructions list and receive INSN rtx form. */
3849 fp_adjust_insn
= emit_insn (fp_adjust_insn
);
3854 /* We have to use 'push25 Re,0' and
3855 expand one more instruction to adjust $sp later. */
3857 /* push_insn = gen_stack_v3push(last_regno, sp_adjust),
3858 the pattern 'stack_v3push' is implemented in nds32.md.
3859 The (const_int 14) means v3push always push { $fp $gp $lp }. */
3860 push_insn
= nds32_gen_stack_v3push (Rb
, Re
,
3861 GEN_INT (14), GEN_INT (0));
3862 /* Emit rtx into instructions list and receive INSN rtx form. */
3863 push_insn
= emit_insn (push_insn
);
3865 /* The insn rtx 'push_insn' will change frame layout.
3866 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3867 generate CFI (Call Frame Information) stuff. */
3868 RTX_FRAME_RELATED_P (push_insn
) = 1;
3870 /* Check frame_pointer_needed to see
3871 if we shall emit fp adjustment instruction. */
3872 if (frame_pointer_needed
)
3874 /* adjust $fp = $sp + 4 ($fp size)
3877 + (4 * n) (callee-saved registers)
3878 Note: Since we use 'push25 Re,0',
3879 the stack pointer is just at the position
3880 after push instruction.
3881 No need to take sp_adjust into consideration. */
3882 fp_adjust
= cfun
->machine
->fp_size
3883 + cfun
->machine
->gp_size
3884 + cfun
->machine
->lp_size
3885 + cfun
->machine
->callee_saved_regs_size
;
3886 fp_adjust_insn
= gen_addsi3 (hard_frame_pointer_rtx
,
3888 GEN_INT (fp_adjust
));
3889 /* Emit rtx into instructions list and receive INSN rtx form. */
3890 fp_adjust_insn
= emit_insn (fp_adjust_insn
);
3893 /* Because we use 'push25 Re,0',
3894 we need to expand one more instruction to adjust $sp.
3895 However, sp_adjust value may be out of range of the addi instruction,
3896 create alternative add behavior with TA_REGNUM if necessary,
3897 using NEGATIVE value to tell that we are decreasing address. */
3898 sp_adjust
= nds32_force_addi_stack_int ( (-1) * sp_adjust
);
3901 /* Generate sp adjustment instruction
3902 if and only if sp_adjust != 0. */
3903 sp_adjust_insn
= gen_addsi3 (stack_pointer_rtx
,
3905 GEN_INT (-1 * sp_adjust
));
3906 /* Emit rtx into instructions list and receive INSN rtx form. */
3907 sp_adjust_insn
= emit_insn (sp_adjust_insn
);
3909 /* The insn rtx 'sp_adjust_insn' will change frame layout.
3910 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3911 generate CFI (Call Frame Information) stuff. */
3912 RTX_FRAME_RELATED_P (sp_adjust_insn
) = 1;
3916 /* Prevent the instruction scheduler from
3917 moving instructions across the boundary. */
3918 emit_insn (gen_blockage ());
3921 /* Function for v3pop epilogue. */
3923 nds32_expand_epilogue_v3pop (void)
3931 /* Compute and setup stack frame size.
3932 The result will be in cfun->machine. */
3933 nds32_compute_stack_frame ();
3935 /* Prevent the instruction scheduler from
3936 moving instructions across the boundary. */
3937 emit_insn (gen_blockage ());
3939 /* If the function is 'naked', we do not have to generate
3940 epilogue code fragment BUT 'ret' instruction. */
3941 if (cfun
->machine
->naked_p
)
3943 /* Generate return instruction by using
3944 unspec_volatile_func_return pattern.
3945 Make sure this instruction is after gen_blockage().
3946 NOTE that $lp will become 'live'
3947 after this instruction has been emitted. */
3948 emit_insn (gen_unspec_volatile_func_return ());
3952 /* Get callee_first_regno and callee_last_regno. */
3953 Rb
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_first_regno
);
3954 Re
= gen_rtx_REG (SImode
, cfun
->machine
->callee_saved_regs_last_regno
);
3956 /* Calculate sp_adjust first to test if 'pop25 Re,imm8u' is available,
3957 where imm8u has to be 8-byte alignment. */
3958 sp_adjust
= cfun
->machine
->local_size
3959 + cfun
->machine
->out_args_size
3960 + cfun
->machine
->callee_saved_area_padding_bytes
;
3962 /* We have to consider alloca issue as well.
3963 If the function does call alloca(), the stack pointer is not fixed.
3964 In that case, we cannot use 'pop25 Re,imm8u' directly.
3965 We have to caculate stack pointer from frame pointer
3966 and then use 'pop25 Re,0'.
3967 Of course, the frame_pointer_needed should be nonzero
3968 if the function calls alloca(). */
3969 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust
))
3970 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust
)
3971 && !cfun
->calls_alloca
)
3973 /* We can use 'pop25 Re,imm8u'. */
3975 /* pop_insn = gen_stack_v3pop(last_regno, sp_adjust),
3976 the pattern 'stack_v3pop' is implementad in nds32.md.
3977 The (const_int 14) means v3pop always pop { $fp $gp $lp }. */
3978 pop_insn
= nds32_gen_stack_v3pop (Rb
, Re
,
3979 GEN_INT (14), GEN_INT (sp_adjust
));
3981 /* Emit pop instruction. */
3982 emit_insn (pop_insn
);
3986 /* We have to use 'pop25 Re,0', and prior to it,
3987 we must expand one more instruction to adjust $sp. */
3989 if (frame_pointer_needed
)
3991 /* adjust $sp = $fp - 4 ($fp size)
3994 - (4 * n) (callee-saved registers)
3995 Note: No need to adjust
3996 cfun->machine->callee_saved_area_padding_bytes,
3997 because we want to adjust stack pointer
3998 to the position for pop instruction. */
3999 sp_adjust
= cfun
->machine
->fp_size
4000 + cfun
->machine
->gp_size
4001 + cfun
->machine
->lp_size
4002 + cfun
->machine
->callee_saved_regs_size
;
4003 sp_adjust_insn
= gen_addsi3 (stack_pointer_rtx
,
4004 hard_frame_pointer_rtx
,
4005 GEN_INT (-1 * sp_adjust
));
4006 /* Emit rtx into instructions list and receive INSN rtx form. */
4007 sp_adjust_insn
= emit_insn (sp_adjust_insn
);
4011 /* If frame pointer is NOT needed,
4012 we cannot calculate the sp adjustment from frame pointer.
4013 Instead, we calculate the adjustment by local_size,
4014 out_args_size, and callee_saved_area_padding_bytes.
4015 Notice that such sp adjustment value may be out of range,
4016 so we have to deal with it as well. */
4018 /* Adjust $sp = $sp + local_size + out_args_size
4019 + callee_saved_area_padding_bytes. */
4020 sp_adjust
= cfun
->machine
->local_size
4021 + cfun
->machine
->out_args_size
4022 + cfun
->machine
->callee_saved_area_padding_bytes
;
4023 /* sp_adjust value may be out of range of the addi instruction,
4024 create alternative add behavior with TA_REGNUM if necessary,
4025 using POSITIVE value to tell that we are increasing address. */
4026 sp_adjust
= nds32_force_addi_stack_int (sp_adjust
);
4029 /* Generate sp adjustment instruction
4030 if and only if sp_adjust != 0. */
4031 sp_adjust_insn
= gen_addsi3 (stack_pointer_rtx
,
4033 GEN_INT (sp_adjust
));
4034 /* Emit rtx into instructions list and receive INSN rtx form. */
4035 sp_adjust_insn
= emit_insn (sp_adjust_insn
);
4039 /* pop_insn = gen_stack_v3pop(last_regno, sp_adjust),
4040 the pattern 'stack_v3pop' is implementad in nds32.md. */
4041 /* The (const_int 14) means v3pop always pop { $fp $gp $lp }. */
4042 pop_insn
= nds32_gen_stack_v3pop (Rb
, Re
,
4043 GEN_INT (14), GEN_INT (0));
4045 /* Emit pop instruction. */
4046 emit_insn (pop_insn
);
4050 /* ------------------------------------------------------------------------ */
4052 /* Function to test 333-form for load/store instructions.
4053 This is auxiliary extern function for auxiliary macro in nds32.h.
4054 Because it is a little complicated, we use function instead of macro. */
4056 nds32_ls_333_p (rtx rt
, rtx ra
, rtx imm
, enum machine_mode mode
)
4058 if (REGNO_REG_CLASS (REGNO (rt
)) == LOW_REGS
4059 && REGNO_REG_CLASS (REGNO (ra
)) == LOW_REGS
)
4061 if (GET_MODE_SIZE (mode
) == 4)
4062 return satisfies_constraint_Iu05 (imm
);
4064 if (GET_MODE_SIZE (mode
) == 2)
4065 return satisfies_constraint_Iu04 (imm
);
4067 if (GET_MODE_SIZE (mode
) == 1)
4068 return satisfies_constraint_Iu03 (imm
);
4075 /* Functions to expand load_multiple and store_multiple.
4076 They are auxiliary extern functions to help create rtx template.
4077 Check nds32-multiple.md file for the patterns. */
4079 nds32_expand_load_multiple (int base_regno
, int count
,
4080 rtx base_addr
, rtx basemem
)
4085 rtx new_addr
, mem
, reg
;
4087 /* Create the pattern that is presented in nds32-multiple.md. */
4089 result
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (count
));
4091 for (par_index
= 0; par_index
< count
; par_index
++)
4093 offset
= par_index
* 4;
4094 /* 4-byte for loading data to each register. */
4095 new_addr
= plus_constant (Pmode
, base_addr
, offset
);
4096 mem
= adjust_automodify_address_nv (basemem
, SImode
,
4098 reg
= gen_rtx_REG (SImode
, base_regno
+ par_index
);
4100 XVECEXP (result
, 0, par_index
) = gen_rtx_SET (VOIDmode
, reg
, mem
);
4107 nds32_expand_store_multiple (int base_regno
, int count
,
4108 rtx base_addr
, rtx basemem
)
4113 rtx new_addr
, mem
, reg
;
4115 /* Create the pattern that is presented in nds32-multiple.md. */
4117 result
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (count
));
4119 for (par_index
= 0; par_index
< count
; par_index
++)
4121 offset
= par_index
* 4;
4122 /* 4-byte for storing data to memory. */
4123 new_addr
= plus_constant (Pmode
, base_addr
, offset
);
4124 mem
= adjust_automodify_address_nv (basemem
, SImode
,
4126 reg
= gen_rtx_REG (SImode
, base_regno
+ par_index
);
4128 XVECEXP (result
, 0, par_index
) = gen_rtx_SET (VOIDmode
, mem
, reg
);
4134 /* Function to move block memory content by
4135 using load_multiple and store_multiple.
4136 This is auxiliary extern function to help create rtx template.
4137 Check nds32-multiple.md file for the patterns. */
4139 nds32_expand_movmemqi (rtx dstmem
, rtx srcmem
, rtx total_bytes
, rtx alignment
)
4141 HOST_WIDE_INT in_words
, out_words
;
4142 rtx dst_base_reg
, src_base_reg
;
4145 /* Because reduced-set regsiters has few registers
4146 (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31'
4147 cannot be used for register allocation),
4148 using 8 registers (32 bytes) for moving memory block
4149 may easily consume all of them.
4150 It makes register allocation/spilling hard to work.
4151 So we only allow maximum=4 registers (16 bytes) for
4152 moving memory block under reduced-set registers. */
4153 if (TARGET_REDUCED_REGS
)
4158 /* 1. Total_bytes is integer for sure.
4159 2. Alignment is integer for sure.
4160 3. Maximum 4 or 8 registers, 4 * 4 = 16 bytes, 8 * 4 = 32 bytes.
4161 4. Requires (n * 4) block size.
4162 5. Requires 4-byte alignment. */
4163 if (GET_CODE (total_bytes
) != CONST_INT
4164 || GET_CODE (alignment
) != CONST_INT
4165 || INTVAL (total_bytes
) > maximum_bytes
4166 || INTVAL (total_bytes
) & 3
4167 || INTVAL (alignment
) & 3)
4170 dst_base_reg
= copy_to_mode_reg (SImode
, XEXP (dstmem
, 0));
4171 src_base_reg
= copy_to_mode_reg (SImode
, XEXP (srcmem
, 0));
4173 out_words
= in_words
= INTVAL (total_bytes
) / UNITS_PER_WORD
;
4175 emit_insn (nds32_expand_load_multiple (0, in_words
, src_base_reg
, srcmem
));
4176 emit_insn (nds32_expand_store_multiple (0, out_words
, dst_base_reg
, dstmem
));
4178 /* Successfully create patterns, return 1. */
4182 /* Function to check whether the OP is a valid load/store operation.
4183 This is a helper function for the predicates:
4184 'nds32_load_multiple_operation' and 'nds32_store_multiple_operation'
4185 in predicates.md file.
4187 The OP is supposed to be a parallel rtx.
4188 For each element within this parallel rtx:
4189 (set (reg) (mem addr)) is the form for load operation.
4190 (set (mem addr) (reg)) is the form for store operation.
4191 We have to extract reg and mem of every element and
4192 check if the information is valid for multiple load/store operation. */
4194 nds32_valid_multiple_load_store (rtx op
, bool load_p
)
4197 int first_elt_regno
;
4200 /* Get the counts of elements in the parallel rtx. */
4201 count
= XVECLEN (op
, 0);
4202 /* Pick up the first element. */
4203 elt
= XVECEXP (op
, 0, 0);
4205 /* Perform some quick check for the first element in the parallel rtx. */
4206 if (GET_CODE (elt
) != SET
4211 /* Pick up regno of first element for further detail checking.
4212 Note that the form is different between load and store operation. */
4215 if (GET_CODE (SET_DEST (elt
)) != REG
4216 || GET_CODE (SET_SRC (elt
)) != MEM
)
4219 first_elt_regno
= REGNO (SET_DEST (elt
));
4223 if (GET_CODE (SET_SRC (elt
)) != REG
4224 || GET_CODE (SET_DEST (elt
)) != MEM
)
4227 first_elt_regno
= REGNO (SET_SRC (elt
));
4230 /* Perform detail check for each element.
4231 Refer to nds32-multiple.md for more information
4232 about following checking.
4233 The starting element of parallel rtx is index 0. */
4234 if (!nds32_consecutive_registers_load_store_p (op
, load_p
, 0,
4239 /* Pass all test, this is a valid rtx. */
4243 /* Function to check whether the OP is a valid stack push/pop operation.
4244 For a valid stack operation, it must satisfy following conditions:
4245 1. Consecutive registers push/pop operations.
4246 2. Valid $fp/$gp/$lp push/pop operations.
4247 3. The last element must be stack adjustment rtx.
4248 See the prologue/epilogue implementation for details. */
4250 nds32_valid_stack_push_pop (rtx op
, bool push_p
)
4261 /* Get the counts of elements in the parallel rtx. */
4262 total_count
= XVECLEN (op
, 0);
4264 /* Perform some quick check for that every element should be 'set'. */
4265 for (index
= 0; index
< total_count
; index
++)
4267 elt
= XVECEXP (op
, 0, index
);
4268 if (GET_CODE (elt
) != SET
)
4272 /* For push operation, the parallel rtx looks like:
4273 (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
4275 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
4278 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
4280 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
4282 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
4284 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
4286 (set (reg:SI SP_REGNUM)
4287 (plus (reg:SI SP_REGNUM) (const_int -32)))])
4289 For pop operation, the parallel rtx looks like:
4290 (parallel [(set (reg:SI Rb)
4291 (mem (reg:SI SP_REGNUM)))
4293 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
4296 (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
4297 (set (reg:SI FP_REGNUM)
4298 (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
4299 (set (reg:SI GP_REGNUM)
4300 (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
4301 (set (reg:SI LP_REGNUM)
4302 (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
4303 (set (reg:SI SP_REGNUM)
4304 (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
4306 /* 1. Consecutive registers push/pop operations.
4307 We need to calculate how many registers should be consecutive.
4308 The $sp adjustment rtx, $fp push rtx, $gp push rtx,
4309 and $lp push rtx are excluded. */
4311 /* Exclude last $sp adjustment rtx. */
4312 rest_count
= total_count
- 1;
4313 /* Exclude $fp, $gp, and $lp if they are in the parallel rtx. */
4314 if (cfun
->machine
->fp_size
)
4316 if (cfun
->machine
->gp_size
)
4318 if (cfun
->machine
->lp_size
)
4323 elt
= XVECEXP (op
, 0, 0);
4324 /* Pick up register element. */
4325 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
4326 first_regno
= REGNO (elt_reg
);
4328 /* The 'push' operation is a kind of store operation.
4329 The 'pop' operation is a kind of load operation.
4330 Pass corresponding false/true as second argument (bool load_p).
4331 The par_index is supposed to start with index 0. */
4332 if (!nds32_consecutive_registers_load_store_p (op
,
4333 !push_p
? true : false,
4340 /* 2. Valid $fp/$gp/$lp push/pop operations.
4341 Remember to set start index for checking them. */
4343 /* The rest_count is the start index for checking $fp/$gp/$lp. */
4345 /* If index < 0, this parallel rtx is definitely
4346 not a valid stack push/pop operation. */
4350 /* Check $fp/$gp/$lp one by one.
4351 We use 'push_p' to pick up reg rtx and mem rtx. */
4352 if (cfun
->machine
->fp_size
)
4354 elt
= XVECEXP (op
, 0, index
);
4355 elt_mem
= push_p
? SET_DEST (elt
) : SET_SRC (elt
);
4356 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
4359 if (GET_CODE (elt_mem
) != MEM
4360 || GET_CODE (elt_reg
) != REG
4361 || REGNO (elt_reg
) != FP_REGNUM
)
4364 if (cfun
->machine
->gp_size
)
4366 elt
= XVECEXP (op
, 0, index
);
4367 elt_mem
= push_p
? SET_DEST (elt
) : SET_SRC (elt
);
4368 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
4371 if (GET_CODE (elt_mem
) != MEM
4372 || GET_CODE (elt_reg
) != REG
4373 || REGNO (elt_reg
) != GP_REGNUM
)
4376 if (cfun
->machine
->lp_size
)
4378 elt
= XVECEXP (op
, 0, index
);
4379 elt_mem
= push_p
? SET_DEST (elt
) : SET_SRC (elt
);
4380 elt_reg
= push_p
? SET_SRC (elt
) : SET_DEST (elt
);
4383 if (GET_CODE (elt_mem
) != MEM
4384 || GET_CODE (elt_reg
) != REG
4385 || REGNO (elt_reg
) != LP_REGNUM
)
4389 /* 3. The last element must be stack adjustment rtx.
4390 Its form of rtx should be:
4391 (set (reg:SI SP_REGNUM)
4392 (plus (reg:SI SP_REGNUM) (const_int X)))
4393 The X could be positive or negative value. */
4395 /* Pick up the last element. */
4396 elt
= XVECEXP (op
, 0, total_count
- 1);
4398 /* Extract its destination and source rtx. */
4399 elt_reg
= SET_DEST (elt
);
4400 elt_plus
= SET_SRC (elt
);
4402 /* Check this is (set (stack_reg) (plus stack_reg const)) pattern. */
4403 if (GET_CODE (elt_reg
) != REG
4404 || GET_CODE (elt_plus
) != PLUS
4405 || REGNO (elt_reg
) != SP_REGNUM
)
4408 /* Pass all test, this is a valid rtx. */
4412 /* Computing the Length of an Insn.
4413 Modifies the length assigned to instruction INSN.
4414 LEN is the initially computed length of the insn. */
4416 nds32_adjust_insn_length (rtx insn
, int length
)
4420 switch (recog_memoized (insn
))
4422 case CODE_FOR_move_df
:
4423 case CODE_FOR_move_di
:
4424 /* Adjust length of movd44 to 2. */
4425 src
= XEXP (PATTERN (insn
), 1);
4426 dst
= XEXP (PATTERN (insn
), 0);
4430 && (REGNO (src
) % 2) == 0
4431 && (REGNO (dst
) % 2) == 0)
4443 /* Function to check if 'bclr' instruction can be used with IVAL. */
4445 nds32_can_use_bclr_p (int ival
)
4449 /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit,
4450 it means the original ival has only one 0-bit,
4451 So it is ok to perform 'bclr' operation. */
4453 one_bit_count
= popcount_hwi ((unsigned HOST_WIDE_INT
) (~ival
));
4455 /* 'bclr' is a performance extension instruction. */
4456 return (TARGET_PERF_EXT
&& (one_bit_count
== 1));
4459 /* Function to check if 'bset' instruction can be used with IVAL. */
4461 nds32_can_use_bset_p (int ival
)
4465 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
4466 it is ok to perform 'bset' operation. */
4468 one_bit_count
= popcount_hwi ((unsigned HOST_WIDE_INT
) (ival
));
4470 /* 'bset' is a performance extension instruction. */
4471 return (TARGET_PERF_EXT
&& (one_bit_count
== 1));
4474 /* Function to check if 'btgl' instruction can be used with IVAL. */
4476 nds32_can_use_btgl_p (int ival
)
4480 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
4481 it is ok to perform 'btgl' operation. */
4483 one_bit_count
= popcount_hwi ((unsigned HOST_WIDE_INT
) (ival
));
4485 /* 'btgl' is a performance extension instruction. */
4486 return (TARGET_PERF_EXT
&& (one_bit_count
== 1));
4489 /* Function to check if 'bitci' instruction can be used with IVAL. */
4491 nds32_can_use_bitci_p (int ival
)
4493 /* If we are using V3 ISA, we have 'bitci' instruction.
4494 Try to see if we can present 'andi' semantic with
4495 such 'bit-clear-immediate' operation.
4496 For example, 'andi $r0,$r0,0xfffffffc' can be
4497 presented with 'bitci $r0,$r0,3'. */
4498 return (TARGET_ISA_V3
4500 && satisfies_constraint_Iu15 (gen_int_mode (~ival
, SImode
)));
4504 /* Return true if is load/store with SYMBOL_REF addressing mode
4505 and memory mode is SImode. */
4507 nds32_symbol_load_store_p (rtx insn
)
4509 rtx mem_src
= NULL_RTX
;
4511 switch (get_attr_type (insn
))
4514 mem_src
= SET_SRC (PATTERN (insn
));
4517 mem_src
= SET_DEST (PATTERN (insn
));
4523 /* Find load/store insn with addressing mode is SYMBOL_REF. */
4524 if (mem_src
!= NULL_RTX
)
4526 if ((GET_CODE (mem_src
) == ZERO_EXTEND
)
4527 || (GET_CODE (mem_src
) == SIGN_EXTEND
))
4528 mem_src
= XEXP (mem_src
, 0);
4530 if ((GET_CODE (XEXP (mem_src
, 0)) == SYMBOL_REF
)
4531 || (GET_CODE (XEXP (mem_src
, 0)) == LO_SUM
))
4538 /* Function to determine whether it is worth to do fp_as_gp optimization.
4539 Return 0: It is NOT worth to do fp_as_gp optimization.
4540 Return 1: It is APPROXIMATELY worth to do fp_as_gp optimization.
4541 Note that if it is worth to do fp_as_gp optimization,
4542 we MUST set FP_REGNUM ever live in this function. */
4544 nds32_fp_as_gp_check_available (void)
4546 /* If there exists ANY of following conditions,
4547 we DO NOT perform fp_as_gp optimization:
4548 1. TARGET_FORBID_FP_AS_GP is set
4549 regardless of the TARGET_FORCE_FP_AS_GP.
4550 2. User explicitly uses 'naked' attribute.
4551 3. Not optimize for size.
4552 4. Need frame pointer.
4553 5. If $fp is already required to be saved,
4554 it means $fp is already choosen by register allocator.
4555 Thus we better not to use it for fp_as_gp optimization.
4556 6. This function is a vararg function.
4557 DO NOT apply fp_as_gp optimization on this function
4558 because it may change and break stack frame.
4559 7. The epilogue is empty.
4560 This happens when the function uses exit()
4561 or its attribute is no_return.
4562 In that case, compiler will not expand epilogue
4563 so that we have no chance to output .omit_fp_end directive. */
4564 if (TARGET_FORBID_FP_AS_GP
4565 || lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl
))
4567 || frame_pointer_needed
4568 || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM
)
4569 || (cfun
->stdarg
== 1)
4570 || (find_fallthru_edge (EXIT_BLOCK_PTR_FOR_FN (cfun
)->preds
) == NULL
))
4573 /* Now we can check the possibility of using fp_as_gp optimization. */
4574 if (TARGET_FORCE_FP_AS_GP
)
4576 /* User explicitly issues -mforce-fp-as-gp option. */
4577 df_set_regs_ever_live (FP_REGNUM
, 1);
4582 /* In the following we are going to evaluate whether
4583 it is worth to do fp_as_gp optimization. */
4585 int symbol_count
= 0;
4590 /* We check if there already requires prologue.
4591 Note that $gp will be saved in prologue for PIC code generation.
4592 After that, we can set threshold by the existence of prologue.
4593 Each fp-implied instruction will gain 2-byte code size
4594 from gp-aware instruction, so we have following heuristics. */
4596 || nds32_have_prologue_p ())
4599 Compiler already intends to generate prologue content,
4600 so the fp_as_gp optimization will only insert
4601 'la $fp,_FP_BASE_' instruction, which will be
4602 converted into 4-byte instruction at link time.
4603 The threshold is "3" symbol accesses, 2 + 2 + 2 > 4. */
4609 Compiler originally does not generate prologue content,
4610 so the fp_as_gp optimization will NOT ONLY insert
4611 'la $fp,_FP_BASE' instruction, but also causes
4612 push/pop instructions.
4613 If we are using v3push (push25/pop25),
4614 the threshold is "5" symbol accesses, 5*2 > 4 + 2 + 2;
4615 If we are using normal push (smw/lmw),
4616 the threshold is "5+2" symbol accesses 7*2 > 4 + 4 + 4. */
4617 threshold
= 5 + (TARGET_V3PUSH
? 0 : 2);
4620 /* We would like to traverse every instruction in this function.
4621 So we need to have push_topmost_sequence()/pop_topmost_sequence()
4622 surrounding our for-loop evaluation. */
4623 push_topmost_sequence ();
4624 /* Counting the insn number which the addressing mode is symbol. */
4625 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
4627 if (single_set (insn
) && nds32_symbol_load_store_p (insn
))
4630 if (symbol_count
== threshold
)
4636 pop_topmost_sequence ();
4638 /* Enable fp_as_gp optimization when potential gain is good enough. */
4641 df_set_regs_ever_live (FP_REGNUM
, 1);
4646 /* By default we return 0. */
4651 /* Function to generate PC relative jump table.
4652 Refer to nds32.md for more details.
4654 The following is the sample for the case that diff value
4655 can be presented in '.short' size.
4657 addi $r1, $r1, -(case_lower_bound)
4658 slti $ta, $r1, (case_number)
4659 beqz $ta, .L_skip_label
4661 la $ta, .L35 ! get jump table address
4662 lh $r1, [$ta + $r1 << 1] ! load symbol diff from jump table entry
4679 nds32_output_casesi_pc_relative (rtx
*operands
)
4681 enum machine_mode mode
;
4684 diff_vec
= PATTERN (NEXT_INSN (operands
[1]));
4686 gcc_assert (GET_CODE (diff_vec
) == ADDR_DIFF_VEC
);
4688 /* Step C: "t <-- operands[1]". */
4689 output_asm_insn ("la\t$ta, %l1", operands
);
4691 /* Get the mode of each element in the difference vector. */
4692 mode
= GET_MODE (diff_vec
);
4694 /* Step D: "z <-- (mem (plus (operands[0] << m) t))",
4695 where m is 0, 1, or 2 to load address-diff value from table. */
4699 output_asm_insn ("lb\t%2, [$ta + %0 << 0]", operands
);
4702 output_asm_insn ("lh\t%2, [$ta + %0 << 1]", operands
);
4705 output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands
);
4711 /* Step E: "t <-- z + t".
4712 Add table label_ref with address-diff value to
4713 obtain target case address. */
4714 output_asm_insn ("add\t$ta, %2, $ta", operands
);
4716 /* Step F: jump to target with register t. */
4723 /* Function to generate normal jump table. */
4725 nds32_output_casesi (rtx
*operands
)
4727 /* Step C: "t <-- operands[1]". */
4728 output_asm_insn ("la\t$ta, %l1", operands
);
4730 /* Step D: "z <-- (mem (plus (operands[0] << 2) t))". */
4731 output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands
);
4733 /* No need to perform Step E, which is only used for
4734 pc relative jump table. */
4736 /* Step F: jump to target with register z. */
4744 /* Function to return memory format. */
4745 enum nds32_16bit_address_type
4746 nds32_mem_format (rtx op
)
4748 enum machine_mode mode_test
;
4753 return ADDRESS_NOT_16BIT_FORMAT
;
4755 mode_test
= GET_MODE (op
);
4760 if (GET_CODE (op
) == REG
&& (mode_test
== SImode
))
4763 /* 333 format for QI/HImode. */
4764 if (GET_CODE (op
) == REG
&& (REGNO (op
) < R8_REGNUM
))
4765 return ADDRESS_LO_REG_IMM3U
;
4767 /* post_inc 333 format. */
4768 if ((GET_CODE (op
) == POST_INC
) && (mode_test
== SImode
))
4770 regno
= REGNO(XEXP (op
, 0));
4773 return ADDRESS_POST_INC_LO_REG_IMM3U
;
4776 /* post_inc 333 format. */
4777 if ((GET_CODE (op
) == POST_MODIFY
)
4778 && (mode_test
== SImode
)
4779 && (REG_P (XEXP (XEXP (op
, 1), 0)))
4780 && (CONST_INT_P (XEXP (XEXP (op
, 1), 1))))
4782 regno
= REGNO (XEXP (XEXP (op
, 1), 0));
4783 val
= INTVAL (XEXP (XEXP (op
, 1), 1));
4784 if (regno
< 8 && val
< 32)
4785 return ADDRESS_POST_INC_LO_REG_IMM3U
;
4788 if ((GET_CODE (op
) == PLUS
)
4789 && (GET_CODE (XEXP (op
, 0)) == REG
)
4790 && (GET_CODE (XEXP (op
, 1)) == CONST_INT
))
4792 val
= INTVAL (XEXP (op
, 1));
4794 regno
= REGNO(XEXP (op
, 0));
4797 && regno
!= SP_REGNUM
4798 && regno
!= FP_REGNUM
)
4799 return ADDRESS_NOT_16BIT_FORMAT
;
4805 if (val
>= 0 && val
< 8 && regno
< 8)
4806 return ADDRESS_LO_REG_IMM3U
;
4811 if (val
>= 0 && val
< 16 && (val
% 2 == 0) && regno
< 8)
4812 return ADDRESS_LO_REG_IMM3U
;
4818 /* fp imply 37 format. */
4819 if ((regno
== FP_REGNUM
) &&
4820 (val
>= 0 && val
< 512 && (val
% 4 == 0)))
4821 return ADDRESS_FP_IMM7U
;
4822 /* sp imply 37 format. */
4823 else if ((regno
== SP_REGNUM
) &&
4824 (val
>= 0 && val
< 512 && (val
% 4 == 0)))
4825 return ADDRESS_SP_IMM7U
;
4827 else if (val
>= 0 && val
< 32 && (val
% 4 == 0) && regno
< 8)
4828 return ADDRESS_LO_REG_IMM3U
;
4836 return ADDRESS_NOT_16BIT_FORMAT
;
4839 /* Output 16-bit store. */
4841 nds32_output_16bit_store (rtx
*operands
, int byte
)
4845 rtx code
= XEXP (operands
[0], 0);
4847 size
= nds32_byte_to_size (byte
);
4849 switch (nds32_mem_format (operands
[0]))
4853 output_asm_insn ("swi450\t%1, [%0]", operands
);
4855 case ADDRESS_LO_REG_IMM3U
:
4856 snprintf (pattern
, sizeof (pattern
), "s%ci333\t%%1, %%0", size
);
4857 output_asm_insn (pattern
, operands
);
4859 case ADDRESS_POST_INC_LO_REG_IMM3U
:
4860 snprintf (pattern
, sizeof (pattern
), "s%ci333.bi\t%%1, %%0", size
);
4861 output_asm_insn (pattern
, operands
);
4863 case ADDRESS_FP_IMM7U
:
4864 output_asm_insn ("swi37\t%1, %0", operands
);
4866 case ADDRESS_SP_IMM7U
:
4867 /* Get immediate value and set back to operands[1]. */
4868 operands
[0] = XEXP (code
, 1);
4869 output_asm_insn ("swi37.sp\t%1, [ + (%0)]", operands
);
4878 /* Output 16-bit load. */
4880 nds32_output_16bit_load (rtx
*operands
, int byte
)
4884 rtx code
= XEXP (operands
[1], 0);
4886 size
= nds32_byte_to_size (byte
);
4888 switch (nds32_mem_format (operands
[1]))
4892 output_asm_insn ("lwi450\t%0, [%1]", operands
);
4894 case ADDRESS_LO_REG_IMM3U
:
4895 snprintf (pattern
, sizeof (pattern
), "l%ci333\t%%0, %%1", size
);
4896 output_asm_insn (pattern
, operands
);
4898 case ADDRESS_POST_INC_LO_REG_IMM3U
:
4899 snprintf (pattern
, sizeof (pattern
), "l%ci333.bi\t%%0, %%1", size
);
4900 output_asm_insn (pattern
, operands
);
4902 case ADDRESS_FP_IMM7U
:
4903 output_asm_insn ("lwi37\t%0, %1", operands
);
4905 case ADDRESS_SP_IMM7U
:
4906 /* Get immediate value and set back to operands[0]. */
4907 operands
[1] = XEXP (code
, 1);
4908 output_asm_insn ("lwi37.sp\t%0, [ + (%1)]", operands
);
4917 /* Output 32-bit store. */
4919 nds32_output_32bit_store (rtx
*operands
, int byte
)
4923 rtx code
= XEXP (operands
[0], 0);
4925 size
= nds32_byte_to_size (byte
);
4927 switch (GET_CODE (code
))
4931 => access location by using register,
4932 use "sbi / shi / swi" */
4933 snprintf (pattern
, sizeof (pattern
), "s%ci\t%%1, %%0", size
);
4938 /* (mem (symbol_ref X))
4940 => access global variables,
4941 use "sbi.gp / shi.gp / swi.gp" */
4942 operands
[0] = XEXP (operands
[0], 0);
4943 snprintf (pattern
, sizeof (pattern
), "s%ci.gp\t%%1, [ + %%0]", size
);
4947 /* (mem (post_inc reg))
4948 => access location by using register which will be post increment,
4949 use "sbi.bi / shi.bi / swi.bi" */
4950 snprintf (pattern
, sizeof (pattern
),
4951 "s%ci.bi\t%%1, %%0, %d", size
, byte
);
4955 /* (mem (post_dec reg))
4956 => access location by using register which will be post decrement,
4957 use "sbi.bi / shi.bi / swi.bi" */
4958 snprintf (pattern
, sizeof (pattern
),
4959 "s%ci.bi\t%%1, %%0, -%d", size
, byte
);
4963 switch (GET_CODE (XEXP (XEXP (code
, 1), 1)))
4967 /* (mem (post_modify (reg) (plus (reg) (reg))))
4968 => access location by using register which will be
4969 post modified with reg,
4970 use "sb.bi/ sh.bi / sw.bi" */
4971 snprintf (pattern
, sizeof (pattern
), "s%c.bi\t%%1, %%0", size
);
4974 /* (mem (post_modify (reg) (plus (reg) (const_int))))
4975 => access location by using register which will be
4976 post modified with const_int,
4977 use "sbi.bi/ shi.bi / swi.bi" */
4978 snprintf (pattern
, sizeof (pattern
), "s%ci.bi\t%%1, %%0", size
);
4986 switch (GET_CODE (XEXP (code
, 1)))
4990 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
4991 => access location by adding two registers,
4992 use "sb / sh / sw" */
4993 snprintf (pattern
, sizeof (pattern
), "s%c\t%%1, %%0", size
);
4996 /* (mem (plus reg const_int))
4997 => access location by adding one register with const_int,
4998 use "sbi / shi / swi" */
4999 snprintf (pattern
, sizeof (pattern
), "s%ci\t%%1, %%0", size
);
5007 operands
[2] = XEXP (code
, 1);
5008 operands
[0] = XEXP (code
, 0);
5009 snprintf (pattern
, sizeof (pattern
),
5010 "s%ci\t%%1, [%%0 + lo12(%%2)]", size
);
5017 output_asm_insn (pattern
, operands
);
5021 /* Output 32-bit load. */
5023 nds32_output_32bit_load (rtx
*operands
, int byte
)
5029 code
= XEXP (operands
[1], 0);
5031 size
= nds32_byte_to_size (byte
);
5033 switch (GET_CODE (code
))
5037 => access location by using register,
5038 use "lbi / lhi / lwi" */
5039 snprintf (pattern
, sizeof (pattern
), "l%ci\t%%0, %%1", size
);
5044 /* (mem (symbol_ref X))
5046 => access global variables,
5047 use "lbi.gp / lhi.gp / lwi.gp" */
5048 operands
[1] = XEXP (operands
[1], 0);
5049 snprintf (pattern
, sizeof (pattern
), "l%ci.gp\t%%0, [ + %%1]", size
);
5053 /* (mem (post_inc reg))
5054 => access location by using register which will be post increment,
5055 use "lbi.bi / lhi.bi / lwi.bi" */
5056 snprintf (pattern
, sizeof (pattern
),
5057 "l%ci.bi\t%%0, %%1, %d", size
, byte
);
5061 /* (mem (post_dec reg))
5062 => access location by using register which will be post decrement,
5063 use "lbi.bi / lhi.bi / lwi.bi" */
5064 snprintf (pattern
, sizeof (pattern
),
5065 "l%ci.bi\t%%0, %%1, -%d", size
, byte
);
5069 switch (GET_CODE (XEXP (XEXP (code
, 1), 1)))
5073 /* (mem (post_modify (reg) (plus (reg) (reg))))
5074 => access location by using register which will be
5075 post modified with reg,
5076 use "lb.bi/ lh.bi / lw.bi" */
5077 snprintf (pattern
, sizeof (pattern
), "l%c.bi\t%%0, %%1", size
);
5080 /* (mem (post_modify (reg) (plus (reg) (const_int))))
5081 => access location by using register which will be
5082 post modified with const_int,
5083 use "lbi.bi/ lhi.bi / lwi.bi" */
5084 snprintf (pattern
, sizeof (pattern
), "l%ci.bi\t%%0, %%1", size
);
5092 switch (GET_CODE (XEXP (code
, 1)))
5096 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
5097 use "lb / lh / lw" */
5098 snprintf (pattern
, sizeof (pattern
), "l%c\t%%0, %%1", size
);
5101 /* (mem (plus reg const_int))
5102 => access location by adding one register with const_int,
5103 use "lbi / lhi / lwi" */
5104 snprintf (pattern
, sizeof (pattern
), "l%ci\t%%0, %%1", size
);
5112 operands
[2] = XEXP (code
, 1);
5113 operands
[1] = XEXP (code
, 0);
5114 snprintf (pattern
, sizeof (pattern
),
5115 "l%ci\t%%0, [%%1 + lo12(%%2)]", size
);
5122 output_asm_insn (pattern
, operands
);
5126 /* Output 32-bit load with signed extension. */
5128 nds32_output_32bit_load_s (rtx
*operands
, int byte
)
5134 code
= XEXP (operands
[1], 0);
5136 size
= nds32_byte_to_size (byte
);
5138 switch (GET_CODE (code
))
5142 => access location by using register,
5143 use "lbsi / lhsi" */
5144 snprintf (pattern
, sizeof (pattern
), "l%csi\t%%0, %%1", size
);
5149 /* (mem (symbol_ref X))
5151 => access global variables,
5152 use "lbsi.gp / lhsi.gp" */
5153 operands
[1] = XEXP (operands
[1], 0);
5154 snprintf (pattern
, sizeof (pattern
), "l%csi.gp\t%%0, [ + %%1]", size
);
5158 /* (mem (post_inc reg))
5159 => access location by using register which will be post increment,
5160 use "lbsi.bi / lhsi.bi" */
5161 snprintf (pattern
, sizeof (pattern
),
5162 "l%csi.bi\t%%0, %%1, %d", size
, byte
);
5166 /* (mem (post_dec reg))
5167 => access location by using register which will be post decrement,
5168 use "lbsi.bi / lhsi.bi" */
5169 snprintf (pattern
, sizeof (pattern
),
5170 "l%csi.bi\t%%0, %%1, -%d", size
, byte
);
5174 switch (GET_CODE (XEXP (XEXP (code
, 1), 1)))
5178 /* (mem (post_modify (reg) (plus (reg) (reg))))
5179 => access location by using register which will be
5180 post modified with reg,
5181 use "lbs.bi/ lhs.bi" */
5182 snprintf (pattern
, sizeof (pattern
), "l%cs.bi\t%%0, %%1", size
);
5185 /* (mem (post_modify (reg) (plus (reg) (const_int))))
5186 => access location by using register which will be
5187 post modified with const_int,
5188 use "lbsi.bi/ lhsi.bi" */
5189 snprintf (pattern
, sizeof (pattern
), "l%csi.bi\t%%0, %%1", size
);
5197 switch (GET_CODE (XEXP (code
, 1)))
5201 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
5203 snprintf (pattern
, sizeof (pattern
), "l%cs\t%%0, %%1", size
);
5206 /* (mem (plus reg const_int))
5207 => access location by adding one register with const_int,
5208 use "lbsi / lhsi" */
5209 snprintf (pattern
, sizeof (pattern
), "l%csi\t%%0, %%1", size
);
5217 operands
[2] = XEXP (code
, 1);
5218 operands
[1] = XEXP (code
, 0);
5219 snprintf (pattern
, sizeof (pattern
),
5220 "l%csi\t%%0, [%%1 + lo12(%%2)]", size
);
5227 output_asm_insn (pattern
, operands
);
5231 /* Function to output stack push operation.
5232 We need to deal with normal stack push multiple or stack v3push. */
5234 nds32_output_stack_push (void)
5236 /* A string pattern for output_asm_insn(). */
5238 /* The operands array which will be used in output_asm_insn(). */
5240 /* Pick up callee-saved first regno and last regno for further use. */
5241 int rb_regno
= cfun
->machine
->callee_saved_regs_first_regno
;
5242 int re_regno
= cfun
->machine
->callee_saved_regs_last_regno
;
5246 /* For stack v3push:
5248 operands[1]: imm8u */
5250 /* This variable is to check if 'push25 Re,imm8u' is available. */
5253 /* Set operands[0]. */
5254 operands
[0] = gen_rtx_REG (SImode
, re_regno
);
5256 /* Check if we can generate 'push25 Re,imm8u',
5257 otherwise, generate 'push25 Re,0'. */
5258 sp_adjust
= cfun
->machine
->local_size
5259 + cfun
->machine
->out_args_size
5260 + cfun
->machine
->callee_saved_area_padding_bytes
;
5261 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust
))
5262 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust
))
5263 operands
[1] = GEN_INT (sp_adjust
);
5265 operands
[1] = GEN_INT (0);
5267 /* Create assembly code pattern. */
5268 snprintf (pattern
, sizeof (pattern
), "push25\t%%0, %%1");
5272 /* For normal stack push multiple:
5277 /* This variable is used to check if we only need to generate En4 field.
5278 As long as Rb==Re=SP_REGNUM, we set this variable to 1. */
5279 int push_en4_only_p
= 0;
5281 /* Set operands[0] and operands[1]. */
5282 operands
[0] = gen_rtx_REG (SImode
, rb_regno
);
5283 operands
[1] = gen_rtx_REG (SImode
, re_regno
);
5285 /* 'smw.adm $sp,[$sp],$sp,0' means push nothing. */
5286 if (!cfun
->machine
->fp_size
5287 && !cfun
->machine
->gp_size
5288 && !cfun
->machine
->lp_size
5289 && REGNO (operands
[0]) == SP_REGNUM
5290 && REGNO (operands
[1]) == SP_REGNUM
)
5292 /* No need to generate instruction. */
5297 /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */
5298 if (REGNO (operands
[0]) == SP_REGNUM
5299 && REGNO (operands
[1]) == SP_REGNUM
)
5300 push_en4_only_p
= 1;
5302 /* Create assembly code pattern.
5303 We need to handle the form: "Rb, Re, { $fp $gp $lp }". */
5304 snprintf (pattern
, sizeof (pattern
),
5305 "push.s\t%s{%s%s%s }",
5306 push_en4_only_p
? "" : "%0, %1, ",
5307 cfun
->machine
->fp_size
? " $fp" : "",
5308 cfun
->machine
->gp_size
? " $gp" : "",
5309 cfun
->machine
->lp_size
? " $lp" : "");
5313 /* We use output_asm_insn() to output assembly code by ourself. */
5314 output_asm_insn (pattern
, operands
);
5318 /* Function to output stack pop operation.
5319 We need to deal with normal stack pop multiple or stack v3pop. */
5321 nds32_output_stack_pop (void)
5323 /* A string pattern for output_asm_insn(). */
5325 /* The operands array which will be used in output_asm_insn(). */
5327 /* Pick up callee-saved first regno and last regno for further use. */
5328 int rb_regno
= cfun
->machine
->callee_saved_regs_first_regno
;
5329 int re_regno
= cfun
->machine
->callee_saved_regs_last_regno
;
5335 operands[1]: imm8u */
5337 /* This variable is to check if 'pop25 Re,imm8u' is available. */
5340 /* Set operands[0]. */
5341 operands
[0] = gen_rtx_REG (SImode
, re_regno
);
5343 /* Check if we can generate 'pop25 Re,imm8u',
5344 otherwise, generate 'pop25 Re,0'.
5345 We have to consider alloca issue as well.
5346 If the function does call alloca(), the stack pointer is not fixed.
5347 In that case, we cannot use 'pop25 Re,imm8u' directly.
5348 We have to caculate stack pointer from frame pointer
5349 and then use 'pop25 Re,0'. */
5350 sp_adjust
= cfun
->machine
->local_size
5351 + cfun
->machine
->out_args_size
5352 + cfun
->machine
->callee_saved_area_padding_bytes
;
5353 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust
))
5354 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust
)
5355 && !cfun
->calls_alloca
)
5356 operands
[1] = GEN_INT (sp_adjust
);
5358 operands
[1] = GEN_INT (0);
5360 /* Create assembly code pattern. */
5361 snprintf (pattern
, sizeof (pattern
), "pop25\t%%0, %%1");
5365 /* For normal stack pop multiple:
5370 /* This variable is used to check if we only need to generate En4 field.
5371 As long as Rb==Re=SP_REGNUM, we set this variable to 1. */
5372 int pop_en4_only_p
= 0;
5374 /* Set operands[0] and operands[1]. */
5375 operands
[0] = gen_rtx_REG (SImode
, rb_regno
);
5376 operands
[1] = gen_rtx_REG (SImode
, re_regno
);
5378 /* 'lmw.bim $sp,[$sp],$sp,0' means pop nothing. */
5379 if (!cfun
->machine
->fp_size
5380 && !cfun
->machine
->gp_size
5381 && !cfun
->machine
->lp_size
5382 && REGNO (operands
[0]) == SP_REGNUM
5383 && REGNO (operands
[1]) == SP_REGNUM
)
5385 /* No need to generate instruction. */
5390 /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */
5391 if (REGNO (operands
[0]) == SP_REGNUM
5392 && REGNO (operands
[1]) == SP_REGNUM
)
5395 /* Create assembly code pattern.
5396 We need to handle the form: "Rb, Re, { $fp $gp $lp }". */
5397 snprintf (pattern
, sizeof (pattern
),
5398 "pop.s\t%s{%s%s%s }",
5399 pop_en4_only_p
? "" : "%0, %1, ",
5400 cfun
->machine
->fp_size
? " $fp" : "",
5401 cfun
->machine
->gp_size
? " $gp" : "",
5402 cfun
->machine
->lp_size
? " $lp" : "");
5406 /* We use output_asm_insn() to output assembly code by ourself. */
5407 output_asm_insn (pattern
, operands
);
5411 /* Return align 2 (log base 2) if the next instruction of LABEL is 4 byte. */
5413 nds32_target_alignment (rtx label
)
5420 insn
= next_active_insn (label
);
5424 else if ((get_attr_length (insn
) % 4) == 0)
5430 /* ------------------------------------------------------------------------ */
5432 /* PART 5: Initialize target hook structure and definitions. */
5434 /* Controlling the Compilation Driver. */
5437 /* Run-time Target Specification. */
5440 /* Defining Data Structures for Per-function Information. */
5443 /* Storage Layout. */
5445 #undef TARGET_PROMOTE_FUNCTION_MODE
5446 #define TARGET_PROMOTE_FUNCTION_MODE \
5447 default_promote_function_mode_always_promote
5450 /* Layout of Source Language Data Types. */
5453 /* Register Usage. */
5455 /* -- Basic Characteristics of Registers. */
5457 /* -- Order of Allocation of Registers. */
5459 /* -- How Values Fit in Registers. */
5461 /* -- Handling Leaf Functions. */
5463 /* -- Registers That Form a Stack. */
5466 /* Register Classes. */
5468 #undef TARGET_CLASS_MAX_NREGS
5469 #define TARGET_CLASS_MAX_NREGS nds32_class_max_nregs
5472 #define TARGET_LRA_P hook_bool_void_true
5474 #undef TARGET_REGISTER_PRIORITY
5475 #define TARGET_REGISTER_PRIORITY nds32_register_priority
5478 /* Obsolete Macros for Defining Constraints. */
5481 /* Stack Layout and Calling Conventions. */
5483 /* -- Basic Stack Layout. */
5485 /* -- Exception Handling Support. */
5487 /* -- Specifying How Stack Checking is Done. */
5489 /* -- Registers That Address the Stack Frame. */
5491 /* -- Eliminating Frame Pointer and Arg Pointer. */
5493 #undef TARGET_CAN_ELIMINATE
5494 #define TARGET_CAN_ELIMINATE nds32_can_eliminate
5496 /* -- Passing Function Arguments on the Stack. */
5498 /* -- Passing Arguments in Registers. */
5500 #undef TARGET_FUNCTION_ARG
5501 #define TARGET_FUNCTION_ARG nds32_function_arg
5503 #undef TARGET_FUNCTION_ARG_ADVANCE
5504 #define TARGET_FUNCTION_ARG_ADVANCE nds32_function_arg_advance
5506 #undef TARGET_FUNCTION_ARG_BOUNDARY
5507 #define TARGET_FUNCTION_ARG_BOUNDARY nds32_function_arg_boundary
5509 /* -- How Scalar Function Values Are Returned. */
5511 #undef TARGET_FUNCTION_VALUE
5512 #define TARGET_FUNCTION_VALUE nds32_function_value
5514 #undef TARGET_LIBCALL_VALUE
5515 #define TARGET_LIBCALL_VALUE nds32_libcall_value
5517 #undef TARGET_FUNCTION_VALUE_REGNO_P
5518 #define TARGET_FUNCTION_VALUE_REGNO_P nds32_function_value_regno_p
5520 /* -- How Large Values Are Returned. */
5522 /* -- Caller-Saves Register Allocation. */
5524 /* -- Function Entry and Exit. */
5526 #undef TARGET_ASM_FUNCTION_PROLOGUE
5527 #define TARGET_ASM_FUNCTION_PROLOGUE nds32_asm_function_prologue
5529 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
5530 #define TARGET_ASM_FUNCTION_END_PROLOGUE nds32_asm_function_end_prologue
5532 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
5533 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE nds32_asm_function_begin_epilogue
5535 #undef TARGET_ASM_FUNCTION_EPILOGUE
5536 #define TARGET_ASM_FUNCTION_EPILOGUE nds32_asm_function_epilogue
5538 #undef TARGET_ASM_OUTPUT_MI_THUNK
5539 #define TARGET_ASM_OUTPUT_MI_THUNK nds32_asm_output_mi_thunk
5541 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5542 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
5544 /* -- Generating Code for Profiling. */
5546 /* -- Permitting tail calls. */
5548 #undef TARGET_WARN_FUNC_RETURN
5549 #define TARGET_WARN_FUNC_RETURN nds32_warn_func_return
5551 /* Stack smashing protection. */
5554 /* Implementing the Varargs Macros. */
5556 #undef TARGET_STRICT_ARGUMENT_NAMING
5557 #define TARGET_STRICT_ARGUMENT_NAMING nds32_strict_argument_naming
5560 /* Trampolines for Nested Functions. */
5562 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
5563 #define TARGET_ASM_TRAMPOLINE_TEMPLATE nds32_asm_trampoline_template
5565 #undef TARGET_TRAMPOLINE_INIT
5566 #define TARGET_TRAMPOLINE_INIT nds32_trampoline_init
5569 /* Implicit Calls to Library Routines. */
5572 /* Addressing Modes. */
5574 #undef TARGET_LEGITIMATE_ADDRESS_P
5575 #define TARGET_LEGITIMATE_ADDRESS_P nds32_legitimate_address_p
5578 /* Anchored Addresses. */
5581 /* Condition Code Status. */
5583 /* -- Representation of condition codes using (cc0). */
5585 /* -- Representation of condition codes using registers. */
5587 /* -- Macros to control conditional execution. */
5590 /* Describing Relative Costs of Operations. */
5592 #undef TARGET_REGISTER_MOVE_COST
5593 #define TARGET_REGISTER_MOVE_COST nds32_register_move_cost
5595 #undef TARGET_MEMORY_MOVE_COST
5596 #define TARGET_MEMORY_MOVE_COST nds32_memory_move_cost
5598 #undef TARGET_RTX_COSTS
5599 #define TARGET_RTX_COSTS nds32_rtx_costs
5601 #undef TARGET_ADDRESS_COST
5602 #define TARGET_ADDRESS_COST nds32_address_cost
5605 /* Adjusting the Instruction Scheduler. */
5608 /* Dividing the Output into Sections (Texts, Data, . . . ). */
5611 /* Position Independent Code. */
5614 /* Defining the Output Assembler Language. */
5616 /* -- The Overall Framework of an Assembler File. */
5618 #undef TARGET_ASM_FILE_START
5619 #define TARGET_ASM_FILE_START nds32_asm_file_start
5620 #undef TARGET_ASM_FILE_END
5621 #define TARGET_ASM_FILE_END nds32_asm_file_end
5623 /* -- Output of Data. */
5625 #undef TARGET_ASM_ALIGNED_HI_OP
5626 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
5628 #undef TARGET_ASM_ALIGNED_SI_OP
5629 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
5631 /* -- Output of Uninitialized Variables. */
5633 /* -- Output and Generation of Labels. */
5635 #undef TARGET_ASM_GLOBALIZE_LABEL
5636 #define TARGET_ASM_GLOBALIZE_LABEL nds32_asm_globalize_label
5638 /* -- How Initialization Functions Are Handled. */
5640 /* -- Macros Controlling Initialization Routines. */
5642 /* -- Output of Assembler Instructions. */
5644 #undef TARGET_PRINT_OPERAND
5645 #define TARGET_PRINT_OPERAND nds32_print_operand
5646 #undef TARGET_PRINT_OPERAND_ADDRESS
5647 #define TARGET_PRINT_OPERAND_ADDRESS nds32_print_operand_address
5649 /* -- Output of Dispatch Tables. */
5651 /* -- Assembler Commands for Exception Regions. */
5653 /* -- Assembler Commands for Alignment. */
5656 /* Controlling Debugging Information Format. */
5658 /* -- Macros Affecting All Debugging Formats. */
5660 /* -- Specific Options for DBX Output. */
5662 /* -- Open-Ended Hooks for DBX Format. */
5664 /* -- File Names in DBX Format. */
5666 /* -- Macros for SDB and DWARF Output. */
5668 /* -- Macros for VMS Debug Format. */
5671 /* Cross Compilation and Floating Point. */
5674 /* Mode Switching Instructions. */
5677 /* Defining target-specific uses of __attribute__. */
5679 #undef TARGET_ATTRIBUTE_TABLE
5680 #define TARGET_ATTRIBUTE_TABLE nds32_attribute_table
5682 #undef TARGET_MERGE_DECL_ATTRIBUTES
5683 #define TARGET_MERGE_DECL_ATTRIBUTES nds32_merge_decl_attributes
5685 #undef TARGET_INSERT_ATTRIBUTES
5686 #define TARGET_INSERT_ATTRIBUTES nds32_insert_attributes
5688 #undef TARGET_OPTION_PRAGMA_PARSE
5689 #define TARGET_OPTION_PRAGMA_PARSE nds32_option_pragma_parse
5691 #undef TARGET_OPTION_OVERRIDE
5692 #define TARGET_OPTION_OVERRIDE nds32_option_override
5695 /* Emulating TLS. */
5698 /* Defining coprocessor specifics for MIPS targets. */
5701 /* Parameters for Precompiled Header Validity Checking. */
5704 /* C++ ABI parameters. */
5707 /* Adding support for named address spaces. */
5710 /* Miscellaneous Parameters. */
5712 #undef TARGET_INIT_BUILTINS
5713 #define TARGET_INIT_BUILTINS nds32_init_builtins
5715 #undef TARGET_EXPAND_BUILTIN
5716 #define TARGET_EXPAND_BUILTIN nds32_expand_builtin
5719 /* ------------------------------------------------------------------------ */
5721 /* Initialize the GCC target structure. */
5723 struct gcc_target targetm
= TARGET_INITIALIZER
;
5725 /* ------------------------------------------------------------------------ */