1 /* Subroutines used for code generation of Andes NDS32 cpu for GNU compiler
2    Copyright (C) 2012-2018 Free Software Foundation, Inc.
3    Contributed by Andes Technology Corporation.
4 
5    This file is part of GCC.
6 
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.
11 
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.
16 
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/>.  */
20 
21 /* ------------------------------------------------------------------------ */
22 
23 #define IN_TARGET_CODE 1
24 
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "target.h"
30 #include "rtl.h"
31 #include "tree.h"
32 #include "tree-pass.h"
33 #include "stringpool.h"
34 #include "attribs.h"
35 #include "df.h"
36 #include "memmodel.h"
37 #include "tm_p.h"
38 #include "optabs.h"		/* For GEN_FCN.  */
39 #include "regs.h"
40 #include "emit-rtl.h"
41 #include "recog.h"
42 #include "diagnostic-core.h"
43 #include "stor-layout.h"
44 #include "varasm.h"
45 #include "calls.h"
46 #include "output.h"
47 #include "explow.h"
48 #include "expr.h"
49 #include "tm-constrs.h"
50 #include "builtins.h"
51 #include "cpplib.h"
52 #include "context.h"
53 
54 /* This file should be included last.  */
55 #include "target-def.h"
56 
57 /* ------------------------------------------------------------------------ */
58 
59 /* This file is divided into five parts:
60 
61      PART 1: Auxiliary static variable definitions and
62              target hook static variable definitions.
63 
64      PART 2: Auxiliary static function definitions.
65 
66      PART 3: Implement target hook stuff definitions.
67 
68      PART 4: Implemet extern function definitions,
69              the prototype is in nds32-protos.h.
70 
71      PART 5: Initialize target hook structure and definitions.  */
72 
73 /* ------------------------------------------------------------------------ */
74 
75 /* PART 1: Auxiliary static variable definitions and
76            target hook static variable definitions.  */
77 
78 /* Define intrinsic register names.
79    Please refer to nds32_intrinsic.h file, the index is corresponding to
80    'enum nds32_intrinsic_registers' data type values.
81    NOTE that the base value starting from 1024.  */
82 static const char * const nds32_intrinsic_register_names[] =
83 {
84   "$CPU_VER",
85   "$ICM_CFG",
86   "$DCM_CFG",
87   "$MMU_CFG",
88   "$MSC_CFG",
89   "$MSC_CFG2",
90   "$CORE_ID",
91   "$FUCOP_EXIST",
92 
93   "$PSW",
94   "$IPSW",
95   "$P_IPSW",
96   "$IVB",
97   "$EVA",
98   "$P_EVA",
99   "$ITYPE",
100   "$P_ITYPE",
101 
102   "$MERR",
103   "$IPC",
104   "$P_IPC",
105   "$OIPC",
106   "$P_P0",
107   "$P_P1",
108 
109   "$INT_MASK",
110   "$INT_MASK2",
111   "$INT_MASK3",
112   "$INT_PEND",
113   "$INT_PEND2",
114   "$INT_PEND3",
115   "$SP_USR",
116   "$SP_PRIV",
117   "$INT_PRI",
118   "$INT_PRI2",
119   "$INT_PRI3",
120   "$INT_PRI4",
121   "$INT_CTRL",
122   "$INT_TRIGGER",
123   "$INT_TRIGGER2",
124   "$INT_GPR_PUSH_DIS",
125 
126   "$MMU_CTL",
127   "$L1_PPTB",
128   "$TLB_VPN",
129   "$TLB_DATA",
130   "$TLB_MISC",
131   "$VLPT_IDX",
132   "$ILMB",
133   "$DLMB",
134 
135   "$CACHE_CTL",
136   "$HSMP_SADDR",
137   "$HSMP_EADDR",
138   "$SDZ_CTL",
139   "$N12MISC_CTL",
140   "$MISC_CTL",
141   "$ECC_MISC",
142 
143   "$BPC0",
144   "$BPC1",
145   "$BPC2",
146   "$BPC3",
147   "$BPC4",
148   "$BPC5",
149   "$BPC6",
150   "$BPC7",
151 
152   "$BPA0",
153   "$BPA1",
154   "$BPA2",
155   "$BPA3",
156   "$BPA4",
157   "$BPA5",
158   "$BPA6",
159   "$BPA7",
160 
161   "$BPAM0",
162   "$BPAM1",
163   "$BPAM2",
164   "$BPAM3",
165   "$BPAM4",
166   "$BPAM5",
167   "$BPAM6",
168   "$BPAM7",
169 
170   "$BPV0",
171   "$BPV1",
172   "$BPV2",
173   "$BPV3",
174   "$BPV4",
175   "$BPV5",
176   "$BPV6",
177   "$BPV7",
178 
179   "$BPCID0",
180   "$BPCID1",
181   "$BPCID2",
182   "$BPCID3",
183   "$BPCID4",
184   "$BPCID5",
185   "$BPCID6",
186   "$BPCID7",
187 
188   "$EDM_CFG",
189   "$EDMSW",
190   "$EDM_CTL",
191   "$EDM_DTR",
192   "$BPMTC",
193   "$DIMBR",
194 
195   "$TECR0",
196   "$TECR1",
197   "$PFMC0",
198   "$PFMC1",
199   "$PFMC2",
200   "$PFM_CTL",
201   "$PFT_CTL",
202   "$HSP_CTL",
203   "$SP_BOUND",
204   "$SP_BOUND_PRIV",
205   "$SP_BASE",
206   "$SP_BASE_PRIV",
207   "$FUCOP_CTL",
208   "$PRUSR_ACC_CTL",
209 
210   "$DMA_CFG",
211   "$DMA_GCSW",
212   "$DMA_CHNSEL",
213   "$DMA_ACT",
214   "$DMA_SETUP",
215   "$DMA_ISADDR",
216   "$DMA_ESADDR",
217   "$DMA_TCNT",
218   "$DMA_STATUS",
219   "$DMA_2DSET",
220   "$DMA_2DSCTL",
221   "$DMA_RCNT",
222   "$DMA_HSTATUS",
223 
224   "$PC",
225   "$SP_USR1",
226   "$SP_USR2",
227   "$SP_USR3",
228   "$SP_PRIV1",
229   "$SP_PRIV2",
230   "$SP_PRIV3",
231   "$BG_REGION",
232   "$SFCR",
233   "$SIGN",
234   "$ISIGN",
235   "$P_ISIGN",
236   "$IFC_LP",
237   "$ITB"
238 };
239 
240 /* Define instrinsic cctl names.  */
241 static const char * const nds32_cctl_names[] =
242 {
243   "L1D_VA_FILLCK",
244   "L1D_VA_ULCK",
245   "L1I_VA_FILLCK",
246   "L1I_VA_ULCK",
247 
248   "L1D_IX_WBINVAL",
249   "L1D_IX_INVAL",
250   "L1D_IX_WB",
251   "L1I_IX_INVAL",
252 
253   "L1D_VA_INVAL",
254   "L1D_VA_WB",
255   "L1D_VA_WBINVAL",
256   "L1I_VA_INVAL",
257 
258   "L1D_IX_RTAG",
259   "L1D_IX_RWD",
260   "L1I_IX_RTAG",
261   "L1I_IX_RWD",
262 
263   "L1D_IX_WTAG",
264   "L1D_IX_WWD",
265   "L1I_IX_WTAG",
266   "L1I_IX_WWD"
267 };
268 
269 static const char * const nds32_dpref_names[] =
270 {
271   "SRD",
272   "MRD",
273   "SWR",
274   "MWR",
275   "PTE",
276   "CLWR"
277 };
278 
279 /* Defining register allocation order for performance.
280    We want to allocate callee-saved registers after others.
281    It may be used by nds32_adjust_reg_alloc_order().  */
282 static const int nds32_reg_alloc_order_for_speed[] =
283 {
284    0,   1,   2,   3,   4,   5,  16,  17,
285   18,  19,  20,  21,  22,  23,  24,  25,
286   26,  27,   6,   7,   8,   9,  10,  11,
287   12,  13,  14,  15
288 };
289 
290 /* Defining target-specific uses of __attribute__.  */
291 static const struct attribute_spec nds32_attribute_table[] =
292 {
293   /* Syntax: { name, min_len, max_len, decl_required, type_required,
294 	       function_type_required, affects_type_identity, handler,
295 	       exclude } */
296 
297   /* The interrupt vid: [0-63]+ (actual vector number starts from 9 to 72).  */
298   { "interrupt",    1, 64, false, false, false, false, NULL, NULL },
299   /* The exception vid: [1-8]+  (actual vector number starts from 1 to 8).  */
300   { "exception",    1,  8, false, false, false, false, NULL, NULL },
301   /* Argument is user's interrupt numbers.  The vector number is always 0.  */
302   { "reset",        1,  1, false, false, false, false, NULL, NULL },
303 
304   /* The attributes describing isr nested type.  */
305   { "nested",       0,  0, false, false, false, false, NULL, NULL },
306   { "not_nested",   0,  0, false, false, false, false, NULL, NULL },
307   { "nested_ready", 0,  0, false, false, false, false, NULL, NULL },
308 
309   /* The attributes describing isr register save scheme.  */
310   { "save_all",     0,  0, false, false, false, false, NULL, NULL },
311   { "partial_save", 0,  0, false, false, false, false, NULL, NULL },
312 
313   /* The attributes used by reset attribute.  */
314   { "nmi",          1,  1, false, false, false, false, NULL, NULL },
315   { "warm",         1,  1, false, false, false, false, NULL, NULL },
316 
317   /* The attribute telling no prologue/epilogue.  */
318   { "naked",        0,  0, false, false, false, false, NULL, NULL },
319 
320   /* The last attribute spec is set to be NULL.  */
321   { NULL,           0,  0, false, false, false, false, NULL, NULL }
322 };
323 
324 
325 /* ------------------------------------------------------------------------ */
326 
327 /* PART 2: Auxiliary static function definitions.  */
328 
329 /* Function to save and restore machine-specific function data.  */
330 static struct machine_function *
nds32_init_machine_status(void)331 nds32_init_machine_status (void)
332 {
333   struct machine_function *machine;
334   machine = ggc_cleared_alloc<machine_function> ();
335 
336   /* Initially assume this function does not use __builtin_eh_return.  */
337   machine->use_eh_return_p = 0;
338 
339   /* Initially assume this function needs prologue/epilogue.  */
340   machine->naked_p = 0;
341 
342   /* Initially assume this function does NOT use fp_as_gp optimization.  */
343   machine->fp_as_gp_p = 0;
344 
345   /* Initially this function is not under strictly aligned situation.  */
346   machine->strict_aligned_p = 0;
347 
348   return machine;
349 }
350 
351 /* Function to compute stack frame size and
352    store into cfun->machine structure.  */
353 static void
nds32_compute_stack_frame(void)354 nds32_compute_stack_frame (void)
355 {
356   int r;
357   int block_size;
358   bool v3pushpop_p;
359 
360   /* Because nds32_compute_stack_frame() will be called from different place,
361      everytime we enter this function, we have to assume this function
362      needs prologue/epilogue.  */
363   cfun->machine->naked_p = 0;
364 
365 
366   /* If __builtin_eh_return is used, we better have frame pointer needed
367      so that we can easily locate the stack slot of return address.  */
368   if (crtl->calls_eh_return)
369     {
370       frame_pointer_needed = 1;
371 
372       /* We need to mark eh data registers that need to be saved
373 	 in the stack.  */
374       cfun->machine->eh_return_data_first_regno = EH_RETURN_DATA_REGNO (0);
375       for (r = 0; EH_RETURN_DATA_REGNO (r) != INVALID_REGNUM; r++)
376 	cfun->machine->eh_return_data_last_regno = r;
377 
378       cfun->machine->eh_return_data_regs_size
379 	= 4 * (cfun->machine->eh_return_data_last_regno
380 	       - cfun->machine->eh_return_data_first_regno
381 	       + 1);
382       cfun->machine->use_eh_return_p = 1;
383     }
384   else
385     {
386       /* Assigning SP_REGNUM to eh_first_regno and eh_last_regno means we
387 	 do not need to handle __builtin_eh_return case in this function.  */
388       cfun->machine->eh_return_data_first_regno = SP_REGNUM;
389       cfun->machine->eh_return_data_last_regno  = SP_REGNUM;
390 
391       cfun->machine->eh_return_data_regs_size = 0;
392       cfun->machine->use_eh_return_p = 0;
393     }
394 
395   /* Get variadic arguments size to prepare pretend arguments and
396      we will push them into stack at prologue by ourself.  */
397   cfun->machine->va_args_size = crtl->args.pretend_args_size;
398   if (cfun->machine->va_args_size != 0)
399     {
400       cfun->machine->va_args_first_regno
401 	= NDS32_GPR_ARG_FIRST_REGNUM
402 	  + NDS32_MAX_GPR_REGS_FOR_ARGS
403 	  - (crtl->args.pretend_args_size / UNITS_PER_WORD);
404       cfun->machine->va_args_last_regno
405 	= NDS32_GPR_ARG_FIRST_REGNUM + NDS32_MAX_GPR_REGS_FOR_ARGS - 1;
406     }
407   else
408     {
409       cfun->machine->va_args_first_regno = SP_REGNUM;
410       cfun->machine->va_args_last_regno  = SP_REGNUM;
411     }
412 
413   /* Important: We need to make sure that varargs area is 8-byte alignment.  */
414   block_size = cfun->machine->va_args_size;
415   if (!NDS32_DOUBLE_WORD_ALIGN_P (block_size))
416     {
417       cfun->machine->va_args_area_padding_bytes
418 	= NDS32_ROUND_UP_DOUBLE_WORD (block_size) - block_size;
419     }
420 
421   /* Get local variables, incoming variables, and temporary variables size.
422      Note that we need to make sure it is 8-byte alignment because
423      there may be no padding bytes if we are using LRA.  */
424   cfun->machine->local_size = NDS32_ROUND_UP_DOUBLE_WORD (get_frame_size ());
425 
426   /* Get outgoing arguments size.  */
427   cfun->machine->out_args_size = crtl->outgoing_args_size;
428 
429   /* If $fp value is required to be saved on stack, it needs 4 bytes space.
430      Check whether $fp is ever live.  */
431   cfun->machine->fp_size = (df_regs_ever_live_p (FP_REGNUM)) ? 4 : 0;
432 
433   /* If $gp value is required to be saved on stack, it needs 4 bytes space.
434      Check whether we are using PIC code genration.  */
435   cfun->machine->gp_size = (flag_pic) ? 4 : 0;
436 
437   /* If $lp value is required to be saved on stack, it needs 4 bytes space.
438      Check whether $lp is ever live.  */
439   cfun->machine->lp_size
440     = (flag_always_save_lp || df_regs_ever_live_p (LP_REGNUM)) ? 4 : 0;
441 
442   /* Initially there is no padding bytes.  */
443   cfun->machine->callee_saved_area_gpr_padding_bytes = 0;
444 
445   /* Calculate the bytes of saving callee-saved registers on stack.  */
446   cfun->machine->callee_saved_gpr_regs_size = 0;
447   cfun->machine->callee_saved_first_gpr_regno = SP_REGNUM;
448   cfun->machine->callee_saved_last_gpr_regno  = SP_REGNUM;
449   cfun->machine->callee_saved_fpr_regs_size = 0;
450   cfun->machine->callee_saved_first_fpr_regno = SP_REGNUM;
451   cfun->machine->callee_saved_last_fpr_regno  = SP_REGNUM;
452 
453   /* Currently, there is no need to check $r28~$r31
454      because we will save them in another way.  */
455   for (r = 0; r < 28; r++)
456     {
457       if (NDS32_REQUIRED_CALLEE_SAVED_P (r))
458 	{
459 	  /* Mark the first required callee-saved register
460 	     (only need to set it once).
461 	     If first regno == SP_REGNUM, we can tell that
462 	     it is the first time to be here.  */
463 	  if (cfun->machine->callee_saved_first_gpr_regno == SP_REGNUM)
464 	    cfun->machine->callee_saved_first_gpr_regno = r;
465 	  /* Mark the last required callee-saved register.  */
466 	  cfun->machine->callee_saved_last_gpr_regno = r;
467 	}
468     }
469 
470   /* Recording fpu callee-saved register.  */
471   if (TARGET_HARD_FLOAT)
472     {
473       for (r = NDS32_FIRST_FPR_REGNUM; r < NDS32_LAST_FPR_REGNUM; r++)
474 	{
475 	  if (NDS32_REQUIRED_CALLEE_SAVED_P (r))
476 	    {
477 	      /* Mark the first required callee-saved register.  */
478 	      if (cfun->machine->callee_saved_first_fpr_regno == SP_REGNUM)
479 		{
480 		  /* Make first callee-saved number is even,
481 		     bacause we use doubleword access, and this way
482 		     promise 8-byte alignemt.  */
483 		  if (!NDS32_FPR_REGNO_OK_FOR_DOUBLE (r))
484 		    cfun->machine->callee_saved_first_fpr_regno = r - 1;
485 		  else
486 		    cfun->machine->callee_saved_first_fpr_regno = r;
487 		}
488 	      cfun->machine->callee_saved_last_fpr_regno = r;
489 	    }
490 	}
491 
492       /* Make last callee-saved register number is odd,
493 	 we hope callee-saved register is even.  */
494       int last_fpr = cfun->machine->callee_saved_last_fpr_regno;
495       if (NDS32_FPR_REGNO_OK_FOR_DOUBLE (last_fpr))
496 	cfun->machine->callee_saved_last_fpr_regno++;
497     }
498 
499   /* Check if this function can omit prologue/epilogue code fragment.
500      If there is 'naked' attribute in this function,
501      we can set 'naked_p' flag to indicate that
502      we do not have to generate prologue/epilogue.
503      Or, if all the following conditions succeed,
504      we can set this function 'naked_p' as well:
505        condition 1: first_regno == last_regno == SP_REGNUM,
506 		    which means we do not have to save
507 		    any callee-saved registers.
508        condition 2: Both $lp and $fp are NOT live in this function,
509 		    which means we do not need to save them and there
510 		    is no outgoing size.
511        condition 3: There is no local_size, which means
512 		    we do not need to adjust $sp.  */
513   if (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))
514       || (cfun->machine->callee_saved_first_gpr_regno == SP_REGNUM
515 	  && cfun->machine->callee_saved_last_gpr_regno == SP_REGNUM
516 	  && cfun->machine->callee_saved_first_fpr_regno == SP_REGNUM
517 	  && cfun->machine->callee_saved_last_fpr_regno == SP_REGNUM
518 	  && !df_regs_ever_live_p (FP_REGNUM)
519 	  && !df_regs_ever_live_p (LP_REGNUM)
520 	  && cfun->machine->local_size == 0))
521     {
522       /* Set this function 'naked_p' and other functions can check this flag.
523 	 Note that in nds32 port, the 'naked_p = 1' JUST means there is no
524 	 callee-saved, local size, and outgoing size.
525 	 The varargs space and ret instruction may still present in
526 	 the prologue/epilogue expanding.  */
527       cfun->machine->naked_p = 1;
528 
529       /* No need to save $fp, $gp, and $lp.
530 	 We should set these value to be zero
531 	 so that nds32_initial_elimination_offset() can work properly.  */
532       cfun->machine->fp_size = 0;
533       cfun->machine->gp_size = 0;
534       cfun->machine->lp_size = 0;
535 
536       /* If stack usage computation is required,
537 	 we need to provide the static stack size.  */
538       if (flag_stack_usage_info)
539 	current_function_static_stack_size = 0;
540 
541       /* No need to do following adjustment, return immediately.  */
542       return;
543     }
544 
545   v3pushpop_p = NDS32_V3PUSH_AVAILABLE_P;
546 
547   /* Adjustment for v3push instructions:
548      If we are using v3push (push25/pop25) instructions,
549      we need to make sure Rb is $r6 and Re is
550      located on $r6, $r8, $r10, or $r14.
551      Some results above will be discarded and recomputed.
552      Note that it is only available under V3/V3M ISA and we
553      DO NOT setup following stuff for isr or variadic function.  */
554   if (v3pushpop_p)
555     {
556       /* Recompute:
557 	   cfun->machine->fp_size
558 	   cfun->machine->gp_size
559 	   cfun->machine->lp_size
560 	   cfun->machine->callee_saved_first_gpr_regno
561 	   cfun->machine->callee_saved_last_gpr_regno */
562 
563       /* For v3push instructions, $fp, $gp, and $lp are always saved.  */
564       cfun->machine->fp_size = 4;
565       cfun->machine->gp_size = 4;
566       cfun->machine->lp_size = 4;
567 
568       /* Remember to set Rb = $r6.  */
569       cfun->machine->callee_saved_first_gpr_regno = 6;
570 
571       if (cfun->machine->callee_saved_last_gpr_regno <= 6)
572 	{
573 	  /* Re = $r6 */
574 	  cfun->machine->callee_saved_last_gpr_regno = 6;
575 	}
576       else if (cfun->machine->callee_saved_last_gpr_regno <= 8)
577 	{
578 	  /* Re = $r8 */
579 	  cfun->machine->callee_saved_last_gpr_regno = 8;
580 	}
581       else if (cfun->machine->callee_saved_last_gpr_regno <= 10)
582 	{
583 	  /* Re = $r10 */
584 	  cfun->machine->callee_saved_last_gpr_regno = 10;
585 	}
586       else if (cfun->machine->callee_saved_last_gpr_regno <= 14)
587 	{
588 	  /* Re = $r14 */
589 	  cfun->machine->callee_saved_last_gpr_regno = 14;
590 	}
591       else if (cfun->machine->callee_saved_last_gpr_regno == SP_REGNUM)
592 	{
593 	  /* If last_regno is SP_REGNUM, which means
594 	     it is never changed, so set it to Re = $r6.  */
595 	  cfun->machine->callee_saved_last_gpr_regno = 6;
596 	}
597       else
598 	{
599 	  /* The program flow should not go here.  */
600 	  gcc_unreachable ();
601 	}
602     }
603 
604   int sp_adjust = cfun->machine->local_size
605 		  + cfun->machine->out_args_size
606 		  + cfun->machine->callee_saved_area_gpr_padding_bytes
607 		  + cfun->machine->callee_saved_fpr_regs_size;
608 
609   if (!v3pushpop_p
610       && sp_adjust == 0
611       && !frame_pointer_needed)
612     {
613       block_size = cfun->machine->fp_size
614 		   + cfun->machine->gp_size
615 		   + cfun->machine->lp_size;
616 
617       if (cfun->machine->callee_saved_last_gpr_regno != SP_REGNUM)
618 	block_size += (4 * (cfun->machine->callee_saved_last_gpr_regno
619 			    - cfun->machine->callee_saved_first_gpr_regno
620 			    + 1));
621 
622       if (!NDS32_DOUBLE_WORD_ALIGN_P (block_size))
623 	{
624 	  /* $r14 is last callee save register.  */
625 	  if (cfun->machine->callee_saved_last_gpr_regno
626 	      < NDS32_LAST_CALLEE_SAVE_GPR_REGNUM)
627 	    {
628 	      cfun->machine->callee_saved_last_gpr_regno++;
629 	    }
630 	  else if (cfun->machine->callee_saved_first_gpr_regno == SP_REGNUM)
631 	    {
632 	      cfun->machine->callee_saved_first_gpr_regno
633 		= NDS32_FIRST_CALLEE_SAVE_GPR_REGNUM;
634 	      cfun->machine->callee_saved_last_gpr_regno
635 		= NDS32_FIRST_CALLEE_SAVE_GPR_REGNUM;
636 	    }
637 	}
638     }
639 
640   /* We have correctly set callee_saved_first_gpr_regno
641      and callee_saved_last_gpr_regno.
642      Initially, the callee_saved_gpr_regs_size is supposed to be 0.
643      As long as callee_saved_last_gpr_regno is not SP_REGNUM,
644      we can update callee_saved_gpr_regs_size with new size.  */
645   if (cfun->machine->callee_saved_last_gpr_regno != SP_REGNUM)
646     {
647       /* Compute pushed size of callee-saved registers.  */
648       cfun->machine->callee_saved_gpr_regs_size
649 	= 4 * (cfun->machine->callee_saved_last_gpr_regno
650 	       - cfun->machine->callee_saved_first_gpr_regno
651 	       + 1);
652     }
653 
654   if (TARGET_HARD_FLOAT)
655     {
656       /* Compute size of callee svaed floating-point registers.  */
657       if (cfun->machine->callee_saved_last_fpr_regno != SP_REGNUM)
658 	{
659 	  cfun->machine->callee_saved_fpr_regs_size
660 	   = 4 * (cfun->machine->callee_saved_last_fpr_regno
661 		  - cfun->machine->callee_saved_first_fpr_regno
662 		  + 1);
663 	}
664     }
665 
666   /* Important: We need to make sure that
667 		(fp_size + gp_size + lp_size + callee_saved_gpr_regs_size)
668 		is 8-byte alignment.
669 		If it is not, calculate the padding bytes.  */
670   block_size = cfun->machine->fp_size
671 	       + cfun->machine->gp_size
672 	       + cfun->machine->lp_size
673 	       + cfun->machine->callee_saved_gpr_regs_size;
674   if (!NDS32_DOUBLE_WORD_ALIGN_P (block_size))
675     {
676       cfun->machine->callee_saved_area_gpr_padding_bytes
677 	= NDS32_ROUND_UP_DOUBLE_WORD (block_size) - block_size;
678     }
679 
680   /* If stack usage computation is required,
681      we need to provide the static stack size.  */
682   if (flag_stack_usage_info)
683     {
684       current_function_static_stack_size
685 	= NDS32_ROUND_UP_DOUBLE_WORD (block_size)
686 	  + cfun->machine->local_size
687 	  + cfun->machine->out_args_size;
688     }
689 }
690 
691 /* Function to create a parallel rtx pattern
692    which presents stack push multiple behavior.
693    The overall concept are:
694      "push registers to memory",
695      "adjust stack pointer".  */
696 static void
nds32_emit_stack_push_multiple(unsigned Rb,unsigned Re,bool save_fp_p,bool save_gp_p,bool save_lp_p,bool vaarg_p)697 nds32_emit_stack_push_multiple (unsigned Rb, unsigned Re,
698 				bool save_fp_p, bool save_gp_p, bool save_lp_p,
699 				bool vaarg_p)
700 {
701   unsigned regno;
702   int extra_count;
703   int num_use_regs;
704   int par_index;
705   int offset;
706 
707   rtx reg;
708   rtx mem;
709   rtx push_rtx;
710   rtx adjust_sp_rtx;
711   rtx parallel_insn;
712   rtx dwarf;
713 
714   /* We need to provide a customized rtx which contains
715      necessary information for data analysis,
716      so we create a parallel rtx like this:
717      (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
718 		     (reg:SI Rb))
719 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
720 		     (reg:SI Rb+1))
721 		...
722 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
723 		     (reg:SI Re))
724 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
725 		     (reg:SI FP_REGNUM))
726 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
727 		     (reg:SI GP_REGNUM))
728 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
729 		     (reg:SI LP_REGNUM))
730 		(set (reg:SI SP_REGNUM)
731 		     (plus (reg:SI SP_REGNUM) (const_int -32)))]) */
732 
733   /* Calculate the number of registers that will be pushed.  */
734   extra_count = 0;
735   if (save_fp_p)
736     extra_count++;
737   if (save_gp_p)
738     extra_count++;
739   if (save_lp_p)
740     extra_count++;
741   /* Note that Rb and Re may be SP_REGNUM.  DO NOT count it in.  */
742   if (Rb == SP_REGNUM && Re == SP_REGNUM)
743     num_use_regs = extra_count;
744   else
745     num_use_regs = Re - Rb + 1 + extra_count;
746 
747   /* In addition to used registers,
748      we need one more space for (set sp sp-x) rtx.  */
749   parallel_insn = gen_rtx_PARALLEL (VOIDmode,
750 				    rtvec_alloc (num_use_regs + 1));
751   par_index = 0;
752 
753   /* Initialize offset and start to create push behavior.  */
754   offset = -(num_use_regs * 4);
755 
756   /* Create (set mem regX) from Rb, Rb+1 up to Re.  */
757   for (regno = Rb; regno <= Re; regno++)
758     {
759       /* Rb and Re may be SP_REGNUM.
760 	 We need to break this loop immediately.  */
761       if (regno == SP_REGNUM)
762 	break;
763 
764       reg = gen_rtx_REG (SImode, regno);
765       mem = gen_frame_mem (SImode, plus_constant (Pmode,
766 						  stack_pointer_rtx,
767 						  offset));
768       push_rtx = gen_rtx_SET (mem, reg);
769       XVECEXP (parallel_insn, 0, par_index) = push_rtx;
770       RTX_FRAME_RELATED_P (push_rtx) = 1;
771       offset = offset + 4;
772       par_index++;
773     }
774 
775   /* Create (set mem fp), (set mem gp), and (set mem lp) if necessary.  */
776   if (save_fp_p)
777     {
778       reg = gen_rtx_REG (SImode, FP_REGNUM);
779       mem = gen_frame_mem (SImode, plus_constant (Pmode,
780 						  stack_pointer_rtx,
781 						  offset));
782       push_rtx = gen_rtx_SET (mem, reg);
783       XVECEXP (parallel_insn, 0, par_index) = push_rtx;
784       RTX_FRAME_RELATED_P (push_rtx) = 1;
785       offset = offset + 4;
786       par_index++;
787     }
788   if (save_gp_p)
789     {
790       reg = gen_rtx_REG (SImode, GP_REGNUM);
791       mem = gen_frame_mem (SImode, plus_constant (Pmode,
792 						  stack_pointer_rtx,
793 						  offset));
794       push_rtx = gen_rtx_SET (mem, reg);
795       XVECEXP (parallel_insn, 0, par_index) = push_rtx;
796       RTX_FRAME_RELATED_P (push_rtx) = 1;
797       offset = offset + 4;
798       par_index++;
799     }
800   if (save_lp_p)
801     {
802       reg = gen_rtx_REG (SImode, LP_REGNUM);
803       mem = gen_frame_mem (SImode, plus_constant (Pmode,
804 						  stack_pointer_rtx,
805 						  offset));
806       push_rtx = gen_rtx_SET (mem, reg);
807       XVECEXP (parallel_insn, 0, par_index) = push_rtx;
808       RTX_FRAME_RELATED_P (push_rtx) = 1;
809       offset = offset + 4;
810       par_index++;
811     }
812 
813   /* Create (set sp sp-x).  */
814 
815   /* We need to re-calculate the offset value again for adjustment.  */
816   offset = -(num_use_regs * 4);
817   adjust_sp_rtx
818     = gen_rtx_SET (stack_pointer_rtx,
819 		   plus_constant (Pmode, stack_pointer_rtx, offset));
820   XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
821   RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1;
822 
823   parallel_insn = emit_insn (parallel_insn);
824 
825   /* The insn rtx 'parallel_insn' will change frame layout.
826      We need to use RTX_FRAME_RELATED_P so that GCC is able to
827      generate CFI (Call Frame Information) stuff.  */
828   RTX_FRAME_RELATED_P (parallel_insn) = 1;
829 
830   /* Don't use GCC's logic for CFI info if we are generate a push for VAARG
831      since we will not restore those register at epilogue.  */
832   if (vaarg_p)
833     {
834       dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA,
835 			      copy_rtx (adjust_sp_rtx), NULL_RTX);
836       REG_NOTES (parallel_insn) = dwarf;
837     }
838 }
839 
840 /* Function to create a parallel rtx pattern
841    which presents stack pop multiple behavior.
842    The overall concept are:
843      "pop registers from memory",
844      "adjust stack pointer".  */
845 static void
nds32_emit_stack_pop_multiple(unsigned Rb,unsigned Re,bool save_fp_p,bool save_gp_p,bool save_lp_p)846 nds32_emit_stack_pop_multiple (unsigned Rb, unsigned Re,
847 			       bool save_fp_p, bool save_gp_p, bool save_lp_p)
848 {
849   unsigned regno;
850   int extra_count;
851   int num_use_regs;
852   int par_index;
853   int offset;
854 
855   rtx reg;
856   rtx mem;
857   rtx pop_rtx;
858   rtx adjust_sp_rtx;
859   rtx parallel_insn;
860   rtx dwarf = NULL_RTX;
861 
862   /* We need to provide a customized rtx which contains
863      necessary information for data analysis,
864      so we create a parallel rtx like this:
865      (parallel [(set (reg:SI Rb)
866 		     (mem (reg:SI SP_REGNUM)))
867 		(set (reg:SI Rb+1)
868 		     (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
869 		...
870 		(set (reg:SI Re)
871 		     (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
872 		(set (reg:SI FP_REGNUM)
873 		     (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
874 		(set (reg:SI GP_REGNUM)
875 		     (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
876 		(set (reg:SI LP_REGNUM)
877 		     (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
878 		(set (reg:SI SP_REGNUM)
879 		     (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
880 
881   /* Calculate the number of registers that will be poped.  */
882   extra_count = 0;
883   if (save_fp_p)
884     extra_count++;
885   if (save_gp_p)
886     extra_count++;
887   if (save_lp_p)
888     extra_count++;
889   /* Note that Rb and Re may be SP_REGNUM.  DO NOT count it in.  */
890   if (Rb == SP_REGNUM && Re == SP_REGNUM)
891     num_use_regs = extra_count;
892   else
893     num_use_regs = Re - Rb + 1 + extra_count;
894 
895   /* In addition to used registers,
896      we need one more space for (set sp sp+x) rtx.  */
897   parallel_insn = gen_rtx_PARALLEL (VOIDmode,
898 				    rtvec_alloc (num_use_regs + 1));
899   par_index = 0;
900 
901   /* Initialize offset and start to create pop behavior.  */
902   offset = 0;
903 
904   /* Create (set regX mem) from Rb, Rb+1 up to Re.  */
905   for (regno = Rb; regno <= Re; regno++)
906     {
907       /* Rb and Re may be SP_REGNUM.
908 	 We need to break this loop immediately.  */
909       if (regno == SP_REGNUM)
910 	break;
911 
912       reg = gen_rtx_REG (SImode, regno);
913       mem = gen_frame_mem (SImode, plus_constant (Pmode,
914 						  stack_pointer_rtx,
915 						  offset));
916       pop_rtx = gen_rtx_SET (reg, mem);
917       XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
918       RTX_FRAME_RELATED_P (pop_rtx) = 1;
919       offset = offset + 4;
920       par_index++;
921 
922       dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
923     }
924 
925   /* Create (set fp mem), (set gp mem), and (set lp mem) if necessary.  */
926   if (save_fp_p)
927     {
928       reg = gen_rtx_REG (SImode, FP_REGNUM);
929       mem = gen_frame_mem (SImode, plus_constant (Pmode,
930 						  stack_pointer_rtx,
931 						  offset));
932       pop_rtx = gen_rtx_SET (reg, mem);
933       XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
934       RTX_FRAME_RELATED_P (pop_rtx) = 1;
935       offset = offset + 4;
936       par_index++;
937 
938       dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
939     }
940   if (save_gp_p)
941     {
942       reg = gen_rtx_REG (SImode, GP_REGNUM);
943       mem = gen_frame_mem (SImode, plus_constant (Pmode,
944 						  stack_pointer_rtx,
945 						  offset));
946       pop_rtx = gen_rtx_SET (reg, mem);
947       XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
948       RTX_FRAME_RELATED_P (pop_rtx) = 1;
949       offset = offset + 4;
950       par_index++;
951 
952       dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
953     }
954   if (save_lp_p)
955     {
956       reg = gen_rtx_REG (SImode, LP_REGNUM);
957       mem = gen_frame_mem (SImode, plus_constant (Pmode,
958 						  stack_pointer_rtx,
959 						  offset));
960       pop_rtx = gen_rtx_SET (reg, mem);
961       XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
962       RTX_FRAME_RELATED_P (pop_rtx) = 1;
963       offset = offset + 4;
964       par_index++;
965 
966       dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
967     }
968 
969   /* Create (set sp sp+x).  */
970 
971   /* The offset value is already in place.  No need to re-calculate it.  */
972   adjust_sp_rtx
973     = gen_rtx_SET (stack_pointer_rtx,
974 		   plus_constant (Pmode, stack_pointer_rtx, offset));
975   XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
976 
977   /* Tell gcc we adjust SP in this insn.  */
978   dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, copy_rtx (adjust_sp_rtx), dwarf);
979 
980   parallel_insn = emit_insn (parallel_insn);
981 
982   /* The insn rtx 'parallel_insn' will change frame layout.
983      We need to use RTX_FRAME_RELATED_P so that GCC is able to
984      generate CFI (Call Frame Information) stuff.  */
985   RTX_FRAME_RELATED_P (parallel_insn) = 1;
986 
987   /* Add CFI info by manual.  */
988   REG_NOTES (parallel_insn) = dwarf;
989 }
990 
991 /* Function to create a parallel rtx pattern
992    which presents stack v3push behavior.
993    The overall concept are:
994      "push registers to memory",
995      "adjust stack pointer".  */
996 static void
nds32_emit_stack_v3push(unsigned Rb,unsigned Re,unsigned imm8u)997 nds32_emit_stack_v3push (unsigned Rb,
998 			 unsigned Re,
999 			 unsigned imm8u)
1000 {
1001   unsigned regno;
1002   int num_use_regs;
1003   int par_index;
1004   int offset;
1005 
1006   rtx reg;
1007   rtx mem;
1008   rtx push_rtx;
1009   rtx adjust_sp_rtx;
1010   rtx parallel_insn;
1011 
1012   /* We need to provide a customized rtx which contains
1013      necessary information for data analysis,
1014      so we create a parallel rtx like this:
1015      (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
1016 		     (reg:SI Rb))
1017 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
1018 		     (reg:SI Rb+1))
1019 		...
1020 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
1021 		     (reg:SI Re))
1022 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
1023 		     (reg:SI FP_REGNUM))
1024 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
1025 		     (reg:SI GP_REGNUM))
1026 		(set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
1027 		     (reg:SI LP_REGNUM))
1028 		(set (reg:SI SP_REGNUM)
1029 		     (plus (reg:SI SP_REGNUM) (const_int -32-imm8u)))]) */
1030 
1031   /* Calculate the number of registers that will be pushed.
1032      Since $fp, $gp, and $lp is always pushed with v3push instruction,
1033      we need to count these three registers.
1034      Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
1035      So there is no need to worry about Rb=Re=SP_REGNUM case.  */
1036   num_use_regs = Re - Rb + 1 + 3;
1037 
1038   /* In addition to used registers,
1039      we need one more space for (set sp sp-x-imm8u) rtx.  */
1040   parallel_insn = gen_rtx_PARALLEL (VOIDmode,
1041 				    rtvec_alloc (num_use_regs + 1));
1042   par_index = 0;
1043 
1044   /* Initialize offset and start to create push behavior.  */
1045   offset = -(num_use_regs * 4);
1046 
1047   /* Create (set mem regX) from Rb, Rb+1 up to Re.
1048      Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
1049      So there is no need to worry about Rb=Re=SP_REGNUM case.  */
1050   for (regno = Rb; regno <= Re; regno++)
1051     {
1052       reg = gen_rtx_REG (SImode, regno);
1053       mem = gen_frame_mem (SImode, plus_constant (Pmode,
1054 						  stack_pointer_rtx,
1055 						  offset));
1056       push_rtx = gen_rtx_SET (mem, reg);
1057       XVECEXP (parallel_insn, 0, par_index) = push_rtx;
1058       RTX_FRAME_RELATED_P (push_rtx) = 1;
1059       offset = offset + 4;
1060       par_index++;
1061     }
1062 
1063   /* Create (set mem fp).  */
1064   reg = gen_rtx_REG (SImode, FP_REGNUM);
1065   mem = gen_frame_mem (SImode, plus_constant (Pmode,
1066 					      stack_pointer_rtx,
1067 					      offset));
1068   push_rtx = gen_rtx_SET (mem, reg);
1069   XVECEXP (parallel_insn, 0, par_index) = push_rtx;
1070   RTX_FRAME_RELATED_P (push_rtx) = 1;
1071   offset = offset + 4;
1072   par_index++;
1073   /* Create (set mem gp).  */
1074   reg = gen_rtx_REG (SImode, GP_REGNUM);
1075   mem = gen_frame_mem (SImode, plus_constant (Pmode,
1076 					      stack_pointer_rtx,
1077 					      offset));
1078   push_rtx = gen_rtx_SET (mem, reg);
1079   XVECEXP (parallel_insn, 0, par_index) = push_rtx;
1080   RTX_FRAME_RELATED_P (push_rtx) = 1;
1081   offset = offset + 4;
1082   par_index++;
1083   /* Create (set mem lp).  */
1084   reg = gen_rtx_REG (SImode, LP_REGNUM);
1085   mem = gen_frame_mem (SImode, plus_constant (Pmode,
1086 					      stack_pointer_rtx,
1087 					      offset));
1088   push_rtx = gen_rtx_SET (mem, reg);
1089   XVECEXP (parallel_insn, 0, par_index) = push_rtx;
1090   RTX_FRAME_RELATED_P (push_rtx) = 1;
1091   offset = offset + 4;
1092   par_index++;
1093 
1094   /* Create (set sp sp-x-imm8u).  */
1095 
1096   /* We need to re-calculate the offset value again for adjustment.  */
1097   offset = -(num_use_regs * 4);
1098   adjust_sp_rtx
1099     = gen_rtx_SET (stack_pointer_rtx,
1100 		   plus_constant (Pmode,
1101 				  stack_pointer_rtx,
1102 				  offset - imm8u));
1103   XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
1104   RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1;
1105 
1106   parallel_insn = emit_insn (parallel_insn);
1107 
1108   /* The insn rtx 'parallel_insn' will change frame layout.
1109      We need to use RTX_FRAME_RELATED_P so that GCC is able to
1110      generate CFI (Call Frame Information) stuff.  */
1111   RTX_FRAME_RELATED_P (parallel_insn) = 1;
1112 }
1113 
1114 /* Function to create a parallel rtx pattern
1115    which presents stack v3pop behavior.
1116    The overall concept are:
1117      "pop registers from memory",
1118      "adjust stack pointer".  */
1119 static void
nds32_emit_stack_v3pop(unsigned Rb,unsigned Re,unsigned imm8u)1120 nds32_emit_stack_v3pop (unsigned Rb,
1121 			unsigned Re,
1122 			unsigned imm8u)
1123 {
1124   unsigned regno;
1125   int num_use_regs;
1126   int par_index;
1127   int offset;
1128 
1129   rtx reg;
1130   rtx mem;
1131   rtx pop_rtx;
1132   rtx adjust_sp_rtx;
1133   rtx parallel_insn;
1134   rtx dwarf = NULL_RTX;
1135 
1136   /* We need to provide a customized rtx which contains
1137      necessary information for data analysis,
1138      so we create a parallel rtx like this:
1139      (parallel [(set (reg:SI Rb)
1140 		     (mem (reg:SI SP_REGNUM)))
1141 		(set (reg:SI Rb+1)
1142 		     (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
1143 		...
1144 		(set (reg:SI Re)
1145 		     (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
1146 		(set (reg:SI FP_REGNUM)
1147 		     (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
1148 		(set (reg:SI GP_REGNUM)
1149 		     (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
1150 		(set (reg:SI LP_REGNUM)
1151 		     (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
1152 		(set (reg:SI SP_REGNUM)
1153 		     (plus (reg:SI SP_REGNUM) (const_int 32+imm8u)))]) */
1154 
1155   /* Calculate the number of registers that will be poped.
1156      Since $fp, $gp, and $lp is always poped with v3pop instruction,
1157      we need to count these three registers.
1158      Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
1159      So there is no need to worry about Rb=Re=SP_REGNUM case.  */
1160   num_use_regs = Re - Rb + 1 + 3;
1161 
1162   /* In addition to used registers,
1163      we need one more space for (set sp sp+x+imm8u) rtx.  */
1164   parallel_insn = gen_rtx_PARALLEL (VOIDmode,
1165 				    rtvec_alloc (num_use_regs + 1));
1166   par_index = 0;
1167 
1168   /* Initialize offset and start to create pop behavior.  */
1169   offset = 0;
1170 
1171   /* Create (set regX mem) from Rb, Rb+1 up to Re.
1172      Under v3pop, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
1173      So there is no need to worry about Rb=Re=SP_REGNUM case.  */
1174   for (regno = Rb; regno <= Re; regno++)
1175     {
1176       reg = gen_rtx_REG (SImode, regno);
1177       mem = gen_frame_mem (SImode, plus_constant (Pmode,
1178 						  stack_pointer_rtx,
1179 						  offset));
1180       pop_rtx = gen_rtx_SET (reg, mem);
1181       XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
1182       RTX_FRAME_RELATED_P (pop_rtx) = 1;
1183       offset = offset + 4;
1184       par_index++;
1185 
1186       dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
1187     }
1188 
1189   /* Create (set fp mem).  */
1190   reg = gen_rtx_REG (SImode, FP_REGNUM);
1191   mem = gen_frame_mem (SImode, plus_constant (Pmode,
1192 					      stack_pointer_rtx,
1193 					      offset));
1194   pop_rtx = gen_rtx_SET (reg, mem);
1195   XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
1196   RTX_FRAME_RELATED_P (pop_rtx) = 1;
1197   offset = offset + 4;
1198   par_index++;
1199   dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
1200 
1201   /* Create (set gp mem).  */
1202   reg = gen_rtx_REG (SImode, GP_REGNUM);
1203   mem = gen_frame_mem (SImode, plus_constant (Pmode,
1204 					      stack_pointer_rtx,
1205 					      offset));
1206   pop_rtx = gen_rtx_SET (reg, mem);
1207   XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
1208   RTX_FRAME_RELATED_P (pop_rtx) = 1;
1209   offset = offset + 4;
1210   par_index++;
1211   dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
1212 
1213   /* Create (set lp mem ).  */
1214   reg = gen_rtx_REG (SImode, LP_REGNUM);
1215   mem = gen_frame_mem (SImode, plus_constant (Pmode,
1216 					      stack_pointer_rtx,
1217 					      offset));
1218   pop_rtx = gen_rtx_SET (reg, mem);
1219   XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
1220   RTX_FRAME_RELATED_P (pop_rtx) = 1;
1221   offset = offset + 4;
1222   par_index++;
1223   dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
1224 
1225   /* Create (set sp sp+x+imm8u).  */
1226 
1227   /* The offset value is already in place.  No need to re-calculate it.  */
1228   adjust_sp_rtx
1229     = gen_rtx_SET (stack_pointer_rtx,
1230 		   plus_constant (Pmode,
1231 				  stack_pointer_rtx,
1232 				  offset + imm8u));
1233   XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
1234 
1235   if (frame_pointer_needed)
1236     {
1237       /* (expr_list:REG_CFA_DEF_CFA (plus:SI (reg/f:SI $sp)
1238 					     (const_int 0))
1239 	 mean reset frame pointer to $sp and reset to offset 0.  */
1240       rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
1241 					 const0_rtx);
1242       dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf);
1243     }
1244   else
1245     {
1246       /* Tell gcc we adjust SP in this insn.  */
1247       dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA,
1248 			      copy_rtx (adjust_sp_rtx), dwarf);
1249     }
1250 
1251   parallel_insn = emit_insn (parallel_insn);
1252 
1253   /* The insn rtx 'parallel_insn' will change frame layout.
1254      We need to use RTX_FRAME_RELATED_P so that GCC is able to
1255      generate CFI (Call Frame Information) stuff.  */
1256   RTX_FRAME_RELATED_P (parallel_insn) = 1;
1257 
1258   /* Add CFI info by manual.  */
1259   REG_NOTES (parallel_insn) = dwarf;
1260 }
1261 
1262 /* Function that may creates more instructions
1263    for large value on adjusting stack pointer.
1264 
1265    In nds32 target, 'addi' can be used for stack pointer
1266    adjustment in prologue/epilogue stage.
1267    However, sometimes there are too many local variables so that
1268    the adjustment value is not able to be fit in the 'addi' instruction.
1269    One solution is to move value into a register
1270    and then use 'add' instruction.
1271    In practice, we use TA_REGNUM ($r15) to accomplish this purpose.  */
1272 static void
nds32_emit_adjust_frame(rtx to_reg,rtx from_reg,int adjust_value)1273 nds32_emit_adjust_frame (rtx to_reg, rtx from_reg, int adjust_value)
1274 {
1275   rtx tmp_reg;
1276   rtx frame_adjust_insn;
1277   rtx adjust_value_rtx = GEN_INT (adjust_value);
1278 
1279   if (adjust_value == 0)
1280     return;
1281 
1282   if (!satisfies_constraint_Is15 (adjust_value_rtx))
1283     {
1284       /* The value is not able to fit in single addi instruction.
1285 	 Create more instructions of moving value into a register
1286 	 and then add stack pointer with it.  */
1287 
1288       /* $r15 is going to be temporary register to hold the value.  */
1289       tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
1290 
1291       /* Create one more instruction to move value
1292 	 into the temporary register.  */
1293       emit_move_insn (tmp_reg, adjust_value_rtx);
1294 
1295       /* Create new 'add' rtx.  */
1296       frame_adjust_insn = gen_addsi3 (to_reg,
1297 				      from_reg,
1298 				      tmp_reg);
1299       /* Emit rtx into insn list and receive its transformed insn rtx.  */
1300       frame_adjust_insn = emit_insn (frame_adjust_insn);
1301 
1302       /* Because (tmp_reg <- full_value) may be split into two
1303 	 rtl patterns, we can not set its RTX_FRAME_RELATED_P.
1304 	 We need to construct another (sp <- sp + full_value)
1305 	 and then insert it into sp_adjust_insn's reg note to
1306 	 represent a frame related expression.
1307 	 GCC knows how to refer it and output debug information.  */
1308 
1309       rtx plus_rtx;
1310       rtx set_rtx;
1311 
1312       plus_rtx = plus_constant (Pmode, from_reg, adjust_value);
1313       set_rtx = gen_rtx_SET (to_reg, plus_rtx);
1314       add_reg_note (frame_adjust_insn, REG_FRAME_RELATED_EXPR, set_rtx);
1315     }
1316   else
1317     {
1318       /* Generate sp adjustment instruction if and only if sp_adjust != 0.  */
1319       frame_adjust_insn = gen_addsi3 (to_reg,
1320 				      from_reg,
1321 				      adjust_value_rtx);
1322       /* Emit rtx into instructions list and receive INSN rtx form.  */
1323       frame_adjust_insn = emit_insn (frame_adjust_insn);
1324     }
1325 
1326     /* The insn rtx 'sp_adjust_insn' will change frame layout.
1327        We need to use RTX_FRAME_RELATED_P so that GCC is able to
1328        generate CFI (Call Frame Information) stuff.  */
1329     RTX_FRAME_RELATED_P (frame_adjust_insn) = 1;
1330 }
1331 
1332 /* Return true if MODE/TYPE need double word alignment.  */
1333 static bool
nds32_needs_double_word_align(machine_mode mode,const_tree type)1334 nds32_needs_double_word_align (machine_mode mode, const_tree type)
1335 {
1336   unsigned int align;
1337 
1338   /* Pick up the alignment according to the mode or type.  */
1339   align = NDS32_MODE_TYPE_ALIGN (mode, type);
1340 
1341   return (align > PARM_BOUNDARY);
1342 }
1343 
1344 /* Return true if FUNC is a naked function.  */
1345 static bool
nds32_naked_function_p(tree func)1346 nds32_naked_function_p (tree func)
1347 {
1348   tree t;
1349 
1350   if (TREE_CODE (func) != FUNCTION_DECL)
1351     abort ();
1352 
1353   t = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
1354 
1355   return (t != NULL_TREE);
1356 }
1357 
1358 /* Function that determine whether a load postincrement is a good thing to use
1359    for a given mode.  */
1360 bool
nds32_use_load_post_increment(machine_mode mode)1361 nds32_use_load_post_increment (machine_mode mode)
1362 {
1363   return (GET_MODE_SIZE (mode) <= GET_MODE_SIZE(E_DImode));
1364 }
1365 
1366 /* Function that check if 'X' is a valid address register.
1367    The variable 'STRICT' is very important to
1368    make decision for register number.
1369 
1370    STRICT : true
1371      => We are in reload pass or after reload pass.
1372 	The register number should be strictly limited in general registers.
1373 
1374    STRICT : false
1375      => Before reload pass, we are free to use any register number.  */
1376 static bool
nds32_address_register_rtx_p(rtx x,bool strict)1377 nds32_address_register_rtx_p (rtx x, bool strict)
1378 {
1379   int regno;
1380 
1381   if (GET_CODE (x) != REG)
1382     return false;
1383 
1384   regno = REGNO (x);
1385 
1386   if (strict)
1387     return REGNO_OK_FOR_BASE_P (regno);
1388   else
1389     return true;
1390 }
1391 
1392 /* Function that check if 'INDEX' is valid to be a index rtx for address.
1393 
1394    OUTER_MODE : Machine mode of outer address rtx.
1395 	INDEX : Check if this rtx is valid to be a index for address.
1396        STRICT : If it is true, we are in reload pass or after reload pass.  */
1397 static bool
nds32_legitimate_index_p(machine_mode outer_mode,rtx index,bool strict)1398 nds32_legitimate_index_p (machine_mode outer_mode,
1399 			  rtx index,
1400 			  bool strict)
1401 {
1402   int regno;
1403   rtx op0;
1404   rtx op1;
1405 
1406   switch (GET_CODE (index))
1407     {
1408     case REG:
1409       regno = REGNO (index);
1410       /* If we are in reload pass or after reload pass,
1411 	 we need to limit it to general register.  */
1412       if (strict)
1413 	return REGNO_OK_FOR_INDEX_P (regno);
1414       else
1415 	return true;
1416 
1417     case CONST_INT:
1418       /* The alignment of the integer value is determined by 'outer_mode'.  */
1419       switch (GET_MODE_SIZE (outer_mode))
1420 	{
1421 	case 1:
1422 	  /* Further check if the value is legal for the 'outer_mode'.  */
1423 	  if (satisfies_constraint_Is15 (index))
1424 	    return true;
1425 	  break;
1426 
1427 	case 2:
1428 	  /* Further check if the value is legal for the 'outer_mode'.  */
1429 	  if (satisfies_constraint_Is16 (index))
1430 	    {
1431 	      /* If it is not under strictly aligned situation,
1432 		 we can return true without checking alignment.  */
1433 	      if (!cfun->machine->strict_aligned_p)
1434 		return true;
1435 	      /* Make sure address is half word alignment.  */
1436 	      else if (NDS32_HALF_WORD_ALIGN_P (INTVAL (index)))
1437 		return true;
1438 	    }
1439 	  break;
1440 
1441 	case 4:
1442 	  /* Further check if the value is legal for the 'outer_mode'.  */
1443 	  if (satisfies_constraint_Is17 (index))
1444 	    {
1445 	      if ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE))
1446 		{
1447 		  if (!satisfies_constraint_Is14 (index))
1448 		    return false;
1449 		}
1450 
1451 	      /* If it is not under strictly aligned situation,
1452 		 we can return true without checking alignment.  */
1453 	      if (!cfun->machine->strict_aligned_p)
1454 		return true;
1455 	      /* Make sure address is word alignment.  */
1456 	      else if (NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index)))
1457 		return true;
1458 	    }
1459 	  break;
1460 
1461 	case 8:
1462 	  if (satisfies_constraint_Is17 (gen_int_mode (INTVAL (index) + 4,
1463 						       SImode)))
1464 	    {
1465 	      if ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE))
1466 		{
1467 		  if (!satisfies_constraint_Is14 (index))
1468 		    return false;
1469 		}
1470 
1471 	      /* If it is not under strictly aligned situation,
1472 		 we can return true without checking alignment.  */
1473 	      if (!cfun->machine->strict_aligned_p)
1474 		return true;
1475 	      /* Make sure address is word alignment.
1476 		Currently we do not have 64-bit load/store yet,
1477 		so we will use two 32-bit load/store instructions to do
1478 		memory access and they are single word alignment.  */
1479 	      else if (NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index)))
1480 		return true;
1481 	    }
1482 	  break;
1483 
1484 	default:
1485 	  return false;
1486 	}
1487 
1488       return false;
1489 
1490     case MULT:
1491       op0 = XEXP (index, 0);
1492       op1 = XEXP (index, 1);
1493 
1494       if (REG_P (op0) && CONST_INT_P (op1))
1495 	{
1496 	  int multiplier;
1497 	  multiplier = INTVAL (op1);
1498 
1499 	  /* We only allow (mult reg const_int_1), (mult reg const_int_2),
1500 	     (mult reg const_int_4) or (mult reg const_int_8).  */
1501 	  if (multiplier != 1 && multiplier != 2
1502 	      && multiplier != 4 && multiplier != 8)
1503 	    return false;
1504 
1505 	  regno = REGNO (op0);
1506 	  /* Limit it in general registers if we are
1507 	     in reload pass or after reload pass.  */
1508 	  if(strict)
1509 	    return REGNO_OK_FOR_INDEX_P (regno);
1510 	  else
1511 	    return true;
1512 	}
1513 
1514       return false;
1515 
1516     case ASHIFT:
1517       op0 = XEXP (index, 0);
1518       op1 = XEXP (index, 1);
1519 
1520       if (REG_P (op0) && CONST_INT_P (op1))
1521 	{
1522 	  int sv;
1523 	  /* op1 is already the sv value for use to do left shift.  */
1524 	  sv = INTVAL (op1);
1525 
1526 	  /* We only allow (ashift reg const_int_0)
1527 	     or (ashift reg const_int_1) or (ashift reg const_int_2) or
1528 	     (ashift reg const_int_3).  */
1529 	  if (sv != 0 && sv != 1 && sv !=2 && sv != 3)
1530 	    return false;
1531 
1532 	  regno = REGNO (op0);
1533 	  /* Limit it in general registers if we are
1534 	     in reload pass or after reload pass.  */
1535 	  if(strict)
1536 	    return REGNO_OK_FOR_INDEX_P (regno);
1537 	  else
1538 	    return true;
1539 	}
1540 
1541       return false;
1542 
1543     default:
1544       return false;
1545     }
1546 }
1547 
1548 static void
nds32_register_pass(rtl_opt_pass * (* make_pass_func)(gcc::context *),enum pass_positioning_ops pass_pos,const char * ref_pass_name)1549 nds32_register_pass (
1550   rtl_opt_pass *(*make_pass_func) (gcc::context *),
1551   enum pass_positioning_ops pass_pos,
1552   const char *ref_pass_name)
1553 {
1554   opt_pass *new_opt_pass = make_pass_func (g);
1555 
1556   struct register_pass_info insert_pass =
1557     {
1558       new_opt_pass,	/* pass */
1559       ref_pass_name,	/* reference_pass_name */
1560       1,		/* ref_pass_instance_number */
1561       pass_pos		/* po_op */
1562     };
1563 
1564   register_pass (&insert_pass);
1565 }
1566 
1567 /* This function is called from nds32_option_override ().
1568    All new passes should be registered here.  */
1569 static void
nds32_register_passes(void)1570 nds32_register_passes (void)
1571 {
1572   nds32_register_pass (
1573     make_pass_nds32_relax_opt,
1574     PASS_POS_INSERT_AFTER,
1575     "mach");
1576 }
1577 
1578 /* ------------------------------------------------------------------------ */
1579 
1580 /* PART 3: Implement target hook stuff definitions.  */
1581 
1582 
1583 /* Computing the Length of an Insn.
1584    Modifies the length assigned to instruction INSN.
1585    LEN is the initially computed length of the insn.  */
1586 int
nds32_adjust_insn_length(rtx_insn * insn,int length)1587 nds32_adjust_insn_length (rtx_insn *insn, int length)
1588 {
1589   int adjust_value = 0;
1590   switch (recog_memoized (insn))
1591     {
1592     case CODE_FOR_call_internal:
1593     case CODE_FOR_call_value_internal:
1594       {
1595 	if (NDS32_ALIGN_P ())
1596 	  {
1597 	    rtx_insn *next_insn = next_active_insn (insn);
1598 	    if (next_insn && get_attr_length (next_insn) != 2)
1599 	      adjust_value += 2;
1600 	  }
1601 	/* We need insert a nop after a noretun function call
1602 	   to prevent software breakpoint corrupt the next function. */
1603 	if (find_reg_note (insn, REG_NORETURN, NULL_RTX))
1604 	  {
1605 	    if (TARGET_16_BIT)
1606 	      adjust_value += 2;
1607 	    else
1608 	      adjust_value += 4;
1609 	  }
1610       }
1611       return length + adjust_value;
1612 
1613     default:
1614       return length;
1615     }
1616 }
1617 
1618 /* Storage Layout.  */
1619 
1620 /* This function will be called just before expansion into rtl.  */
1621 static void
nds32_expand_to_rtl_hook(void)1622 nds32_expand_to_rtl_hook (void)
1623 {
1624   /* We need to set strictly aligned situation.
1625      After that, the memory address checking in nds32_legitimate_address_p()
1626      will take alignment offset into consideration so that it will not create
1627      unaligned [base + offset] access during the rtl optimization.  */
1628   cfun->machine->strict_aligned_p = 1;
1629 }
1630 
1631 
1632 /* Register Usage.  */
1633 
1634 static void
nds32_conditional_register_usage(void)1635 nds32_conditional_register_usage (void)
1636 {
1637   int regno;
1638 
1639   if (TARGET_HARD_FLOAT)
1640     {
1641       for (regno = NDS32_FIRST_FPR_REGNUM;
1642 	   regno <= NDS32_LAST_FPR_REGNUM; regno++)
1643 	{
1644 	  fixed_regs[regno] = 0;
1645 	  if (regno < NDS32_FIRST_FPR_REGNUM + NDS32_MAX_FPR_REGS_FOR_ARGS)
1646 	    call_used_regs[regno] = 1;
1647 	  else if (regno >= NDS32_FIRST_FPR_REGNUM + 22
1648 		   && regno < NDS32_FIRST_FPR_REGNUM + 48)
1649 	    call_used_regs[regno] = 1;
1650 	  else
1651 	    call_used_regs[regno] = 0;
1652 	}
1653     }
1654   else if (TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)
1655     {
1656       for (regno = NDS32_FIRST_FPR_REGNUM;
1657 	   regno <= NDS32_LAST_FPR_REGNUM;
1658 	   regno++)
1659 	fixed_regs[regno] = 0;
1660     }
1661 }
1662 
1663 
1664 /* Register Classes.  */
1665 
1666 static unsigned char
nds32_class_max_nregs(reg_class_t rclass ATTRIBUTE_UNUSED,machine_mode mode)1667 nds32_class_max_nregs (reg_class_t rclass ATTRIBUTE_UNUSED,
1668 		       machine_mode mode)
1669 {
1670   /* Return the maximum number of consecutive registers
1671      needed to represent "mode" in a register of "rclass".  */
1672   return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1673 }
1674 
1675 static int
nds32_register_priority(int hard_regno)1676 nds32_register_priority (int hard_regno)
1677 {
1678   /* Encourage to use r0-r7 for LRA when optimize for size.  */
1679   if (optimize_size)
1680     {
1681       if (hard_regno < 8)
1682 	return 4;
1683       else if (hard_regno < 16)
1684 	return 3;
1685       else if (hard_regno < 28)
1686 	return 2;
1687       else
1688 	return 1;
1689     }
1690   else
1691     {
1692       if (hard_regno > 27)
1693 	return 1;
1694       else
1695 	return 4;
1696     }
1697 }
1698 
1699 static bool
nds32_can_change_mode_class(machine_mode from,machine_mode to,reg_class_t rclass)1700 nds32_can_change_mode_class (machine_mode from,
1701 			     machine_mode to,
1702 			     reg_class_t rclass)
1703 {
1704   /* Don't spill double-precision register to two singal-precision
1705      registers  */
1706   if ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)
1707        && GET_MODE_SIZE (from) != GET_MODE_SIZE (to))
1708     {
1709       return !reg_classes_intersect_p (rclass, FP_REGS);
1710     }
1711 
1712   return true;
1713 }
1714 
1715 
1716 /* Stack Layout and Calling Conventions.  */
1717 
1718 /* There are three kinds of pointer concepts using in GCC compiler:
1719 
1720      frame pointer: A pointer to the first location of local variables.
1721      stack pointer: A pointer to the top of a stack frame.
1722      argument pointer: A pointer to the incoming arguments.
1723 
1724    In nds32 target calling convention, we are using 8-byte alignment.
1725    Besides, we would like to have each stack frame of a function includes:
1726 
1727      [Block A]
1728        1. previous hard frame pointer
1729        2. return address
1730        3. callee-saved registers
1731        4. <padding bytes> (we will calculte in nds32_compute_stack_frame()
1732 			   and save it at
1733 			   cfun->machine->callee_saved_area_padding_bytes)
1734 
1735      [Block B]
1736        1. local variables
1737        2. spilling location
1738        3. <padding bytes> (it will be calculated by GCC itself)
1739        4. incoming arguments
1740        5. <padding bytes> (it will be calculated by GCC itself)
1741 
1742      [Block C]
1743        1. <padding bytes> (it will be calculated by GCC itself)
1744        2. outgoing arguments
1745 
1746    We 'wrap' these blocks together with
1747    hard frame pointer ($r28) and stack pointer ($r31).
1748    By applying the basic frame/stack/argument pointers concept,
1749    the layout of a stack frame shoule be like this:
1750 
1751 			    |    |
1752        old stack pointer ->  ----
1753 			    |    | \
1754 			    |    |   saved arguments for
1755 			    |    |   vararg functions
1756 			    |    | /
1757       hard frame pointer ->   --
1758       & argument pointer    |    | \
1759 			    |    |   previous hardware frame pointer
1760 			    |    |   return address
1761 			    |    |   callee-saved registers
1762 			    |    | /
1763 	   frame pointer ->   --
1764 			    |    | \
1765 			    |    |   local variables
1766 			    |    |   and incoming arguments
1767 			    |    | /
1768 			      --
1769 			    |    | \
1770 			    |    |   outgoing
1771 			    |    |   arguments
1772 			    |    | /
1773 	   stack pointer ->  ----
1774 
1775   $SFP and $AP are used to represent frame pointer and arguments pointer,
1776   which will be both eliminated as hard frame pointer.  */
1777 
1778 /* -- Eliminating Frame Pointer and Arg Pointer.  */
1779 
1780 static bool
nds32_can_eliminate(const int from_reg,const int to_reg)1781 nds32_can_eliminate (const int from_reg, const int to_reg)
1782 {
1783   if (from_reg == ARG_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM)
1784     return true;
1785 
1786   if (from_reg == ARG_POINTER_REGNUM && to_reg == HARD_FRAME_POINTER_REGNUM)
1787     return true;
1788 
1789   if (from_reg == FRAME_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM)
1790     return true;
1791 
1792   if (from_reg == FRAME_POINTER_REGNUM && to_reg == HARD_FRAME_POINTER_REGNUM)
1793     return true;
1794 
1795   return false;
1796 }
1797 
1798 /* -- Passing Arguments in Registers.  */
1799 
1800 static rtx
nds32_function_arg(cumulative_args_t ca,machine_mode mode,const_tree type,bool named)1801 nds32_function_arg (cumulative_args_t ca, machine_mode mode,
1802 		    const_tree type, bool named)
1803 {
1804   unsigned int regno;
1805   CUMULATIVE_ARGS *cum = get_cumulative_args (ca);
1806 
1807   /* The last time this hook is called,
1808      it is called with MODE == VOIDmode.  */
1809   if (mode == VOIDmode)
1810     return NULL_RTX;
1811 
1812   /* For nameless arguments, we need to take care it individually.  */
1813   if (!named)
1814     {
1815       /* If we are under hard float abi, we have arguments passed on the
1816 	 stack and all situation can be handled by GCC itself.  */
1817       if (TARGET_HARD_FLOAT)
1818 	return NULL_RTX;
1819 
1820       if (NDS32_ARG_PARTIAL_IN_GPR_REG_P (cum->gpr_offset, mode, type))
1821 	{
1822 	  /* If we still have enough registers to pass argument, pick up
1823 	     next available register number.  */
1824 	  regno
1825 	    = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type);
1826 	  return gen_rtx_REG (mode, regno);
1827 	}
1828 
1829       /* No register available, return NULL_RTX.
1830 	 The compiler will use stack to pass argument instead.  */
1831       return NULL_RTX;
1832     }
1833 
1834   /* The following is to handle named argument.
1835      Note that the strategies of TARGET_HARD_FLOAT and !TARGET_HARD_FLOAT
1836      are different.  */
1837   if (TARGET_HARD_FLOAT)
1838     {
1839       /* For TARGET_HARD_FLOAT calling convention, we use GPR and FPR
1840 	 to pass argument.  We have to further check TYPE and MODE so
1841 	 that we can determine which kind of register we shall use.  */
1842 
1843       /* Note that we need to pass argument entirely in registers under
1844 	 hard float abi.  */
1845       if (GET_MODE_CLASS (mode) == MODE_FLOAT
1846 	  && NDS32_ARG_ENTIRE_IN_FPR_REG_P (cum->fpr_offset, mode, type))
1847 	{
1848 	  /* Pick up the next available FPR register number.  */
1849 	  regno
1850 	    = NDS32_AVAILABLE_REGNUM_FOR_FPR_ARG (cum->fpr_offset, mode, type);
1851 	  return gen_rtx_REG (mode, regno);
1852 	}
1853       else if (GET_MODE_CLASS (mode) != MODE_FLOAT
1854 	       && NDS32_ARG_ENTIRE_IN_GPR_REG_P (cum->gpr_offset, mode, type))
1855 	{
1856 	  /* Pick up the next available GPR register number.  */
1857 	  regno
1858 	    = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type);
1859 	  return gen_rtx_REG (mode, regno);
1860 	}
1861     }
1862   else
1863     {
1864       /* For !TARGET_HARD_FLOAT calling convention, we always use GPR to pass
1865 	 argument.  Since we allow to pass argument partially in registers,
1866 	 we can just return it if there are still registers available.  */
1867       if (NDS32_ARG_PARTIAL_IN_GPR_REG_P (cum->gpr_offset, mode, type))
1868 	{
1869 	  /* Pick up the next available register number.  */
1870 	  regno
1871 	    = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type);
1872 	  return gen_rtx_REG (mode, regno);
1873 	}
1874 
1875     }
1876 
1877   /* No register available, return NULL_RTX.
1878      The compiler will use stack to pass argument instead.  */
1879   return NULL_RTX;
1880 }
1881 
1882 static bool
nds32_must_pass_in_stack(machine_mode mode,const_tree type)1883 nds32_must_pass_in_stack (machine_mode mode, const_tree type)
1884 {
1885   /* Return true if a type must be passed in memory.
1886      If it is NOT using hard float abi, small aggregates can be
1887      passed in a register even we are calling a variadic function.
1888      So there is no need to take padding into consideration.  */
1889   if (TARGET_HARD_FLOAT)
1890     return must_pass_in_stack_var_size_or_pad (mode, type);
1891   else
1892     return must_pass_in_stack_var_size (mode, type);
1893 }
1894 
1895 static int
nds32_arg_partial_bytes(cumulative_args_t ca,machine_mode mode,tree type,bool named ATTRIBUTE_UNUSED)1896 nds32_arg_partial_bytes (cumulative_args_t ca, machine_mode mode,
1897 			 tree type, bool named ATTRIBUTE_UNUSED)
1898 {
1899   /* Returns the number of bytes at the beginning of an argument that
1900      must be put in registers.  The value must be zero for arguments that are
1901      passed entirely in registers or that are entirely pushed on the stack.
1902      Besides, TARGET_FUNCTION_ARG for these arguments should return the
1903      first register to be used by the caller for this argument.  */
1904   unsigned int needed_reg_count;
1905   unsigned int remaining_reg_count;
1906   CUMULATIVE_ARGS *cum;
1907 
1908   cum = get_cumulative_args (ca);
1909 
1910   /* Under hard float abi, we better have argument entirely passed in
1911      registers or pushed on the stack so that we can reduce the complexity
1912      of dealing with cum->gpr_offset and cum->fpr_offset.  */
1913   if (TARGET_HARD_FLOAT)
1914     return 0;
1915 
1916   /* If we have already runned out of argument registers, return zero
1917      so that the argument will be entirely pushed on the stack.  */
1918   if (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
1919       >= NDS32_GPR_ARG_FIRST_REGNUM + NDS32_MAX_GPR_REGS_FOR_ARGS)
1920     return 0;
1921 
1922   /* Calculate how many registers do we need for this argument.  */
1923   needed_reg_count = NDS32_NEED_N_REGS_FOR_ARG (mode, type);
1924 
1925   /* Calculate how many argument registers have left for passing argument.
1926      Note that we should count it from next available register number.  */
1927   remaining_reg_count
1928     = NDS32_MAX_GPR_REGS_FOR_ARGS
1929       - (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
1930 	 - NDS32_GPR_ARG_FIRST_REGNUM);
1931 
1932   /* Note that we have to return the nubmer of bytes, not registers count.  */
1933   if (needed_reg_count > remaining_reg_count)
1934     return remaining_reg_count * UNITS_PER_WORD;
1935 
1936   return 0;
1937 }
1938 
1939 static void
nds32_function_arg_advance(cumulative_args_t ca,machine_mode mode,const_tree type,bool named)1940 nds32_function_arg_advance (cumulative_args_t ca, machine_mode mode,
1941 			    const_tree type, bool named)
1942 {
1943   CUMULATIVE_ARGS *cum = get_cumulative_args (ca);
1944 
1945   if (named)
1946     {
1947       /* We need to further check TYPE and MODE so that we can determine
1948 	 which kind of register we shall advance.  */
1949 
1950       /* Under hard float abi, we may advance FPR registers.  */
1951       if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
1952 	{
1953 	  cum->fpr_offset
1954 	    = NDS32_AVAILABLE_REGNUM_FOR_FPR_ARG (cum->fpr_offset, mode, type)
1955 	      - NDS32_FPR_ARG_FIRST_REGNUM
1956 	      + NDS32_NEED_N_REGS_FOR_ARG (mode, type);
1957 	}
1958       else
1959 	{
1960 	  cum->gpr_offset
1961 	    = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
1962 	      - NDS32_GPR_ARG_FIRST_REGNUM
1963 	      + NDS32_NEED_N_REGS_FOR_ARG (mode, type);
1964 	}
1965     }
1966   else
1967     {
1968       /* If this nameless argument is NOT under TARGET_HARD_FLOAT,
1969 	 we can advance next register as well so that caller is
1970 	 able to pass arguments in registers and callee must be
1971 	 in charge of pushing all of them into stack.  */
1972       if (!TARGET_HARD_FLOAT)
1973 	{
1974 	  cum->gpr_offset
1975 	    = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
1976 	      - NDS32_GPR_ARG_FIRST_REGNUM
1977 	      + NDS32_NEED_N_REGS_FOR_ARG (mode, type);
1978 	}
1979     }
1980 }
1981 
1982 static unsigned int
nds32_function_arg_boundary(machine_mode mode,const_tree type)1983 nds32_function_arg_boundary (machine_mode mode, const_tree type)
1984 {
1985   return (nds32_needs_double_word_align (mode, type)
1986 	  ? NDS32_DOUBLE_WORD_ALIGNMENT
1987 	  : PARM_BOUNDARY);
1988 }
1989 
1990 /* -- How Scalar Function Values Are Returned.  */
1991 
1992 static rtx
nds32_function_value(const_tree ret_type,const_tree fn_decl_or_type ATTRIBUTE_UNUSED,bool outgoing ATTRIBUTE_UNUSED)1993 nds32_function_value (const_tree ret_type,
1994 		      const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1995 		      bool outgoing ATTRIBUTE_UNUSED)
1996 {
1997   machine_mode mode;
1998   int unsignedp;
1999 
2000   mode = TYPE_MODE (ret_type);
2001   unsignedp = TYPE_UNSIGNED (ret_type);
2002 
2003   if (INTEGRAL_TYPE_P (ret_type))
2004     mode = promote_mode (ret_type, mode, &unsignedp);
2005 
2006   if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode))
2007     return gen_rtx_REG (mode, NDS32_FPR_RET_FIRST_REGNUM);
2008   else
2009     return gen_rtx_REG (mode, NDS32_GPR_RET_FIRST_REGNUM);
2010 }
2011 
2012 static rtx
nds32_libcall_value(machine_mode mode,const_rtx fun ATTRIBUTE_UNUSED)2013 nds32_libcall_value (machine_mode mode,
2014 		     const_rtx fun ATTRIBUTE_UNUSED)
2015 {
2016   if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode))
2017     return gen_rtx_REG (mode, NDS32_FPR_RET_FIRST_REGNUM);
2018 
2019   return gen_rtx_REG (mode, NDS32_GPR_RET_FIRST_REGNUM);
2020 }
2021 
2022 static bool
nds32_function_value_regno_p(const unsigned int regno)2023 nds32_function_value_regno_p (const unsigned int regno)
2024 {
2025   if (regno == NDS32_GPR_RET_FIRST_REGNUM
2026       || (TARGET_HARD_FLOAT
2027 	  && regno == NDS32_FPR_RET_FIRST_REGNUM))
2028     return true;
2029 
2030   return false;
2031 }
2032 
2033 /* -- How Large Values Are Returned.  */
2034 
2035 static bool
nds32_return_in_memory(const_tree type,const_tree fntype ATTRIBUTE_UNUSED)2036 nds32_return_in_memory (const_tree type,
2037 			const_tree fntype ATTRIBUTE_UNUSED)
2038 {
2039   /* Note that int_size_in_bytes can return -1 if the size can vary
2040      or is larger than an integer.  */
2041   HOST_WIDE_INT size = int_size_in_bytes (type);
2042 
2043   /* For COMPLEX_TYPE, if the total size cannot be hold within two registers,
2044      the return value is supposed to be in memory.  We need to be aware of
2045      that the size may be -1.  */
2046   if (TREE_CODE (type) == COMPLEX_TYPE)
2047     if (size < 0 || size > 2 * UNITS_PER_WORD)
2048       return true;
2049 
2050   /* If it is BLKmode and the total size cannot be hold within two registers,
2051      the return value is supposed to be in memory.  We need to be aware of
2052      that the size may be -1.  */
2053   if (TYPE_MODE (type) == BLKmode)
2054     if (size < 0 || size > 2 * UNITS_PER_WORD)
2055       return true;
2056 
2057   /* For other cases, having result in memory is unnecessary.  */
2058   return false;
2059 }
2060 
2061 /* -- Function Entry and Exit.  */
2062 
2063 /* The content produced from this function
2064    will be placed before prologue body.  */
2065 static void
nds32_asm_function_prologue(FILE * file)2066 nds32_asm_function_prologue (FILE *file)
2067 {
2068   int r;
2069   const char *func_name;
2070   tree attrs;
2071   tree name;
2072 
2073   /* All stack frame information is supposed to be
2074      already computed when expanding prologue.
2075      The result is in cfun->machine.
2076      DO NOT call nds32_compute_stack_frame() here
2077      because it may corrupt the essential information.  */
2078 
2079   fprintf (file, "\t! BEGIN PROLOGUE\n");
2080   fprintf (file, "\t!     fp needed: %d\n", frame_pointer_needed);
2081   fprintf (file, "\t!  pretend_args: %d\n", cfun->machine->va_args_size);
2082   fprintf (file, "\t!    local_size: %d\n", cfun->machine->local_size);
2083   fprintf (file, "\t! out_args_size: %d\n", cfun->machine->out_args_size);
2084 
2085   /* Use df_regs_ever_live_p() to detect if the register
2086      is ever used in the current function.  */
2087   fprintf (file, "\t! registers ever_live: ");
2088   for (r = 0; r < 65; r++)
2089     {
2090       if (df_regs_ever_live_p (r))
2091 	fprintf (file, "%s, ", reg_names[r]);
2092     }
2093   fputc ('\n', file);
2094 
2095   /* Display the attributes of this function.  */
2096   fprintf (file, "\t! function attributes: ");
2097   /* Get the attributes tree list.
2098      Note that GCC builds attributes list with reverse order.  */
2099   attrs = DECL_ATTRIBUTES (current_function_decl);
2100 
2101   /* If there is no any attribute, print out "None".  */
2102   if (!attrs)
2103     fprintf (file, "None");
2104 
2105   /* If there are some attributes, try if we need to
2106      construct isr vector information.  */
2107   func_name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
2108   nds32_construct_isr_vectors_information (attrs, func_name);
2109 
2110   /* Display all attributes of this function.  */
2111   while (attrs)
2112     {
2113       name = TREE_PURPOSE (attrs);
2114       fprintf (file, "%s ", IDENTIFIER_POINTER (name));
2115 
2116       /* Pick up the next attribute.  */
2117       attrs = TREE_CHAIN (attrs);
2118     }
2119   fputc ('\n', file);
2120 }
2121 
2122 /* After rtl prologue has been expanded, this function is used.  */
2123 static void
nds32_asm_function_end_prologue(FILE * file)2124 nds32_asm_function_end_prologue (FILE *file)
2125 {
2126   fprintf (file, "\t! END PROLOGUE\n");
2127 
2128   /* If frame pointer is NOT needed and -mfp-as-gp is issued,
2129      we can generate special directive: ".omit_fp_begin"
2130      to guide linker doing fp-as-gp optimization.
2131      However, for a naked function, which means
2132      it should not have prologue/epilogue,
2133      using fp-as-gp still requires saving $fp by push/pop behavior and
2134      there is no benefit to use fp-as-gp on such small function.
2135      So we need to make sure this function is NOT naked as well.  */
2136   if (!frame_pointer_needed
2137       && !cfun->machine->naked_p
2138       && cfun->machine->fp_as_gp_p)
2139     {
2140       fprintf (file, "\t! ----------------------------------------\n");
2141       fprintf (file, "\t! Guide linker to do "
2142 		     "link time optimization: fp-as-gp\n");
2143       fprintf (file, "\t! We add one more instruction to "
2144 		     "initialize $fp near to $gp location.\n");
2145       fprintf (file, "\t! If linker fails to use fp-as-gp transformation,\n");
2146       fprintf (file, "\t! this extra instruction should be "
2147 		     "eliminated at link stage.\n");
2148       fprintf (file, "\t.omit_fp_begin\n");
2149       fprintf (file, "\tla\t$fp,_FP_BASE_\n");
2150       fprintf (file, "\t! ----------------------------------------\n");
2151     }
2152 }
2153 
2154 /* Before rtl epilogue has been expanded, this function is used.  */
2155 static void
nds32_asm_function_begin_epilogue(FILE * file)2156 nds32_asm_function_begin_epilogue (FILE *file)
2157 {
2158   /* If frame pointer is NOT needed and -mfp-as-gp is issued,
2159      we can generate special directive: ".omit_fp_end"
2160      to claim fp-as-gp optimization range.
2161      However, for a naked function,
2162      which means it should not have prologue/epilogue,
2163      using fp-as-gp still requires saving $fp by push/pop behavior and
2164      there is no benefit to use fp-as-gp on such small function.
2165      So we need to make sure this function is NOT naked as well.  */
2166   if (!frame_pointer_needed
2167       && !cfun->machine->naked_p
2168       && cfun->machine->fp_as_gp_p)
2169     {
2170       fprintf (file, "\t! ----------------------------------------\n");
2171       fprintf (file, "\t! Claim the range of fp-as-gp "
2172 		     "link time optimization\n");
2173       fprintf (file, "\t.omit_fp_end\n");
2174       fprintf (file, "\t! ----------------------------------------\n");
2175     }
2176 
2177   fprintf (file, "\t! BEGIN EPILOGUE\n");
2178 }
2179 
2180 /* The content produced from this function
2181    will be placed after epilogue body.  */
2182 static void
nds32_asm_function_epilogue(FILE * file)2183 nds32_asm_function_epilogue (FILE *file)
2184 {
2185   fprintf (file, "\t! END EPILOGUE\n");
2186 }
2187 
2188 static void
nds32_asm_output_mi_thunk(FILE * file,tree thunk ATTRIBUTE_UNUSED,HOST_WIDE_INT delta,HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,tree function)2189 nds32_asm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
2190 			   HOST_WIDE_INT delta,
2191 			   HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
2192 			   tree function)
2193 {
2194   int this_regno;
2195 
2196   /* Make sure unwind info is emitted for the thunk if needed.  */
2197   final_start_function (emit_barrier (), file, 1);
2198 
2199   this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)
2200 		? 1
2201 		: 0);
2202 
2203   if (delta != 0)
2204     {
2205       if (satisfies_constraint_Is15 (GEN_INT (delta)))
2206 	{
2207 	  fprintf (file, "\taddi\t$r%d, $r%d, " HOST_WIDE_INT_PRINT_DEC "\n",
2208 		   this_regno, this_regno, delta);
2209 	}
2210       else if (satisfies_constraint_Is20 (GEN_INT (delta)))
2211 	{
2212 	  fprintf (file, "\tmovi\t$ta, " HOST_WIDE_INT_PRINT_DEC "\n", delta);
2213 	  fprintf (file, "\tadd\t$r%d, $r%d, $ta\n", this_regno, this_regno);
2214 	}
2215       else
2216 	{
2217 	  fprintf (file,
2218 		   "\tsethi\t$ta, hi20(" HOST_WIDE_INT_PRINT_DEC ")\n",
2219 		   delta);
2220 	  fprintf (file,
2221 		   "\tori\t$ta, $ta, lo12(" HOST_WIDE_INT_PRINT_DEC ")\n",
2222 		   delta);
2223 	  fprintf (file, "\tadd\t$r%d, $r%d, $ta\n", this_regno, this_regno);
2224 	}
2225     }
2226 
2227   fprintf (file, "\tb\t");
2228   assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
2229   fprintf (file, "\n");
2230 
2231   final_end_function ();
2232 }
2233 
2234 /* -- Permitting tail calls.  */
2235 
2236 /* Return true if it is ok to do sibling call optimization.  */
2237 static bool
nds32_function_ok_for_sibcall(tree decl,tree exp ATTRIBUTE_UNUSED)2238 nds32_function_ok_for_sibcall (tree decl,
2239 			       tree exp ATTRIBUTE_UNUSED)
2240 {
2241   /* The DECL is NULL if it is an indirect call.  */
2242 
2243   /* 1. Do not apply sibling call if -mv3push is enabled,
2244 	because pop25 instruction also represents return behavior.
2245      2. If this function is a variadic function, do not apply sibling call
2246 	because the stack layout may be a mess.
2247      3. We don't want to apply sibling call optimization for indirect
2248 	sibcall because the pop behavior in epilogue may pollute the
2249 	content of caller-saved regsiter when the register is used for
2250 	indirect sibcall.  */
2251   return (!TARGET_V3PUSH
2252 	  && (cfun->machine->va_args_size == 0)
2253 	  && decl);
2254 }
2255 
2256 /* Determine whether we need to enable warning for function return check.  */
2257 static bool
nds32_warn_func_return(tree decl)2258 nds32_warn_func_return (tree decl)
2259 {
2260   /* Naked functions are implemented entirely in assembly, including the
2261      return sequence, so suppress warnings about this.  */
2262   return !nds32_naked_function_p (decl);
2263 }
2264 
2265 
2266 /* Implementing the Varargs Macros.  */
2267 
2268 static void
nds32_setup_incoming_varargs(cumulative_args_t ca,machine_mode mode,tree type,int * pretend_args_size,int second_time ATTRIBUTE_UNUSED)2269 nds32_setup_incoming_varargs (cumulative_args_t ca,
2270 			      machine_mode mode,
2271 			      tree type,
2272 			      int *pretend_args_size,
2273 			      int second_time ATTRIBUTE_UNUSED)
2274 {
2275   unsigned int total_args_regs;
2276   unsigned int num_of_used_regs;
2277   unsigned int remaining_reg_count;
2278   CUMULATIVE_ARGS *cum;
2279 
2280   /* If we are under hard float abi, we do not need to set *pretend_args_size.
2281      So that all nameless arguments are pushed by caller and all situation
2282      can be handled by GCC itself.  */
2283   if (TARGET_HARD_FLOAT)
2284     return;
2285 
2286   /* We are using NDS32_MAX_GPR_REGS_FOR_ARGS registers,
2287      counting from NDS32_GPR_ARG_FIRST_REGNUM, for saving incoming arguments.
2288      However, for nameless(anonymous) arguments, we should push them on the
2289      stack so that all the nameless arguments appear to have been passed
2290      consecutively in the memory for accessing.  Hence, we need to check and
2291      exclude the registers that are used for named arguments.  */
2292 
2293   cum = get_cumulative_args (ca);
2294 
2295   /* The MODE and TYPE describe the last argument.
2296      We need those information to determine the remaining registers
2297      for varargs.  */
2298   total_args_regs
2299     = NDS32_MAX_GPR_REGS_FOR_ARGS + NDS32_GPR_ARG_FIRST_REGNUM;
2300   num_of_used_regs
2301     = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
2302       + NDS32_NEED_N_REGS_FOR_ARG (mode, type);
2303 
2304   remaining_reg_count = total_args_regs - num_of_used_regs;
2305   *pretend_args_size = remaining_reg_count * UNITS_PER_WORD;
2306 
2307   return;
2308 }
2309 
2310 static bool
nds32_strict_argument_naming(cumulative_args_t ca ATTRIBUTE_UNUSED)2311 nds32_strict_argument_naming (cumulative_args_t ca ATTRIBUTE_UNUSED)
2312 {
2313   /* If this hook returns true, the named argument of FUNCTION_ARG is always
2314      true for named arguments, and false for unnamed arguments.  */
2315   return true;
2316 }
2317 
2318 
2319 /* Trampolines for Nested Functions.  */
2320 
2321 static void
nds32_asm_trampoline_template(FILE * f)2322 nds32_asm_trampoline_template (FILE *f)
2323 {
2324   if (TARGET_REDUCED_REGS)
2325     {
2326       /* Trampoline is not supported on reduced-set registers yet.  */
2327       sorry ("a nested function is not supported for reduced registers");
2328     }
2329   else
2330     {
2331       asm_fprintf (f, "\t! Trampoline code template\n");
2332       asm_fprintf (f, "\t! This code fragment will be copied "
2333 		      "into stack on demand\n");
2334 
2335       asm_fprintf (f, "\tmfusr\t$r16,$pc\n");
2336       asm_fprintf (f, "\tlwi\t$r15,[$r16 + 20] "
2337 		      "! load nested function address\n");
2338       asm_fprintf (f, "\tlwi\t$r16,[$r16 + 16] "
2339 		      "! load chain_value\n");
2340       asm_fprintf (f, "\tjr\t$r15\n");
2341     }
2342 
2343   /* Preserve space ($pc + 16) for saving chain_value,
2344      nds32_trampoline_init will fill the value in this slot.  */
2345   asm_fprintf (f, "\t! space for saving chain_value\n");
2346   assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
2347 
2348   /* Preserve space ($pc + 20) for saving nested function address,
2349      nds32_trampoline_init will fill the value in this slot.  */
2350   asm_fprintf (f, "\t! space for saving nested function address\n");
2351   assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
2352 }
2353 
2354 /* Emit RTL insns to initialize the variable parts of a trampoline.  */
2355 static void
nds32_trampoline_init(rtx m_tramp,tree fndecl,rtx chain_value)2356 nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
2357 {
2358   int i;
2359 
2360   /* Nested function address.  */
2361   rtx fnaddr;
2362   /* The memory rtx that is going to
2363      be filled with chain_value.  */
2364   rtx chain_value_mem;
2365   /* The memory rtx that is going to
2366      be filled with nested function address.  */
2367   rtx nested_func_mem;
2368 
2369   /* Start address of trampoline code in stack, for doing cache sync.  */
2370   rtx sync_cache_addr;
2371   /* Temporary register for sync instruction.  */
2372   rtx tmp_reg;
2373   /* Instruction-cache sync instruction,
2374      requesting an argument as starting address.  */
2375   rtx isync_insn;
2376   /* For convenience reason of doing comparison.  */
2377   int tramp_align_in_bytes;
2378 
2379   /* Trampoline is not supported on reduced-set registers yet.  */
2380   if (TARGET_REDUCED_REGS)
2381     sorry ("a nested function is not supported for reduced registers");
2382 
2383   /* STEP 1: Copy trampoline code template into stack,
2384 	     fill up essential data into stack.  */
2385 
2386   /* Extract nested function address rtx.  */
2387   fnaddr = XEXP (DECL_RTL (fndecl), 0);
2388 
2389   /* m_tramp is memory rtx that is going to be filled with trampoline code.
2390      We have nds32_asm_trampoline_template() to emit template pattern.  */
2391   emit_block_move (m_tramp, assemble_trampoline_template (),
2392 		   GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
2393 
2394   /* After copying trampoline code into stack,
2395      fill chain_value into stack.  */
2396   chain_value_mem = adjust_address (m_tramp, SImode, 16);
2397   emit_move_insn (chain_value_mem, chain_value);
2398   /* After copying trampoline code int stack,
2399      fill nested function address into stack.  */
2400   nested_func_mem = adjust_address (m_tramp, SImode, 20);
2401   emit_move_insn (nested_func_mem, fnaddr);
2402 
2403   /* STEP 2: Sync instruction-cache.  */
2404 
2405   /* We have successfully filled trampoline code into stack.
2406      However, in order to execute code in stack correctly,
2407      we must sync instruction cache.  */
2408   sync_cache_addr = XEXP (m_tramp, 0);
2409   tmp_reg         = gen_reg_rtx (SImode);
2410   isync_insn      = gen_unspec_volatile_isync (tmp_reg);
2411 
2412   /* Because nds32_cache_block_size is in bytes,
2413      we get trampoline alignment in bytes for convenient comparison.  */
2414   tramp_align_in_bytes = TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT;
2415 
2416   if (tramp_align_in_bytes >= nds32_cache_block_size
2417       && (tramp_align_in_bytes % nds32_cache_block_size) == 0)
2418     {
2419       /* Under this condition, the starting address of trampoline
2420 	 must be aligned to the starting address of each cache block
2421 	 and we do not have to worry about cross-boundary issue.  */
2422       for (i = 0;
2423 	   i < (TRAMPOLINE_SIZE + nds32_cache_block_size - 1)
2424 	       / nds32_cache_block_size;
2425 	   i++)
2426 	{
2427 	  emit_move_insn (tmp_reg,
2428 			  plus_constant (Pmode, sync_cache_addr,
2429 					 nds32_cache_block_size * i));
2430 	  emit_insn (isync_insn);
2431 	}
2432     }
2433   else if (TRAMPOLINE_SIZE > nds32_cache_block_size)
2434     {
2435       /* The starting address of trampoline code
2436 	 may not be aligned to the cache block,
2437 	 so the trampoline code may be across two cache block.
2438 	 We need to sync the last element, which is 4-byte size,
2439 	 of trampoline template.  */
2440       for (i = 0;
2441 	   i < (TRAMPOLINE_SIZE + nds32_cache_block_size - 1)
2442 	       / nds32_cache_block_size;
2443 	   i++)
2444 	{
2445 	  emit_move_insn (tmp_reg,
2446 			  plus_constant (Pmode, sync_cache_addr,
2447 					 nds32_cache_block_size * i));
2448 	  emit_insn (isync_insn);
2449 	}
2450 
2451       /* The last element of trampoline template is 4-byte size.  */
2452       emit_move_insn (tmp_reg,
2453 		      plus_constant (Pmode, sync_cache_addr,
2454 				     TRAMPOLINE_SIZE - 4));
2455       emit_insn (isync_insn);
2456     }
2457   else
2458     {
2459       /* This is the simplest case.
2460 	 Because TRAMPOLINE_SIZE is less than or
2461 	 equal to nds32_cache_block_size,
2462 	 we can just sync start address and
2463 	 the last element of trampoline code.  */
2464 
2465       /* Sync starting address of tampoline code.  */
2466       emit_move_insn (tmp_reg, sync_cache_addr);
2467       emit_insn (isync_insn);
2468       /* Sync the last element, which is 4-byte size,
2469 	 of trampoline template.  */
2470       emit_move_insn (tmp_reg,
2471 		      plus_constant (Pmode, sync_cache_addr,
2472 				     TRAMPOLINE_SIZE - 4));
2473       emit_insn (isync_insn);
2474     }
2475 
2476   /* Set instruction serialization barrier
2477      to guarantee the correct operations.  */
2478   emit_insn (gen_unspec_volatile_isb ());
2479 }
2480 
2481 
2482 /* Addressing Modes.  */
2483 
2484 static bool
nds32_legitimate_address_p(machine_mode mode,rtx x,bool strict)2485 nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict)
2486 {
2487   if (TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)
2488     {
2489      /* When using floating-point instructions,
2490 	we don't allow 'addr' to be [symbol_ref], [CONST] pattern.  */
2491       if ((mode == DFmode || mode == SFmode)
2492 	  && (GET_CODE (x) == SYMBOL_REF
2493 	  || GET_CODE(x) == CONST))
2494 	return false;
2495 
2496       /* Allow [post_modify] addressing mode, when using FPU instructions.  */
2497       if (GET_CODE (x) == POST_MODIFY
2498 	  && mode == DFmode)
2499 	{
2500 	  if (GET_CODE (XEXP (x, 0)) == REG
2501 	      && GET_CODE (XEXP (x, 1)) == PLUS)
2502 	    {
2503 	      rtx plus_op = XEXP (x, 1);
2504 	      rtx op0 = XEXP (plus_op, 0);
2505 	      rtx op1 = XEXP (plus_op, 1);
2506 
2507 	      if (nds32_address_register_rtx_p (op0, strict)
2508 		  && CONST_INT_P (op1))
2509 		{
2510 		  if (satisfies_constraint_Is14 (op1))
2511 		    {
2512 		      /* If it is not under strictly aligned situation,
2513 			 we can return true without checking alignment.  */
2514 		      if (!cfun->machine->strict_aligned_p)
2515 			return true;
2516 		      /* Make sure address is word alignment.
2517 			Currently we do not have 64-bit load/store yet,
2518 			so we will use two 32-bit load/store instructions to do
2519 			memory access and they are single word alignment.  */
2520 		      else if (NDS32_SINGLE_WORD_ALIGN_P (INTVAL (op1)))
2521 			return true;
2522 		    }
2523 		}
2524 	    }
2525 	}
2526     }
2527 
2528   /* For (mem:DI addr) or (mem:DF addr) case,
2529      we only allow 'addr' to be [reg], [symbol_ref],
2530 				[const], or [reg + const_int] pattern.  */
2531   if (mode == DImode || mode == DFmode)
2532     {
2533       /* Allow [Reg + const_int] addressing mode.  */
2534       if (GET_CODE (x) == PLUS)
2535 	{
2536 	  if (nds32_address_register_rtx_p (XEXP (x, 0), strict)
2537 	      && nds32_legitimate_index_p (mode, XEXP (x, 1), strict)
2538 	      && CONST_INT_P (XEXP (x, 1)))
2539 	    return true;
2540 	  else if (nds32_address_register_rtx_p (XEXP (x, 1), strict)
2541 		   && nds32_legitimate_index_p (mode, XEXP (x, 0), strict)
2542 		   && CONST_INT_P (XEXP (x, 0)))
2543 	    return true;
2544 	}
2545 
2546       /* Allow [post_inc] and [post_dec] addressing mode.  */
2547       if (GET_CODE (x) == POST_INC || GET_CODE (x) == POST_DEC)
2548 	{
2549 	  if (nds32_address_register_rtx_p (XEXP (x, 0), strict))
2550 	    return true;
2551 	}
2552 
2553       /* Now check [reg], [symbol_ref], and [const].  */
2554       if (GET_CODE (x) != REG
2555 	  && GET_CODE (x) != SYMBOL_REF
2556 	  && GET_CODE (x) != CONST)
2557 	return false;
2558     }
2559 
2560   /* Check if 'x' is a valid address.  */
2561   switch (GET_CODE (x))
2562     {
2563     case REG:
2564       /* (mem (reg A)) => [Ra] */
2565       return nds32_address_register_rtx_p (x, strict);
2566 
2567     case SYMBOL_REF:
2568       /* (mem (symbol_ref A)) => [symbol_ref] */
2569       /* If -mcmodel=large, the 'symbol_ref' is not a valid address
2570 	 during or after LRA/reload phase.  */
2571       if (TARGET_CMODEL_LARGE
2572 	  && (reload_completed
2573 	      || reload_in_progress
2574 	      || lra_in_progress))
2575 	return false;
2576       /* If -mcmodel=medium and the symbol references to rodata section,
2577 	 the 'symbol_ref' is not a valid address during or after
2578 	 LRA/reload phase.  */
2579       if (TARGET_CMODEL_MEDIUM
2580 	  && NDS32_SYMBOL_REF_RODATA_P (x)
2581 	  && (reload_completed
2582 	      || reload_in_progress
2583 	      || lra_in_progress))
2584 	return false;
2585 
2586       return true;
2587 
2588     case CONST:
2589       /* (mem (const (...)))
2590 	 => [ + const_addr ], where const_addr = symbol_ref + const_int */
2591       if (GET_CODE (XEXP (x, 0)) == PLUS)
2592 	{
2593 	  rtx plus_op = XEXP (x, 0);
2594 
2595 	  rtx op0 = XEXP (plus_op, 0);
2596 	  rtx op1 = XEXP (plus_op, 1);
2597 
2598 	  if (GET_CODE (op0) == SYMBOL_REF && CONST_INT_P (op1))
2599 	    {
2600 	      /* Now we see the [ + const_addr ] pattern, but we need
2601 		 some further checking.  */
2602 	      /* If -mcmodel=large, the 'const_addr' is not a valid address
2603 		 during or after LRA/reload phase.  */
2604 	      if (TARGET_CMODEL_LARGE
2605 		  && (reload_completed
2606 		      || reload_in_progress
2607 		      || lra_in_progress))
2608 		return false;
2609 	      /* If -mcmodel=medium and the symbol references to rodata section,
2610 		 the 'const_addr' is not a valid address during or after
2611 		 LRA/reload phase.  */
2612 	      if (TARGET_CMODEL_MEDIUM
2613 		  && NDS32_SYMBOL_REF_RODATA_P (op0)
2614 		  && (reload_completed
2615 		      || reload_in_progress
2616 		      || lra_in_progress))
2617 		return false;
2618 
2619 	      /* At this point we can make sure 'const_addr' is a
2620 		 valid address.  */
2621 	      return true;
2622 	    }
2623 	}
2624 
2625 	return false;
2626 
2627     case POST_MODIFY:
2628       /* (mem (post_modify (reg) (plus (reg) (reg))))
2629 	 => [Ra], Rb */
2630       /* (mem (post_modify (reg) (plus (reg) (const_int))))
2631 	 => [Ra], const_int */
2632       if (GET_CODE (XEXP (x, 0)) == REG
2633 	  && GET_CODE (XEXP (x, 1)) == PLUS)
2634 	{
2635 	  rtx plus_op = XEXP (x, 1);
2636 
2637 	  rtx op0 = XEXP (plus_op, 0);
2638 	  rtx op1 = XEXP (plus_op, 1);
2639 
2640 	  if (nds32_address_register_rtx_p (op0, strict)
2641 	      && nds32_legitimate_index_p (mode, op1, strict))
2642 	    return true;
2643 	  else
2644 	    return false;
2645 	}
2646 
2647 	return false;
2648 
2649     case POST_INC:
2650     case POST_DEC:
2651       /* (mem (post_inc reg)) => [Ra], 1/2/4 */
2652       /* (mem (post_dec reg)) => [Ra], -1/-2/-4 */
2653       /* The 1/2/4 or -1/-2/-4 have been displayed in nds32.md.
2654 	 We only need to deal with register Ra.  */
2655       if (nds32_address_register_rtx_p (XEXP (x, 0), strict))
2656 	return true;
2657       else
2658 	return false;
2659 
2660     case PLUS:
2661       /* (mem (plus reg const_int))
2662 	 => [Ra + imm] */
2663       /* (mem (plus reg reg))
2664 	 => [Ra + Rb] */
2665       /* (mem (plus (mult reg const_int) reg))
2666 	 => [Ra + Rb << sv] */
2667       if (nds32_address_register_rtx_p (XEXP (x, 0), strict)
2668 	  && nds32_legitimate_index_p (mode, XEXP (x, 1), strict))
2669 	return true;
2670       else if (nds32_address_register_rtx_p (XEXP (x, 1), strict)
2671 	       && nds32_legitimate_index_p (mode, XEXP (x, 0), strict))
2672 	return true;
2673       else
2674 	return false;
2675 
2676     case LO_SUM:
2677       /* (mem (lo_sum (reg) (symbol_ref))) */
2678       /* (mem (lo_sum (reg) (const))) */
2679       gcc_assert (REG_P (XEXP (x, 0)));
2680       if (GET_CODE (XEXP (x, 1)) == SYMBOL_REF
2681 	  || GET_CODE (XEXP (x, 1)) == CONST)
2682 	return nds32_legitimate_address_p (mode, XEXP (x, 1), strict);
2683       else
2684 	return false;
2685 
2686     default:
2687       return false;
2688     }
2689 }
2690 
2691 
2692 /* Condition Code Status.  */
2693 
2694 /* -- Representation of condition codes using registers.  */
2695 
2696 static void
nds32_canonicalize_comparison(int * code,rtx * op0 ATTRIBUTE_UNUSED,rtx * op1,bool op0_preserve_value ATTRIBUTE_UNUSED)2697 nds32_canonicalize_comparison (int *code,
2698 			       rtx *op0 ATTRIBUTE_UNUSED,
2699 			       rtx *op1,
2700 			       bool op0_preserve_value ATTRIBUTE_UNUSED)
2701 {
2702   /* When the instruction combination pass tries to combine a comparison insn
2703      with its previous insns, it also transforms the operator in order to
2704      minimize its constant field.  For example, it tries to transform a
2705      comparison insn from
2706        (set (reg:SI 54)
2707 	   (ltu:SI (reg:SI 52)
2708 	       (const_int 10 [0xa])))
2709      to
2710        (set (reg:SI 54)
2711 	   (leu:SI (reg:SI 52)
2712 	       (const_int 9 [0x9])))
2713 
2714      However, the nds32 target only provides instructions supporting the LTU
2715      operation directly, and the implementation of the pattern "cbranchsi4"
2716      only expands the LTU form.  In order to handle the non-LTU operations
2717      generated from passes other than the RTL expansion pass, we have to
2718      implement this hook to revert those changes.  Since we only expand the LTU
2719      operator in the RTL expansion pass, we might only need to handle the LEU
2720      case, unless we find other optimization passes perform more aggressive
2721      transformations.  */
2722 
2723   if (*code == LEU && CONST_INT_P (*op1))
2724     {
2725       *op1 = gen_int_mode (INTVAL (*op1) + 1, SImode);
2726       *code = LTU;
2727     }
2728 }
2729 
2730 
2731 /* Describing Relative Costs of Operations.  */
2732 
2733 static int
nds32_register_move_cost(machine_mode mode ATTRIBUTE_UNUSED,reg_class_t from,reg_class_t to)2734 nds32_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
2735 			  reg_class_t from,
2736 			  reg_class_t to)
2737 {
2738   if ((from == FP_REGS && to != FP_REGS)
2739       || (from != FP_REGS && to == FP_REGS))
2740     return 9;
2741   else if (from == HIGH_REGS || to == HIGH_REGS)
2742     return optimize_size ? 6 : 2;
2743   else
2744     return 2;
2745 }
2746 
2747 static int
nds32_memory_move_cost(machine_mode mode ATTRIBUTE_UNUSED,reg_class_t rclass ATTRIBUTE_UNUSED,bool in ATTRIBUTE_UNUSED)2748 nds32_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
2749 			reg_class_t rclass ATTRIBUTE_UNUSED,
2750 			bool in ATTRIBUTE_UNUSED)
2751 {
2752   return 8;
2753 }
2754 
2755 /* This target hook describes the relative costs of RTL expressions.
2756    Return 'true' when all subexpressions of x have been processed.
2757    Return 'false' to sum the costs of sub-rtx, plus cost of this operation.
2758    Refer to gcc/rtlanal.c for more information.  */
2759 static bool
nds32_rtx_costs(rtx x,machine_mode mode,int outer_code,int opno,int * total,bool speed)2760 nds32_rtx_costs (rtx x,
2761 		 machine_mode mode,
2762 		 int outer_code,
2763 		 int opno,
2764 		 int *total,
2765 		 bool speed)
2766 {
2767   return nds32_rtx_costs_impl (x, mode, outer_code, opno, total, speed);
2768 }
2769 
2770 static int
nds32_address_cost(rtx address,machine_mode mode,addr_space_t as,bool speed)2771 nds32_address_cost (rtx address,
2772 		    machine_mode mode,
2773 		    addr_space_t as,
2774 		    bool speed)
2775 {
2776   return nds32_address_cost_impl (address, mode, as, speed);
2777 }
2778 
2779 
2780 /* Dividing the Output into Sections (Texts, Data, . . . ).  */
2781 
2782 /* If references to a symbol or a constant must be treated differently
2783    depending on something about the variable or function named by the symbol
2784    (such as what section it is in), we use this hook to store flags
2785    in symbol_ref rtx.  */
2786 static void
nds32_encode_section_info(tree decl,rtx rtl,int new_decl_p)2787 nds32_encode_section_info (tree decl, rtx rtl, int new_decl_p)
2788 {
2789   default_encode_section_info (decl, rtl, new_decl_p);
2790 
2791   /* For the memory rtx, if it references to rodata section, we can store
2792      NDS32_SYMBOL_FLAG_RODATA flag into symbol_ref rtx so that the
2793      nds32_legitimate_address_p() can determine how to treat such symbol_ref
2794      based on -mcmodel=X and this information.  */
2795   if (MEM_P (rtl) && MEM_READONLY_P (rtl))
2796     {
2797       rtx addr = XEXP (rtl, 0);
2798 
2799       if (GET_CODE (addr) == SYMBOL_REF)
2800 	{
2801 	  /* For (mem (symbol_ref X)) case.  */
2802 	  SYMBOL_REF_FLAGS (addr) |= NDS32_SYMBOL_FLAG_RODATA;
2803 	}
2804       else if (GET_CODE (addr) == CONST
2805 	       && GET_CODE (XEXP (addr, 0)) == PLUS)
2806 	{
2807 	  /* For (mem (const (plus (symbol_ref X) (const_int N)))) case.  */
2808 	  rtx plus_op = XEXP (addr, 0);
2809 	  rtx op0 = XEXP (plus_op, 0);
2810 	  rtx op1 = XEXP (plus_op, 1);
2811 
2812 	  if (GET_CODE (op0) == SYMBOL_REF && CONST_INT_P (op1))
2813 	    SYMBOL_REF_FLAGS (op0) |= NDS32_SYMBOL_FLAG_RODATA;
2814 	}
2815     }
2816 }
2817 
2818 
2819 /* Defining the Output Assembler Language.  */
2820 
2821 /* -- The Overall Framework of an Assembler File.  */
2822 
2823 static void
nds32_asm_file_start(void)2824 nds32_asm_file_start (void)
2825 {
2826   default_file_start ();
2827 
2828   /* Tell assembler which ABI we are using.  */
2829   fprintf (asm_out_file, "\t! ABI version\n");
2830   if (TARGET_HARD_FLOAT)
2831     fprintf (asm_out_file, "\t.abi_2fp_plus\n");
2832   else
2833     fprintf (asm_out_file, "\t.abi_2\n");
2834 
2835   /* Tell assembler that this asm code is generated by compiler.  */
2836   fprintf (asm_out_file, "\t! This asm file is generated by compiler\n");
2837   fprintf (asm_out_file, "\t.flag\tverbatim\n");
2838   /* Give assembler the size of each vector for interrupt handler.  */
2839   fprintf (asm_out_file, "\t! This vector size directive is required "
2840 			 "for checking inconsistency on interrupt handler\n");
2841   fprintf (asm_out_file, "\t.vec_size\t%d\n", nds32_isr_vector_size);
2842 
2843   fprintf (asm_out_file, "\t! ------------------------------------\n");
2844 
2845   if (TARGET_ISA_V2)
2846     fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V2");
2847   if (TARGET_ISA_V3)
2848     fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V3");
2849   if (TARGET_ISA_V3M)
2850     fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V3M");
2851 
2852   if (TARGET_CMODEL_SMALL)
2853     fprintf (asm_out_file, "\t! Code model\t\t: %s\n", "SMALL");
2854   if (TARGET_CMODEL_MEDIUM)
2855     fprintf (asm_out_file, "\t! Code model\t\t: %s\n", "MEDIUM");
2856   if (TARGET_CMODEL_LARGE)
2857     fprintf (asm_out_file, "\t! Code model\t\t: %s\n", "LARGE");
2858 
2859   fprintf (asm_out_file, "\t! Endian setting\t: %s\n",
2860 			 ((TARGET_BIG_ENDIAN) ? "big-endian"
2861 					      : "little-endian"));
2862   fprintf (asm_out_file, "\t! Use SP floating-point instruction\t: %s\n",
2863 			 ((TARGET_FPU_SINGLE) ? "Yes"
2864 					      : "No"));
2865   fprintf (asm_out_file, "\t! Use DP floating-point instruction\t: %s\n",
2866 			 ((TARGET_FPU_DOUBLE) ? "Yes"
2867 					      : "No"));
2868   fprintf (asm_out_file, "\t! ABI version\t\t: %s\n",
2869 			 ((TARGET_HARD_FLOAT) ? "ABI2FP+"
2870 					      : "ABI2"));
2871 
2872   fprintf (asm_out_file, "\t! ------------------------------------\n");
2873 
2874   fprintf (asm_out_file, "\t! Use conditional move\t\t: %s\n",
2875 			 ((TARGET_CMOV) ? "Yes"
2876 					: "No"));
2877   fprintf (asm_out_file, "\t! Use performance extension\t: %s\n",
2878 			 ((TARGET_EXT_PERF) ? "Yes"
2879 					    : "No"));
2880   fprintf (asm_out_file, "\t! Use performance extension 2\t: %s\n",
2881 			 ((TARGET_EXT_PERF2) ? "Yes"
2882 					     : "No"));
2883   fprintf (asm_out_file, "\t! Use string extension\t\t: %s\n",
2884 			 ((TARGET_EXT_STRING) ? "Yes"
2885 					      : "No"));
2886 
2887   fprintf (asm_out_file, "\t! ------------------------------------\n");
2888 
2889   fprintf (asm_out_file, "\t! V3PUSH instructions\t: %s\n",
2890 			 ((TARGET_V3PUSH) ? "Yes"
2891 					  : "No"));
2892   fprintf (asm_out_file, "\t! 16-bit instructions\t: %s\n",
2893 			 ((TARGET_16_BIT) ? "Yes"
2894 					  : "No"));
2895   fprintf (asm_out_file, "\t! Reduced registers set\t: %s\n",
2896 			 ((TARGET_REDUCED_REGS) ? "Yes"
2897 						: "No"));
2898 
2899   fprintf (asm_out_file, "\t! Support unaligned access\t\t: %s\n",
2900 			 (flag_unaligned_access ? "Yes"
2901 						: "No"));
2902 
2903   fprintf (asm_out_file, "\t! ------------------------------------\n");
2904 
2905   if (optimize_size)
2906     fprintf (asm_out_file, "\t! Optimization level\t: -Os\n");
2907   else if (optimize_fast)
2908     fprintf (asm_out_file, "\t! Optimization level\t: -Ofast\n");
2909   else if (optimize_debug)
2910     fprintf (asm_out_file, "\t! Optimization level\t: -Og\n");
2911   else
2912     fprintf (asm_out_file, "\t! Optimization level\t: -O%d\n", optimize);
2913 
2914   fprintf (asm_out_file, "\t! ------------------------------------\n");
2915 
2916   fprintf (asm_out_file, "\t! Cache block size\t: %d\n",
2917 			 nds32_cache_block_size);
2918 
2919   fprintf (asm_out_file, "\t! ------------------------------------\n");
2920 
2921   nds32_asm_file_start_for_isr ();
2922 }
2923 
2924 static void
nds32_asm_file_end(void)2925 nds32_asm_file_end (void)
2926 {
2927   nds32_asm_file_end_for_isr ();
2928 
2929   fprintf (asm_out_file, "\t! ------------------------------------\n");
2930 }
2931 
2932 /* -- Output and Generation of Labels.  */
2933 
2934 static void
nds32_asm_globalize_label(FILE * stream,const char * name)2935 nds32_asm_globalize_label (FILE *stream, const char *name)
2936 {
2937   fputs ("\t.global\t", stream);
2938   assemble_name (stream, name);
2939   fputs ("\n", stream);
2940 }
2941 
2942 /* -- Output of Assembler Instructions.  */
2943 
2944 static void
nds32_print_operand(FILE * stream,rtx x,int code)2945 nds32_print_operand (FILE *stream, rtx x, int code)
2946 {
2947   HOST_WIDE_INT op_value = 0;
2948   HOST_WIDE_INT one_position;
2949   HOST_WIDE_INT zero_position;
2950   bool pick_lsb_p = false;
2951   bool pick_msb_p = false;
2952   int regno;
2953 
2954   if (CONST_INT_P (x))
2955     op_value = INTVAL (x);
2956 
2957   switch (code)
2958     {
2959     case 0 :
2960       /* Do nothing special.  */
2961       break;
2962 
2963     case 'b':
2964       /* Use exact_log2() to search the 0-bit position.  */
2965       gcc_assert (CONST_INT_P (x));
2966       zero_position = exact_log2 (~UINTVAL (x) & GET_MODE_MASK (SImode));
2967       gcc_assert (zero_position != -1);
2968       fprintf (stream, HOST_WIDE_INT_PRINT_DEC, zero_position);
2969 
2970       /* No need to handle following process, so return immediately.  */
2971       return;
2972 
2973     case 'e':
2974       gcc_assert (MEM_P (x)
2975 		  && GET_CODE (XEXP (x, 0)) == PLUS
2976 		  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT);
2977       fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (XEXP (XEXP (x, 0), 1)));
2978 
2979       /* No need to handle following process, so return immediately.  */
2980       return;
2981     case 'B':
2982       /* Use exact_log2() to search the 1-bit position.  */
2983       gcc_assert (CONST_INT_P (x));
2984       one_position = exact_log2 (UINTVAL (x) & GET_MODE_MASK (SImode));
2985       gcc_assert (one_position != -1);
2986       fprintf (stream, HOST_WIDE_INT_PRINT_DEC, one_position);
2987 
2988       /* No need to handle following process, so return immediately.  */
2989       return;
2990 
2991     case 'L':
2992       /* X is supposed to be REG rtx.  */
2993       gcc_assert (REG_P (x));
2994       /* Claim that we are going to pick LSB part of X.  */
2995       pick_lsb_p = true;
2996       break;
2997 
2998     case 'H':
2999       /* X is supposed to be REG rtx.  */
3000       gcc_assert (REG_P (x));
3001       /* Claim that we are going to pick MSB part of X.  */
3002       pick_msb_p = true;
3003       break;
3004 
3005     case 'V':
3006       /* 'x' is supposed to be CONST_INT, get the value.  */
3007       gcc_assert (CONST_INT_P (x));
3008 
3009       /* According to the Andes architecture,
3010 	 the system/user register index range is 0 ~ 1023.
3011 	 In order to avoid conflict between user-specified-integer value
3012 	 and enum-specified-register value,
3013 	 the 'enum nds32_intrinsic_registers' value
3014 	 in nds32_intrinsic.h starts from 1024.  */
3015       if (op_value < 1024 && op_value >= 0)
3016 	{
3017 	  /* If user gives integer value directly (0~1023),
3018 	     we just print out the value.  */
3019 	  fprintf (stream, HOST_WIDE_INT_PRINT_DEC, op_value);
3020 	}
3021       else if (op_value < 0
3022 	       || op_value >= ((int) ARRAY_SIZE (nds32_intrinsic_register_names)
3023 			       + 1024))
3024 	{
3025 	  /* The enum index value for array size is out of range.  */
3026 	  error ("intrinsic register index is out of range");
3027 	}
3028       else
3029 	{
3030 	  /* If user applies normal way with __NDS32_REG_XXX__ enum data,
3031 	     we can print out register name.  Remember to substract 1024.  */
3032 	  fprintf (stream, "%s",
3033 			   nds32_intrinsic_register_names[op_value - 1024]);
3034 	}
3035 
3036       /* No need to handle following process, so return immediately.  */
3037       return;
3038 
3039     case 'R': /* cctl valck  */
3040       /* Note the cctl divide to 5 group and share the same name table.  */
3041       if (op_value < 0 || op_value > 4)
3042 	error ("CCTL intrinsic function subtype out of range!");
3043       fprintf (stream, "%s", nds32_cctl_names[op_value]);
3044       return;
3045 
3046     case 'T': /* cctl idxwbinv  */
3047       /* Note the cctl divide to 5 group and share the same name table.  */
3048       if (op_value < 0 || op_value > 4)
3049 	error ("CCTL intrinsic function subtype out of range!");
3050       fprintf (stream, "%s", nds32_cctl_names[op_value + 4]);
3051       return;
3052 
3053     case 'U': /* cctl vawbinv  */
3054       /* Note the cctl divide to 5 group and share the same name table.  */
3055       if (op_value < 0 || op_value > 4)
3056 	error ("CCTL intrinsic function subtype out of range!");
3057       fprintf (stream, "%s", nds32_cctl_names[op_value + 8]);
3058       return;
3059 
3060     case 'X': /* cctl idxread  */
3061       /* Note the cctl divide to 5 group and share the same name table.  */
3062       if (op_value < 0 || op_value > 4)
3063 	error ("CCTL intrinsic function subtype out of range!");
3064       fprintf (stream, "%s", nds32_cctl_names[op_value + 12]);
3065       return;
3066 
3067     case 'W': /* cctl idxwitre  */
3068       /* Note the cctl divide to 5 group and share the same name table.  */
3069       if (op_value < 0 || op_value > 4)
3070 	error ("CCTL intrinsic function subtype out of range!");
3071       fprintf (stream, "%s", nds32_cctl_names[op_value + 16]);
3072       return;
3073 
3074     case 'Z': /* dpref  */
3075       fprintf (stream, "%s", nds32_dpref_names[op_value]);
3076       return;
3077 
3078     default :
3079       /* Unknown flag.  */
3080       output_operand_lossage ("invalid operand output code");
3081       break;
3082     }
3083 
3084   switch (GET_CODE (x))
3085     {
3086     case LABEL_REF:
3087     case SYMBOL_REF:
3088       output_addr_const (stream, x);
3089       break;
3090 
3091     case REG:
3092       /* Print a Double-precision register name.  */
3093       if ((GET_MODE (x) == DImode || GET_MODE (x) == DFmode)
3094 	  && NDS32_IS_FPR_REGNUM (REGNO (x)))
3095 	{
3096 	  regno = REGNO (x);
3097 	  if (!NDS32_FPR_REGNO_OK_FOR_DOUBLE (regno))
3098 	    {
3099 	      output_operand_lossage ("invalid operand for code '%c'", code);
3100 	      break;
3101 	    }
3102 	  fprintf (stream, "$fd%d", (regno - NDS32_FIRST_FPR_REGNUM) >> 1);
3103 	  break;
3104 	}
3105 
3106       /* Print LSB or MSB part of register pair if the
3107 	 constraint modifier 'L' or 'H' is specified.  */
3108       if ((GET_MODE (x) == DImode || GET_MODE (x) == DFmode)
3109 	  && NDS32_IS_GPR_REGNUM (REGNO (x)))
3110 	{
3111 	  if ((pick_lsb_p && WORDS_BIG_ENDIAN)
3112 	      || (pick_msb_p && !WORDS_BIG_ENDIAN))
3113 	    {
3114 	      /* If we would like to print out LSB register under big-endian,
3115 		 or print out MSB register under little-endian, we need to
3116 		 increase register number.  */
3117 	      regno = REGNO (x);
3118 	      regno++;
3119 	      fputs (reg_names[regno], stream);
3120 	      break;
3121 	    }
3122 	}
3123 
3124       /* Forbid using static chain register ($r16)
3125 	 on reduced-set registers configuration.  */
3126       if (TARGET_REDUCED_REGS
3127 	  && REGNO (x) == STATIC_CHAIN_REGNUM)
3128 	sorry ("a nested function is not supported for reduced registers");
3129 
3130       /* Normal cases, print out register name.  */
3131       fputs (reg_names[REGNO (x)], stream);
3132       break;
3133 
3134     case MEM:
3135       output_address (GET_MODE (x), XEXP (x, 0));
3136       break;
3137 
3138     case HIGH:
3139       if (GET_CODE (XEXP (x, 0)) == CONST_DOUBLE)
3140 	{
3141 	  const REAL_VALUE_TYPE *rv;
3142 	  long val;
3143 	  gcc_assert (GET_MODE (x) == SFmode);
3144 
3145 	  rv = CONST_DOUBLE_REAL_VALUE (XEXP (x, 0));
3146 	  REAL_VALUE_TO_TARGET_SINGLE (*rv, val);
3147 
3148 	  fprintf (stream, "hi20(0x%lx)", val);
3149 	}
3150       else
3151 	gcc_unreachable ();
3152       break;
3153 
3154     case CONST_DOUBLE:
3155       const REAL_VALUE_TYPE *rv;
3156       long val;
3157       gcc_assert (GET_MODE (x) == SFmode);
3158 
3159       rv = CONST_DOUBLE_REAL_VALUE (x);
3160       REAL_VALUE_TO_TARGET_SINGLE (*rv, val);
3161 
3162       fprintf (stream, "0x%lx", val);
3163       break;
3164 
3165     case CODE_LABEL:
3166     case CONST_INT:
3167     case CONST:
3168       output_addr_const (stream, x);
3169       break;
3170 
3171     default:
3172       /* Generally, output_addr_const () is able to handle most cases.
3173 	 We want to see what CODE could appear,
3174 	 so we use gcc_unreachable() to stop it.  */
3175       debug_rtx (x);
3176       gcc_unreachable ();
3177       break;
3178     }
3179 }
3180 
3181 static void
nds32_print_operand_address(FILE * stream,machine_mode,rtx x)3182 nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x)
3183 {
3184   rtx op0, op1;
3185 
3186   switch (GET_CODE (x))
3187     {
3188     case SYMBOL_REF:
3189     case CONST:
3190       /* [ + symbol_ref] */
3191       /* [ + const_addr], where const_addr = symbol_ref + const_int */
3192       fputs ("[ + ", stream);
3193       output_addr_const (stream, x);
3194       fputs ("]", stream);
3195       break;
3196 
3197     case REG:
3198       /* Forbid using static chain register ($r16)
3199 	 on reduced-set registers configuration.  */
3200       if (TARGET_REDUCED_REGS
3201 	  && REGNO (x) == STATIC_CHAIN_REGNUM)
3202 	sorry ("a nested function is not supported for reduced registers");
3203 
3204       /* [Ra] */
3205       fprintf (stream, "[%s]", reg_names[REGNO (x)]);
3206       break;
3207 
3208     case PLUS:
3209       op0 = XEXP (x, 0);
3210       op1 = XEXP (x, 1);
3211 
3212       /* Checking op0, forbid using static chain register ($r16)
3213 	 on reduced-set registers configuration.  */
3214       if (TARGET_REDUCED_REGS
3215 	  && REG_P (op0)
3216 	  && REGNO (op0) == STATIC_CHAIN_REGNUM)
3217 	sorry ("a nested function is not supported for reduced registers");
3218       /* Checking op1, forbid using static chain register ($r16)
3219 	 on reduced-set registers configuration.  */
3220       if (TARGET_REDUCED_REGS
3221 	  && REG_P (op1)
3222 	  && REGNO (op1) == STATIC_CHAIN_REGNUM)
3223 	sorry ("a nested function is not supported for reduced registers");
3224 
3225       if (REG_P (op0) && CONST_INT_P (op1))
3226 	{
3227 	  /* [Ra + imm] */
3228 	  fprintf (stream, "[%s + (" HOST_WIDE_INT_PRINT_DEC ")]",
3229 			   reg_names[REGNO (op0)], INTVAL (op1));
3230 	}
3231       else if (REG_P (op0) && REG_P (op1))
3232 	{
3233 	  /* [Ra + Rb] */
3234 	  fprintf (stream, "[%s + %s]",
3235 			   reg_names[REGNO (op0)], reg_names[REGNO (op1)]);
3236 	}
3237       else if (GET_CODE (op0) == MULT && REG_P (op1))
3238 	{
3239 	  /* [Ra + Rb << sv]
3240 	     From observation, the pattern looks like:
3241 	     (plus:SI (mult:SI (reg:SI 58)
3242 			       (const_int 4 [0x4]))
3243 		      (reg/f:SI 57)) */
3244 	  int sv;
3245 
3246 	  /* We need to set sv to output shift value.  */
3247 	  if (INTVAL (XEXP (op0, 1)) == 1)
3248 	    sv = 0;
3249 	  else if (INTVAL (XEXP (op0, 1)) == 2)
3250 	    sv = 1;
3251 	  else if (INTVAL (XEXP (op0, 1)) == 4)
3252 	    sv = 2;
3253 	  else if (INTVAL (XEXP (op0, 1)) == 8)
3254 	    sv = 3;
3255 	  else
3256 	    gcc_unreachable ();
3257 
3258 	  fprintf (stream, "[%s + %s << %d]",
3259 			   reg_names[REGNO (op1)],
3260 			   reg_names[REGNO (XEXP (op0, 0))],
3261 			   sv);
3262 	}
3263       else
3264 	{
3265 	  /* The control flow is not supposed to be here.  */
3266 	  debug_rtx (x);
3267 	  gcc_unreachable ();
3268 	}
3269 
3270       break;
3271 
3272     case POST_MODIFY:
3273       /* (post_modify (regA) (plus (regA) (regB)))
3274 	 (post_modify (regA) (plus (regA) (const_int)))
3275 	 We would like to extract
3276 	 regA and regB (or const_int) from plus rtx.  */
3277       op0 = XEXP (XEXP (x, 1), 0);
3278       op1 = XEXP (XEXP (x, 1), 1);
3279 
3280       /* Checking op0, forbid using static chain register ($r16)
3281 	 on reduced-set registers configuration.  */
3282       if (TARGET_REDUCED_REGS
3283 	  && REG_P (op0)
3284 	  && REGNO (op0) == STATIC_CHAIN_REGNUM)
3285 	sorry ("a nested function is not supported for reduced registers");
3286       /* Checking op1, forbid using static chain register ($r16)
3287 	 on reduced-set registers configuration.  */
3288       if (TARGET_REDUCED_REGS
3289 	  && REG_P (op1)
3290 	  && REGNO (op1) == STATIC_CHAIN_REGNUM)
3291 	sorry ("a nested function is not supported for reduced registers");
3292 
3293       if (REG_P (op0) && REG_P (op1))
3294 	{
3295 	  /* [Ra], Rb */
3296 	  fprintf (stream, "[%s], %s",
3297 			   reg_names[REGNO (op0)], reg_names[REGNO (op1)]);
3298 	}
3299       else if (REG_P (op0) && CONST_INT_P (op1))
3300 	{
3301 	  /* [Ra], imm */
3302 	  fprintf (stream, "[%s], " HOST_WIDE_INT_PRINT_DEC,
3303 			   reg_names[REGNO (op0)], INTVAL (op1));
3304 	}
3305       else
3306 	{
3307 	  /* The control flow is not supposed to be here.  */
3308 	  debug_rtx (x);
3309 	  gcc_unreachable ();
3310 	}
3311 
3312       break;
3313 
3314     case POST_INC:
3315     case POST_DEC:
3316       op0 = XEXP (x, 0);
3317 
3318       /* Checking op0, forbid using static chain register ($r16)
3319 	 on reduced-set registers configuration.  */
3320       if (TARGET_REDUCED_REGS
3321 	  && REG_P (op0)
3322 	  && REGNO (op0) == STATIC_CHAIN_REGNUM)
3323 	sorry ("a nested function is not supported for reduced registers");
3324 
3325       if (REG_P (op0))
3326 	{
3327 	  /* "[Ra], 1/2/4" or "[Ra], -1/-2/-4"
3328 	     The 1/2/4 or -1/-2/-4 have been displayed in nds32.md.
3329 	     We only need to deal with register Ra.  */
3330 	  fprintf (stream, "[%s]", reg_names[REGNO (op0)]);
3331 	}
3332       else
3333 	{
3334 	  /* The control flow is not supposed to be here.  */
3335 	  debug_rtx (x);
3336 	  gcc_unreachable ();
3337 	}
3338 
3339       break;
3340 
3341     default :
3342       /* Generally, output_addr_const () is able to handle most cases.
3343 	 We want to see what CODE could appear,
3344 	 so we use gcc_unreachable() to stop it.  */
3345       debug_rtx (x);
3346       gcc_unreachable ();
3347       break;
3348     }
3349 }
3350 
3351 /* -- Assembler Commands for Exception Regions.  */
3352 
3353 static rtx
nds32_dwarf_register_span(rtx reg)3354 nds32_dwarf_register_span (rtx reg)
3355 {
3356   rtx dwarf_high, dwarf_low;
3357   rtx dwarf_single;
3358   machine_mode mode;
3359   int regno;
3360 
3361   mode = GET_MODE (reg);
3362   regno = REGNO (reg);
3363 
3364   /* We need to adjust dwarf register information for floating-point registers
3365      rather than using default register number mapping.  */
3366   if (regno >= NDS32_FIRST_FPR_REGNUM
3367       && regno <= NDS32_LAST_FPR_REGNUM)
3368     {
3369       if (mode == DFmode || mode == SCmode)
3370 	{
3371 	  /* By default, GCC maps increasing register numbers to increasing
3372 	     memory locations, but paired FPRs in NDS32 target are always
3373 	     big-endian, i.e.:
3374 
3375 	       fd0 :  fs0   fs1
3376 		     (MSB) (LSB)
3377 
3378 	     We must return parallel rtx to represent such layout.  */
3379 	  dwarf_high = gen_rtx_REG (word_mode, regno);
3380 	  dwarf_low = gen_rtx_REG (word_mode, regno + 1);
3381 	  return gen_rtx_PARALLEL (VOIDmode,
3382 				   gen_rtvec (2, dwarf_low, dwarf_high));
3383 	}
3384       else if (mode == DCmode)
3385 	{
3386 	  rtx dwarf_high_re = gen_rtx_REG (word_mode, regno);
3387 	  rtx dwarf_low_re = gen_rtx_REG (word_mode, regno + 1);
3388 	  rtx dwarf_high_im = gen_rtx_REG (word_mode, regno);
3389 	  rtx dwarf_low_im = gen_rtx_REG (word_mode, regno + 1);
3390 	  return gen_rtx_PARALLEL (VOIDmode,
3391 				   gen_rtvec (4, dwarf_low_re, dwarf_high_re,
3392 						 dwarf_high_im, dwarf_low_im));
3393 	}
3394       else if (mode == SFmode || mode == SImode)
3395 	{
3396 	  /* Create new dwarf information with adjusted register number.  */
3397 	  dwarf_single = gen_rtx_REG (word_mode, regno);
3398 	  return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, dwarf_single));
3399 	}
3400       else
3401 	{
3402 	  /* We should not be here.  */
3403 	  gcc_unreachable ();
3404 	}
3405     }
3406 
3407   return NULL_RTX;
3408 }
3409 
3410 /* Map internal gcc register numbers to DWARF2 register numbers.  */
3411 
3412 unsigned int
nds32_dbx_register_number(unsigned int regno)3413 nds32_dbx_register_number (unsigned int regno)
3414 {
3415   /* The nds32 port in GDB maintains a mapping between dwarf register
3416      number and displayed register name.  For backward compatibility to
3417      previous toolchain, currently our gdb still has four registers
3418      (d0.l, d0.h, d1.l, and d1.h) between GPR and FPR while compiler
3419      does not count those four registers in its register number table.
3420      So we have to add 4 on its register number and then create new
3421      dwarf information.  Hopefully we can discard such workaround
3422      in the future.  */
3423   if (NDS32_IS_FPR_REGNUM (regno))
3424     return regno + 4;
3425 
3426   return regno;
3427 }
3428 
3429 
3430 /* Defining target-specific uses of __attribute__.  */
3431 
3432 /* Add some checking after merging attributes.  */
3433 static tree
nds32_merge_decl_attributes(tree olddecl,tree newdecl)3434 nds32_merge_decl_attributes (tree olddecl, tree newdecl)
3435 {
3436   tree combined_attrs;
3437 
3438   /* Create combined attributes.  */
3439   combined_attrs = merge_attributes (DECL_ATTRIBUTES (olddecl),
3440 				     DECL_ATTRIBUTES (newdecl));
3441 
3442   /* Since newdecl is acutally a duplicate of olddecl,
3443      we can take olddecl for some operations.  */
3444   if (TREE_CODE (olddecl) == FUNCTION_DECL)
3445     {
3446       /* Check isr-specific attributes conflict.  */
3447       nds32_check_isr_attrs_conflict (olddecl, combined_attrs);
3448     }
3449 
3450   return combined_attrs;
3451 }
3452 
3453 /* Add some checking when inserting attributes.  */
3454 static void
nds32_insert_attributes(tree decl,tree * attributes)3455 nds32_insert_attributes (tree decl, tree *attributes)
3456 {
3457   /* For function declaration, we need to check isr-specific attributes:
3458        1. Call nds32_check_isr_attrs_conflict() to check any conflict.
3459        2. Check valid integer value for interrupt/exception.
3460        3. Check valid integer value for reset.
3461        4. Check valid function for nmi/warm.  */
3462   if (TREE_CODE (decl) == FUNCTION_DECL)
3463     {
3464       tree func_attrs;
3465       tree intr, excp, reset;
3466 
3467       /* Pick up function attributes.  */
3468       func_attrs = *attributes;
3469 
3470       /* 1. Call nds32_check_isr_attrs_conflict() to check any conflict.  */
3471       nds32_check_isr_attrs_conflict (decl, func_attrs);
3472 
3473       /* Now we are starting to check valid id value
3474 	 for interrupt/exception/reset.
3475 	 Note that we ONLY check its validity here.
3476 	 To construct isr vector information, it is still performed
3477 	 by nds32_construct_isr_vectors_information().  */
3478       intr  = lookup_attribute ("interrupt", func_attrs);
3479       excp  = lookup_attribute ("exception", func_attrs);
3480       reset = lookup_attribute ("reset", func_attrs);
3481 
3482       if (intr || excp)
3483 	{
3484 	  /* Deal with interrupt/exception.  */
3485 	  tree id_list;
3486 	  unsigned int lower_bound, upper_bound;
3487 
3488 	  /* The way to handle interrupt or exception is the same,
3489 	     we just need to take care of actual vector number.
3490 	     For interrupt(0..63), the actual vector number is (9..72).
3491 	     For exception(1..8), the actual vector number is (1..8).  */
3492 	  lower_bound = (intr) ? (0) : (1);
3493 	  upper_bound = (intr) ? (63) : (8);
3494 
3495 	  /* Prepare id list so that we can traverse id value.  */
3496 	  id_list = (intr) ? (TREE_VALUE (intr)) : (TREE_VALUE (excp));
3497 
3498 	  /* 2. Check valid integer value for interrupt/exception.  */
3499 	  while (id_list)
3500 	    {
3501 	      tree id;
3502 
3503 	      /* Pick up each vector id value.  */
3504 	      id = TREE_VALUE (id_list);
3505 	      /* Issue error if it is not a valid integer value.  */
3506 	      if (TREE_CODE (id) != INTEGER_CST
3507 		  || wi::ltu_p (wi::to_wide (id), lower_bound)
3508 		  || wi::gtu_p (wi::to_wide (id), upper_bound))
3509 		error ("invalid id value for interrupt/exception attribute");
3510 
3511 	      /* Advance to next id.  */
3512 	      id_list = TREE_CHAIN (id_list);
3513 	    }
3514 	}
3515       else if (reset)
3516 	{
3517 	  /* Deal with reset.  */
3518 	  tree id_list;
3519 	  tree id;
3520 	  tree nmi, warm;
3521 	  unsigned int lower_bound;
3522 	  unsigned int upper_bound;
3523 
3524 	  /* Prepare id_list and identify id value so that
3525 	     we can check if total number of vectors is valid.  */
3526 	  id_list = TREE_VALUE (reset);
3527 	  id = TREE_VALUE (id_list);
3528 
3529 	  /* The maximum numbers for user's interrupt is 64.  */
3530 	  lower_bound = 0;
3531 	  upper_bound = 64;
3532 
3533 	  /* 3. Check valid integer value for reset.  */
3534 	  if (TREE_CODE (id) != INTEGER_CST
3535 	      || wi::ltu_p (wi::to_wide (id), lower_bound)
3536 	      || wi::gtu_p (wi::to_wide (id), upper_bound))
3537 	    error ("invalid id value for reset attribute");
3538 
3539 	  /* 4. Check valid function for nmi/warm.  */
3540 	  nmi  = lookup_attribute ("nmi", func_attrs);
3541 	  warm = lookup_attribute ("warm", func_attrs);
3542 
3543 	  if (nmi != NULL_TREE)
3544 	    {
3545 	      tree nmi_func_list;
3546 	      tree nmi_func;
3547 
3548 	      nmi_func_list = TREE_VALUE (nmi);
3549 	      nmi_func = TREE_VALUE (nmi_func_list);
3550 
3551 	      /* Issue error if it is not a valid nmi function.  */
3552 	      if (TREE_CODE (nmi_func) != IDENTIFIER_NODE)
3553 		error ("invalid nmi function for reset attribute");
3554 	    }
3555 
3556 	  if (warm != NULL_TREE)
3557 	    {
3558 	      tree warm_func_list;
3559 	      tree warm_func;
3560 
3561 	      warm_func_list = TREE_VALUE (warm);
3562 	      warm_func = TREE_VALUE (warm_func_list);
3563 
3564 	      /* Issue error if it is not a valid warm function.  */
3565 	      if (TREE_CODE (warm_func) != IDENTIFIER_NODE)
3566 		error ("invalid warm function for reset attribute");
3567 	    }
3568 	}
3569       else
3570 	{
3571 	  /* No interrupt, exception, or reset attribute is set.  */
3572 	  return;
3573 	}
3574     }
3575 }
3576 
3577 static bool
nds32_option_pragma_parse(tree args ATTRIBUTE_UNUSED,tree pop_target ATTRIBUTE_UNUSED)3578 nds32_option_pragma_parse (tree args ATTRIBUTE_UNUSED,
3579 			   tree pop_target ATTRIBUTE_UNUSED)
3580 {
3581   /* Currently, we do not parse any pragma target by ourself,
3582      so just simply return false.  */
3583   return false;
3584 }
3585 
3586 static void
nds32_option_override(void)3587 nds32_option_override (void)
3588 {
3589   /* After all the command options have been parsed,
3590      we shall deal with some flags for changing compiler settings.  */
3591 
3592   /* At first, we check if we have to strictly
3593      set some flags based on ISA family.  */
3594   if (TARGET_ISA_V2)
3595     {
3596       /* Under V2 ISA, we need to strictly disable TARGET_V3PUSH.  */
3597       target_flags &= ~MASK_V3PUSH;
3598     }
3599   if (TARGET_ISA_V3)
3600     {
3601       /* Under V3 ISA, currently nothing should be strictly set.  */
3602     }
3603   if (TARGET_ISA_V3M)
3604     {
3605       /* Under V3M ISA, we need to strictly enable TARGET_REDUCED_REGS.  */
3606       target_flags |= MASK_REDUCED_REGS;
3607       /* Under V3M ISA, we need to strictly disable TARGET_EXT_PERF.  */
3608       target_flags &= ~MASK_EXT_PERF;
3609       /* Under V3M ISA, we need to strictly disable TARGET_EXT_PERF2.  */
3610       target_flags &= ~MASK_EXT_PERF2;
3611       /* Under V3M ISA, we need to strictly disable TARGET_EXT_STRING.  */
3612       target_flags &= ~MASK_EXT_STRING;
3613     }
3614 
3615   /* See if we are using reduced-set registers:
3616        $r0~$r5, $r6~$r10, $r15, $r28, $r29, $r30, $r31
3617      If so, we must forbid using $r11~$r14, $r16~$r27.  */
3618   if (TARGET_REDUCED_REGS)
3619     {
3620       int r;
3621 
3622       /* Prevent register allocator from
3623 	 choosing it as doing register allocation.  */
3624       for (r = 11; r <= 14; r++)
3625 	fixed_regs[r] = call_used_regs[r] = 1;
3626       for (r = 16; r <= 27; r++)
3627 	fixed_regs[r] = call_used_regs[r] = 1;
3628     }
3629 
3630   if (!TARGET_16_BIT)
3631     {
3632       /* Under no 16 bit ISA, we need to strictly disable TARGET_V3PUSH.  */
3633       target_flags &= ~MASK_V3PUSH;
3634     }
3635 
3636   if (TARGET_HARD_FLOAT && !(TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE))
3637     {
3638       if (nds32_arch_option == ARCH_V3S || nds32_arch_option == ARCH_V3F)
3639 	error ("Disable FPU ISA, "
3640 	       "the ABI option must be enable '-mfloat-abi=soft'");
3641       else
3642 	error ("'-mabi=2fp+' option only support when FPU available, "
3643 	       "must be enable '-mext-fpu-sp' or '-mext-fpu-dp'");
3644     }
3645 
3646   /* Currently, we don't support PIC code generation yet.  */
3647   if (flag_pic)
3648     sorry ("position-independent code not supported");
3649 
3650   nds32_register_passes ();
3651 }
3652 
3653 
3654 /* Miscellaneous Parameters.  */
3655 
3656 static rtx_insn *
nds32_md_asm_adjust(vec<rtx> & outputs ATTRIBUTE_UNUSED,vec<rtx> & inputs ATTRIBUTE_UNUSED,vec<const char * > & constraints ATTRIBUTE_UNUSED,vec<rtx> & clobbers,HARD_REG_SET & clobbered_regs)3657 nds32_md_asm_adjust (vec<rtx> &outputs ATTRIBUTE_UNUSED,
3658 		     vec<rtx> &inputs ATTRIBUTE_UNUSED,
3659 		     vec<const char *> &constraints ATTRIBUTE_UNUSED,
3660 		     vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs)
3661 {
3662   clobbers.safe_push (gen_rtx_REG (SImode, TA_REGNUM));
3663   SET_HARD_REG_BIT (clobbered_regs, TA_REGNUM);
3664   return NULL;
3665 }
3666 
3667 static void
nds32_init_builtins(void)3668 nds32_init_builtins (void)
3669 {
3670   nds32_init_builtins_impl ();
3671 }
3672 
3673 static tree
nds32_builtin_decl(unsigned code,bool initialize_p)3674 nds32_builtin_decl (unsigned code, bool initialize_p)
3675 {
3676   /* Implement in nds32-intrinsic.c.  */
3677   return nds32_builtin_decl_impl (code, initialize_p);
3678 }
3679 
3680 static rtx
nds32_expand_builtin(tree exp,rtx target,rtx subtarget,machine_mode mode,int ignore)3681 nds32_expand_builtin (tree exp,
3682 		      rtx target,
3683 		      rtx subtarget,
3684 		      machine_mode mode,
3685 		      int ignore)
3686 {
3687   return nds32_expand_builtin_impl (exp, target, subtarget, mode, ignore);
3688 }
3689 
3690 
3691 /* ------------------------------------------------------------------------ */
3692 
3693 /* PART 4: Implemet extern function definitions,
3694            the prototype is in nds32-protos.h.  */
3695 
3696 /* Run-time Target Specification.  */
3697 
3698 void
nds32_cpu_cpp_builtins(struct cpp_reader * pfile)3699 nds32_cpu_cpp_builtins(struct cpp_reader *pfile)
3700 {
3701 #define builtin_define(TXT) cpp_define (pfile, TXT)
3702 #define builtin_assert(TXT) cpp_assert (pfile, TXT)
3703   builtin_define ("__nds32__");
3704   builtin_define ("__NDS32__");
3705 
3706   if (TARGET_HARD_FLOAT)
3707     builtin_define ("__NDS32_ABI_2FP_PLUS__");
3708   else
3709     builtin_define ("__NDS32_ABI_2__");
3710 
3711   if (TARGET_ISA_V2)
3712     builtin_define ("__NDS32_ISA_V2__");
3713   if (TARGET_ISA_V3)
3714     builtin_define ("__NDS32_ISA_V3__");
3715   if (TARGET_ISA_V3M)
3716     builtin_define ("__NDS32_ISA_V3M__");
3717 
3718   if (TARGET_FPU_SINGLE)
3719     builtin_define ("__NDS32_EXT_FPU_SP__");
3720   if (TARGET_FPU_DOUBLE)
3721     builtin_define ("__NDS32_EXT_FPU_DP__");
3722 
3723   if (TARGET_EXT_FPU_FMA)
3724     builtin_define ("__NDS32_EXT_FPU_FMA__");
3725   if (NDS32_EXT_FPU_DOT_E)
3726     builtin_define ("__NDS32_EXT_FPU_DOT_E__");
3727   if (TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)
3728     {
3729       switch (nds32_fp_regnum)
3730 	{
3731 	case 0:
3732 	case 4:
3733 	  builtin_define ("__NDS32_EXT_FPU_CONFIG_0__");
3734 	  break;
3735 	case 1:
3736 	case 5:
3737 	  builtin_define ("__NDS32_EXT_FPU_CONFIG_1__");
3738 	  break;
3739 	case 2:
3740 	case 6:
3741 	  builtin_define ("__NDS32_EXT_FPU_CONFIG_2__");
3742 	  break;
3743 	case 3:
3744 	case 7:
3745 	  builtin_define ("__NDS32_EXT_FPU_CONFIG_3__");
3746 	  break;
3747 	default:
3748 	  abort ();
3749 	}
3750     }
3751 
3752   if (TARGET_BIG_ENDIAN)
3753     builtin_define ("__NDS32_EB__");
3754   else
3755     builtin_define ("__NDS32_EL__");
3756 
3757   if (TARGET_REDUCED_REGS)
3758     builtin_define ("__NDS32_REDUCED_REGS__");
3759   if (TARGET_CMOV)
3760     builtin_define ("__NDS32_CMOV__");
3761   if (TARGET_EXT_PERF)
3762     builtin_define ("__NDS32_EXT_PERF__");
3763   if (TARGET_EXT_PERF2)
3764     builtin_define ("__NDS32_EXT_PERF2__");
3765   if (TARGET_EXT_STRING)
3766     builtin_define ("__NDS32_EXT_STRING__");
3767   if (TARGET_16_BIT)
3768     builtin_define ("__NDS32_16_BIT__");
3769   if (TARGET_GP_DIRECT)
3770     builtin_define ("__NDS32_GP_DIRECT__");
3771   if (TARGET_VH)
3772     builtin_define ("__NDS32_VH__");
3773 
3774   if (TARGET_BIG_ENDIAN)
3775     builtin_define ("__big_endian__");
3776 
3777   builtin_assert ("cpu=nds32");
3778   builtin_assert ("machine=nds32");
3779 
3780   if (TARGET_HARD_FLOAT)
3781     builtin_define ("__NDS32_ABI_2FP_PLUS");
3782   else
3783     builtin_define ("__NDS32_ABI_2");
3784 
3785 #undef builtin_define
3786 #undef builtin_assert
3787 }
3788 
3789 
3790 /* Defining Data Structures for Per-function Information.  */
3791 
3792 void
nds32_init_expanders(void)3793 nds32_init_expanders (void)
3794 {
3795   /* Arrange to initialize and mark the machine per-function status.  */
3796   init_machine_status = nds32_init_machine_status;
3797 }
3798 
3799 
3800 /* Register Usage.  */
3801 
3802 /* -- Order of Allocation of Registers.  */
3803 
3804 void
nds32_adjust_reg_alloc_order(void)3805 nds32_adjust_reg_alloc_order (void)
3806 {
3807   const int nds32_reg_alloc_order[] = REG_ALLOC_ORDER;
3808 
3809   /* Copy the default register allocation order, which is designed
3810      to optimize for code size.  */
3811   memcpy(reg_alloc_order, nds32_reg_alloc_order, sizeof (reg_alloc_order));
3812 
3813   /* Adjust few register allocation order when optimizing for speed.  */
3814   if (!optimize_size)
3815     {
3816       memcpy (reg_alloc_order, nds32_reg_alloc_order_for_speed,
3817 	      sizeof (nds32_reg_alloc_order_for_speed));
3818     }
3819 }
3820 
3821 /* -- How Values Fit in Registers.  */
3822 
3823 static unsigned
nds32_hard_regno_nregs(unsigned regno ATTRIBUTE_UNUSED,machine_mode mode)3824 nds32_hard_regno_nregs (unsigned regno ATTRIBUTE_UNUSED,
3825 			machine_mode mode)
3826 {
3827   return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
3828 }
3829 
3830 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
3831 
3832 static bool
nds32_hard_regno_mode_ok(unsigned int regno,machine_mode mode)3833 nds32_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
3834 {
3835   if (regno > FIRST_PSEUDO_REGISTER)
3836     return true;
3837 
3838   if ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE) && NDS32_IS_FPR_REGNUM (regno))
3839     {
3840       if (NDS32_IS_EXT_FPR_REGNUM(regno))
3841 	return (NDS32_FPR_REGNO_OK_FOR_DOUBLE(regno) && (mode == DFmode));
3842       else if (mode == SFmode || mode == SImode)
3843 	return NDS32_FPR_REGNO_OK_FOR_SINGLE (regno);
3844       else if (mode == DFmode)
3845 	return NDS32_FPR_REGNO_OK_FOR_DOUBLE (regno);
3846 
3847       return false;
3848     }
3849 
3850   /* Restrict double-word quantities to even register pairs.  */
3851   if (regno <= NDS32_LAST_GPR_REGNUM)
3852     return (targetm.hard_regno_nregs (regno, mode) == 1
3853 	    || !((regno) & 1));
3854 
3855   return false;
3856 }
3857 
3858 /* Implement TARGET_MODES_TIEABLE_P.  We can use general registers to
3859    tie QI/HI/SI modes together.  */
3860 
3861 static bool
nds32_modes_tieable_p(machine_mode mode1,machine_mode mode2)3862 nds32_modes_tieable_p (machine_mode mode1, machine_mode mode2)
3863 {
3864   if ((GET_MODE_CLASS (mode1) == MODE_INT
3865        && GET_MODE_CLASS (mode2) == MODE_INT)
3866       && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
3867       && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD)
3868     return true;
3869 
3870   if (GET_MODE_SIZE (mode1) == GET_MODE_SIZE (mode2))
3871     {
3872       if ((TARGET_FPU_SINGLE && !TARGET_FPU_DOUBLE)
3873 	  && (mode1 == DFmode || mode2 == DFmode))
3874 	return false;
3875       else
3876 	return true;
3877     }
3878 
3879   return false;
3880 }
3881 
3882 /* Register Classes.  */
3883 
3884 enum reg_class
nds32_regno_reg_class(int regno)3885 nds32_regno_reg_class (int regno)
3886 {
3887   /* Refer to nds32.h for more register class details.  */
3888 
3889   if (regno >= 0 && regno <= 7)
3890     return LOW_REGS;
3891   else if (regno >= 8 && regno <= 11)
3892     return MIDDLE_REGS;
3893   else if (regno >= 12 && regno <= 14)
3894     return HIGH_REGS;
3895   else if (regno == 15)
3896     return R15_TA_REG;
3897   else if (regno >= 16 && regno <= 19)
3898     return MIDDLE_REGS;
3899   else if (regno >= 20 && regno <= 31)
3900     return HIGH_REGS;
3901   else if (regno == 32 || regno == 33)
3902     {
3903       /* $SFP and $AP is FRAME_REGS in fact, However prevent IRA don't
3904 	 know how to allocate register for $SFP and $AP, just tell IRA they
3905 	 are GENERAL_REGS, and ARM do this hack too.  */
3906       return GENERAL_REGS;
3907     }
3908   else if (regno >= 34 && regno <= 97)
3909     return FP_REGS;
3910   else
3911     return NO_REGS;
3912 }
3913 
3914 
3915 /* Stack Layout and Calling Conventions.  */
3916 
3917 /* -- Basic Stack Layout.  */
3918 
3919 rtx
nds32_dynamic_chain_address(rtx frameaddr)3920 nds32_dynamic_chain_address (rtx frameaddr)
3921 {
3922   if (TARGET_V3PUSH)
3923     {
3924       /* If -mv3push is specified, we push $fp, $gp, and $lp into stack.
3925          We can access dynamic chain address from stack by [$fp - 12].  */
3926       return plus_constant (Pmode, frameaddr, -12);
3927     }
3928   else
3929     {
3930       /* For general case we push $fp and $lp into stack at prologue.
3931          We can access dynamic chain address from stack by [$fp - 8].  */
3932       return plus_constant (Pmode, frameaddr, -8);
3933     }
3934 }
3935 
3936 rtx
nds32_return_addr_rtx(int count,rtx frameaddr)3937 nds32_return_addr_rtx (int count,
3938 		       rtx frameaddr)
3939 {
3940   int offset;
3941   rtx addr;
3942 
3943   if (count != 0)
3944     {
3945       /* In nds32 ABI design, we can expect that $lp is always available
3946          from stack by [$fp - 4] location.  */
3947       offset = -4;
3948       addr = plus_constant (Pmode, frameaddr, offset);
3949       addr = memory_address (Pmode, addr);
3950 
3951       return gen_rtx_MEM (Pmode, addr);
3952     }
3953 
3954   /* If count == 0, it means we are at current frame,
3955      the return address is $r30 ($lp).  */
3956   return get_hard_reg_initial_val (Pmode, LP_REGNUM);
3957 }
3958 
3959 /* -- Eliminating Frame Pointer and Arg Pointer.  */
3960 
3961 HOST_WIDE_INT
nds32_initial_elimination_offset(unsigned int from_reg,unsigned int to_reg)3962 nds32_initial_elimination_offset (unsigned int from_reg, unsigned int to_reg)
3963 {
3964   HOST_WIDE_INT offset;
3965 
3966   /* Compute and setup stack frame size.
3967      The result will be in cfun->machine.  */
3968   nds32_compute_stack_frame ();
3969 
3970   /* Remember to consider
3971      cfun->machine->callee_saved_area_gpr_padding_bytes and
3972      cfun->machine->eh_return_data_regs_size
3973      when calculating offset.  */
3974   if (from_reg == ARG_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM)
3975     {
3976       offset = (cfun->machine->fp_size
3977 		+ cfun->machine->gp_size
3978 		+ cfun->machine->lp_size
3979 		+ cfun->machine->callee_saved_gpr_regs_size
3980 		+ cfun->machine->callee_saved_area_gpr_padding_bytes
3981 		+ cfun->machine->callee_saved_fpr_regs_size
3982 		+ cfun->machine->eh_return_data_regs_size
3983 		+ cfun->machine->local_size
3984 		+ cfun->machine->out_args_size);
3985     }
3986   else if (from_reg == ARG_POINTER_REGNUM
3987 	   && to_reg == HARD_FRAME_POINTER_REGNUM)
3988     {
3989       offset = 0;
3990     }
3991   else if (from_reg == FRAME_POINTER_REGNUM
3992 	   && to_reg == STACK_POINTER_REGNUM)
3993     {
3994       offset = (cfun->machine->local_size + cfun->machine->out_args_size);
3995     }
3996   else if (from_reg == FRAME_POINTER_REGNUM
3997 	   && to_reg == HARD_FRAME_POINTER_REGNUM)
3998     {
3999       offset = (-1) * (cfun->machine->fp_size
4000 		       + cfun->machine->gp_size
4001 		       + cfun->machine->lp_size
4002 		       + cfun->machine->callee_saved_gpr_regs_size
4003 		       + cfun->machine->callee_saved_area_gpr_padding_bytes
4004 		       + cfun->machine->callee_saved_fpr_regs_size
4005 		       + cfun->machine->eh_return_data_regs_size);
4006     }
4007   else
4008     {
4009       gcc_unreachable ();
4010     }
4011 
4012   return offset;
4013 }
4014 
4015 /* -- Passing Arguments in Registers.  */
4016 
4017 void
nds32_init_cumulative_args(CUMULATIVE_ARGS * cum,tree fntype ATTRIBUTE_UNUSED,rtx libname ATTRIBUTE_UNUSED,tree fndecl ATTRIBUTE_UNUSED,int n_named_args ATTRIBUTE_UNUSED)4018 nds32_init_cumulative_args (CUMULATIVE_ARGS *cum,
4019 			    tree fntype ATTRIBUTE_UNUSED,
4020 			    rtx libname ATTRIBUTE_UNUSED,
4021 			    tree fndecl ATTRIBUTE_UNUSED,
4022 			    int n_named_args ATTRIBUTE_UNUSED)
4023 {
4024   /* Initial available registers.  The values are offset against
4025      NDS32_GPR_ARG_FIRST_REGNUM and NDS32_FPR_ARG_FIRST_REGNUM
4026      for passing arguments.  */
4027   cum->gpr_offset = 0;
4028   cum->fpr_offset = 0;
4029 }
4030 
4031 /* -- Function Entry and Exit.  */
4032 
4033 /* Function for normal multiple push prologue.  */
4034 void
nds32_expand_prologue(void)4035 nds32_expand_prologue (void)
4036 {
4037   int fp_adjust;
4038   int sp_adjust;
4039   unsigned Rb, Re;
4040 
4041   /* Compute and setup stack frame size.
4042      The result will be in cfun->machine.  */
4043   nds32_compute_stack_frame ();
4044 
4045   /* If this is a variadic function, first we need to push argument
4046      registers that hold the unnamed argument value.  */
4047   if (cfun->machine->va_args_size != 0)
4048     {
4049       Rb = cfun->machine->va_args_first_regno;
4050       Re = cfun->machine->va_args_last_regno;
4051       /* No need to push $fp, $gp, or $lp.  */
4052       nds32_emit_stack_push_multiple (Rb, Re, false, false, false, true);
4053 
4054       /* We may also need to adjust stack pointer for padding bytes
4055          because varargs may cause $sp not 8-byte aligned.  */
4056       if (cfun->machine->va_args_area_padding_bytes)
4057 	{
4058 	  /* Generate sp adjustment instruction.  */
4059 	  sp_adjust = cfun->machine->va_args_area_padding_bytes;
4060 
4061 	  nds32_emit_adjust_frame (stack_pointer_rtx,
4062 				   stack_pointer_rtx,
4063 				   -1 * sp_adjust);
4064 	}
4065     }
4066 
4067   /* If the function is 'naked',
4068      we do not have to generate prologue code fragment.  */
4069   if (cfun->machine->naked_p)
4070     return;
4071 
4072   /* Get callee_first_regno and callee_last_regno.  */
4073   Rb = cfun->machine->callee_saved_first_gpr_regno;
4074   Re = cfun->machine->callee_saved_last_gpr_regno;
4075 
4076   /* If $fp, $gp, $lp, and all callee-save registers are NOT required
4077      to be saved, we don't have to create multiple push instruction.
4078      Otherwise, a multiple push instruction is needed.  */
4079   if (!(Rb == SP_REGNUM && Re == SP_REGNUM
4080 	&& cfun->machine->fp_size == 0
4081 	&& cfun->machine->gp_size == 0
4082 	&& cfun->machine->lp_size == 0))
4083     {
4084       /* Create multiple push instruction rtx.  */
4085       nds32_emit_stack_push_multiple (
4086 	Rb, Re,
4087 	cfun->machine->fp_size, cfun->machine->gp_size, cfun->machine->lp_size,
4088 	false);
4089     }
4090 
4091   /* Save eh data registers.  */
4092   if (cfun->machine->use_eh_return_p)
4093     {
4094       Rb = cfun->machine->eh_return_data_first_regno;
4095       Re = cfun->machine->eh_return_data_last_regno;
4096 
4097       /* No need to push $fp, $gp, or $lp.
4098 	 Also, this is not variadic arguments push.  */
4099       nds32_emit_stack_push_multiple (Rb, Re, false, false, false, false);
4100     }
4101 
4102   /* Check frame_pointer_needed to see
4103      if we shall emit fp adjustment instruction.  */
4104   if (frame_pointer_needed)
4105     {
4106       /* adjust $fp = $sp + ($fp size) + ($gp size) + ($lp size)
4107 			  + (4 * callee-saved-registers)
4108 			  + (4 * exception-handling-data-registers)
4109 	 Note: No need to adjust
4110 	       cfun->machine->callee_saved_area_gpr_padding_bytes,
4111 	       because, at this point, stack pointer is just
4112 	       at the position after push instruction.  */
4113       fp_adjust = cfun->machine->fp_size
4114 		  + cfun->machine->gp_size
4115 		  + cfun->machine->lp_size
4116 		  + cfun->machine->callee_saved_gpr_regs_size
4117 		  + cfun->machine->eh_return_data_regs_size;
4118 
4119       nds32_emit_adjust_frame (hard_frame_pointer_rtx,
4120 			       stack_pointer_rtx,
4121 			       fp_adjust);
4122     }
4123 
4124   /* Save fpu registers.  */
4125   if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
4126     {
4127       /* When $sp moved to bottom of stack, we need to check whether
4128 	 the range of offset in the FPU instruction.  */
4129       int fpr_offset = cfun->machine->local_size
4130 		       + cfun->machine->out_args_size
4131 		       + cfun->machine->callee_saved_fpr_regs_size;
4132 
4133       /* Check FPU instruction offset imm14s.  */
4134       if (!satisfies_constraint_Is14 (GEN_INT (fpr_offset)))
4135 	{
4136 	  int fpr_space = cfun->machine->callee_saved_area_gpr_padding_bytes
4137 			  + cfun->machine->callee_saved_fpr_regs_size;
4138 
4139 	  /* Save fpu registers, need to allocate stack space
4140 	     for fpu callee registers.  And now $sp position
4141 	     on callee saved fpr registers.  */
4142 	  nds32_emit_adjust_frame (stack_pointer_rtx,
4143 				   stack_pointer_rtx,
4144 				   -1 * fpr_space);
4145 
4146 	  /* Emit fpu store instruction, using [$sp + offset] store
4147 	     fpu registers.  */
4148 	  nds32_emit_push_fpr_callee_saved (0);
4149 
4150           /* Adjust $sp = $sp - local_size - out_args_size.  */
4151 	  sp_adjust = cfun->machine->local_size
4152 		      + cfun->machine->out_args_size;
4153 
4154 	  /* Allocate stack space for local size and out args size.  */
4155 	  nds32_emit_adjust_frame (stack_pointer_rtx,
4156 				   stack_pointer_rtx,
4157 				   -1 * sp_adjust);
4158 	}
4159       else
4160 	{
4161 	  /* Offset range in Is14, so $sp moved to bottom of stack.  */
4162 
4163           /* Adjust $sp = $sp - local_size - out_args_size
4164 			      - callee_saved_area_gpr_padding_bytes
4165 			      - callee_saved_fpr_regs_size.  */
4166 	  sp_adjust = cfun->machine->local_size
4167 		      + cfun->machine->out_args_size
4168 		      + cfun->machine->callee_saved_area_gpr_padding_bytes
4169 		      + cfun->machine->callee_saved_fpr_regs_size;
4170 
4171 	  nds32_emit_adjust_frame (stack_pointer_rtx,
4172 				   stack_pointer_rtx,
4173 				   -1 * sp_adjust);
4174 
4175 	  /* Emit fpu store instruction, using [$sp + offset] store
4176 	     fpu registers.  */
4177 	  int fpr_position = cfun->machine->out_args_size
4178 			     + cfun->machine->local_size;
4179 	  nds32_emit_push_fpr_callee_saved (fpr_position);
4180 	}
4181     }
4182   else
4183     {
4184       /* Adjust $sp = $sp - local_size - out_args_size
4185 			  - callee_saved_area_gpr_padding_bytes.  */
4186       sp_adjust = cfun->machine->local_size
4187 		  + cfun->machine->out_args_size
4188 		  + cfun->machine->callee_saved_area_gpr_padding_bytes;
4189 
4190       /* sp_adjust value may be out of range of the addi instruction,
4191 	 create alternative add behavior with TA_REGNUM if necessary,
4192 	 using NEGATIVE value to tell that we are decreasing address.  */
4193       nds32_emit_adjust_frame (stack_pointer_rtx,
4194 			       stack_pointer_rtx,
4195 			       -1 * sp_adjust);
4196     }
4197 
4198   /* Prevent the instruction scheduler from
4199      moving instructions across the boundary.  */
4200   emit_insn (gen_blockage ());
4201 }
4202 
4203 /* Function for normal multiple pop epilogue.  */
4204 void
nds32_expand_epilogue(bool sibcall_p)4205 nds32_expand_epilogue (bool sibcall_p)
4206 {
4207   int sp_adjust;
4208   unsigned Rb, Re;
4209 
4210   /* Compute and setup stack frame size.
4211      The result will be in cfun->machine.  */
4212   nds32_compute_stack_frame ();
4213 
4214   /* Prevent the instruction scheduler from
4215      moving instructions across the boundary.  */
4216   emit_insn (gen_blockage ());
4217 
4218   /* If the function is 'naked', we do not have to generate
4219      epilogue code fragment BUT 'ret' instruction.
4220      However, if this function is also a variadic function,
4221      we need to create adjust stack pointer before 'ret' instruction.  */
4222   if (cfun->machine->naked_p)
4223     {
4224       /* If this is a variadic function, we do not have to restore argument
4225 	 registers but need to adjust stack pointer back to previous stack
4226 	 frame location before return.  */
4227       if (cfun->machine->va_args_size != 0)
4228 	{
4229 	  /* Generate sp adjustment instruction.
4230 	     We  need to consider padding bytes here.  */
4231 	  sp_adjust = cfun->machine->va_args_size
4232 		      + cfun->machine->va_args_area_padding_bytes;
4233 
4234 	  nds32_emit_adjust_frame (stack_pointer_rtx,
4235 				   stack_pointer_rtx,
4236 				   sp_adjust);
4237 	}
4238 
4239       /* Generate return instruction by using 'return_internal' pattern.
4240 	 Make sure this instruction is after gen_blockage().  */
4241       if (!sibcall_p)
4242 	emit_jump_insn (gen_return_internal ());
4243       return;
4244     }
4245 
4246   if (frame_pointer_needed)
4247     {
4248       /* Restore fpu registers.  */
4249       if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
4250 	{
4251 	  int gpr_padding = cfun->machine->callee_saved_area_gpr_padding_bytes;
4252 
4253 	  /* adjust $sp = $fp - ($fp size) - ($gp size) - ($lp size)
4254 			      - (4 * callee-saved-registers)
4255 			      - (4 * exception-handling-data-registers)
4256 			      - (4 * callee-saved-gpr-registers padding byte)
4257 			      - (4 * callee-saved-fpr-registers)
4258 	     Note:  we want to adjust stack pointer
4259 		    to the position for callee-saved fpr register,
4260 		    And restore fpu register use .bi instruction to adjust $sp
4261 		    from callee-saved fpr register to pop instruction.  */
4262 	  sp_adjust = cfun->machine->fp_size
4263 		      + cfun->machine->gp_size
4264 		      + cfun->machine->lp_size
4265 		      + cfun->machine->callee_saved_gpr_regs_size
4266 		      + cfun->machine->eh_return_data_regs_size
4267 		      + cfun->machine->callee_saved_area_gpr_padding_bytes
4268 		      + cfun->machine->callee_saved_fpr_regs_size;
4269 
4270 	  nds32_emit_adjust_frame (stack_pointer_rtx,
4271 				   hard_frame_pointer_rtx,
4272 				   -1 * sp_adjust);
4273 
4274 	  /* Emit fpu load instruction, using .bi instruction
4275 	     load fpu registers.  */
4276 	  nds32_emit_pop_fpr_callee_saved (gpr_padding);
4277 	}
4278       else
4279 	{
4280 	  /* adjust $sp = $fp - ($fp size) - ($gp size) - ($lp size)
4281 			      - (4 * callee-saved-registers)
4282 			      - (4 * exception-handling-data-registers)
4283 	     Note: No need to adjust
4284 		   cfun->machine->callee_saved_area_gpr_padding_bytes,
4285 		   because we want to adjust stack pointer
4286 		   to the position for pop instruction.  */
4287 	  sp_adjust = cfun->machine->fp_size
4288 		      + cfun->machine->gp_size
4289 		      + cfun->machine->lp_size
4290 		      + cfun->machine->callee_saved_gpr_regs_size
4291 		      + cfun->machine->eh_return_data_regs_size;
4292 
4293 	  nds32_emit_adjust_frame (stack_pointer_rtx,
4294 				   hard_frame_pointer_rtx,
4295 				   -1 * sp_adjust);
4296 	}
4297     }
4298   else
4299     {
4300       /* Restore fpu registers.  */
4301       if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
4302 	{
4303 	  int gpr_padding = cfun->machine->callee_saved_area_gpr_padding_bytes;
4304 
4305 	  /* Adjust $sp = $sp + local_size + out_args_size.  */
4306 	  sp_adjust = cfun->machine->local_size
4307 		      + cfun->machine->out_args_size;
4308 
4309 	  nds32_emit_adjust_frame (stack_pointer_rtx,
4310 				   stack_pointer_rtx,
4311 				   sp_adjust);
4312 
4313 	  /* Emit fpu load instruction, using .bi instruction
4314 	     load fpu registers, and adjust $sp from callee-saved fpr register
4315 	     to callee-saved gpr register.  */
4316 	  nds32_emit_pop_fpr_callee_saved (gpr_padding);
4317 	}
4318       else
4319 	{
4320 	  /* If frame pointer is NOT needed,
4321 	     we cannot calculate the sp adjustment from frame pointer.
4322 	     Instead, we calculate the adjustment by local_size,
4323 	     out_args_size, and callee_saved_area_gpr_padding_bytes.
4324 	     Notice that such sp adjustment value may be out of range,
4325 	     so we have to deal with it as well.  */
4326 
4327 	  /* Adjust $sp = $sp + local_size + out_args_size
4328 			      + callee_saved_area_gpr_padding_bytes.  */
4329 	  sp_adjust = cfun->machine->local_size
4330 		      + cfun->machine->out_args_size
4331 		      + cfun->machine->callee_saved_area_gpr_padding_bytes;
4332 
4333 	  nds32_emit_adjust_frame (stack_pointer_rtx,
4334 				   stack_pointer_rtx,
4335 				   sp_adjust);
4336 	}
4337     }
4338 
4339   /* Restore eh data registers.  */
4340   if (cfun->machine->use_eh_return_p)
4341     {
4342       Rb = cfun->machine->eh_return_data_first_regno;
4343       Re = cfun->machine->eh_return_data_last_regno;
4344 
4345       /* No need to pop $fp, $gp, or $lp.  */
4346       nds32_emit_stack_pop_multiple (Rb, Re, false, false, false);
4347     }
4348 
4349   /* Get callee_first_regno and callee_last_regno.  */
4350   Rb = cfun->machine->callee_saved_first_gpr_regno;
4351   Re = cfun->machine->callee_saved_last_gpr_regno;
4352 
4353   /* If $fp, $gp, $lp, and all callee-save registers are NOT required
4354      to be saved, we don't have to create multiple pop instruction.
4355      Otherwise, a multiple pop instruction is needed.  */
4356   if (!(Rb == SP_REGNUM && Re == SP_REGNUM
4357 	&& cfun->machine->fp_size == 0
4358 	&& cfun->machine->gp_size == 0
4359 	&& cfun->machine->lp_size == 0))
4360     {
4361       /* Create multiple pop instruction rtx.  */
4362       nds32_emit_stack_pop_multiple (
4363 	Rb, Re,
4364 	cfun->machine->fp_size, cfun->machine->gp_size, cfun->machine->lp_size);
4365     }
4366 
4367   /* If this is a variadic function, we do not have to restore argument
4368      registers but need to adjust stack pointer back to previous stack
4369      frame location before return.  */
4370   if (cfun->machine->va_args_size != 0)
4371     {
4372       /* Generate sp adjustment instruction.
4373 	 We need to consider padding bytes here.  */
4374       sp_adjust = cfun->machine->va_args_size
4375 		  + cfun->machine->va_args_area_padding_bytes;
4376 
4377       nds32_emit_adjust_frame (stack_pointer_rtx,
4378 			       stack_pointer_rtx,
4379 			       sp_adjust);
4380     }
4381 
4382   /* If this function uses __builtin_eh_return, make stack adjustment
4383      for exception handler.  */
4384   if (cfun->machine->use_eh_return_p)
4385     {
4386       /* We need to unwind the stack by the offset computed by
4387 	 EH_RETURN_STACKADJ_RTX.  However, at this point the CFA is
4388 	 based on SP.  Ideally we would update the SP and define the
4389 	 CFA along the lines of:
4390 
4391 	 SP = SP + EH_RETURN_STACKADJ_RTX
4392 	 (regnote CFA = SP - EH_RETURN_STACKADJ_RTX)
4393 
4394 	 However the dwarf emitter only understands a constant
4395 	 register offset.
4396 
4397 	 The solution chosen here is to use the otherwise $ta ($r15)
4398 	 as a temporary register to hold the current SP value.  The
4399 	 CFA is described using $ta then SP is modified.  */
4400 
4401       rtx ta_reg;
4402       rtx insn;
4403 
4404       ta_reg = gen_rtx_REG (SImode, TA_REGNUM);
4405 
4406       insn = emit_move_insn (ta_reg, stack_pointer_rtx);
4407       add_reg_note (insn, REG_CFA_DEF_CFA, ta_reg);
4408       RTX_FRAME_RELATED_P (insn) = 1;
4409 
4410       emit_insn (gen_addsi3 (stack_pointer_rtx,
4411 			     stack_pointer_rtx,
4412 			     EH_RETURN_STACKADJ_RTX));
4413 
4414       /* Ensure the assignment to $ta does not get optimized away.  */
4415       emit_use (ta_reg);
4416     }
4417 
4418   /* Generate return instruction.  */
4419   if (!sibcall_p)
4420     emit_jump_insn (gen_return_internal ());
4421 }
4422 
4423 /* Function for v3push prologue.  */
4424 void
nds32_expand_prologue_v3push(void)4425 nds32_expand_prologue_v3push (void)
4426 {
4427   int fp_adjust;
4428   int sp_adjust;
4429   int fpr_space = 0;
4430   unsigned Rb, Re;
4431 
4432   /* Compute and setup stack frame size.
4433      The result will be in cfun->machine.  */
4434   nds32_compute_stack_frame ();
4435 
4436   if (cfun->machine->callee_saved_gpr_regs_size > 0)
4437     df_set_regs_ever_live (FP_REGNUM, 1);
4438 
4439   /* If the function is 'naked',
4440      we do not have to generate prologue code fragment.  */
4441   if (cfun->machine->naked_p)
4442     return;
4443 
4444   /* Get callee_first_regno and callee_last_regno.  */
4445   Rb = cfun->machine->callee_saved_first_gpr_regno;
4446   Re = cfun->machine->callee_saved_last_gpr_regno;
4447 
4448   /* Calculate sp_adjust first to test if 'push25 Re,imm8u' is available,
4449      where imm8u has to be 8-byte alignment.  */
4450   sp_adjust = cfun->machine->local_size
4451 	      + cfun->machine->out_args_size
4452 	      + cfun->machine->callee_saved_area_gpr_padding_bytes
4453 	      + cfun->machine->callee_saved_fpr_regs_size;
4454 
4455   if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
4456       && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust))
4457     {
4458       /* We can use 'push25 Re,imm8u'.  */
4459 
4460       /* nds32_emit_stack_v3push(last_regno, sp_adjust),
4461 	 the pattern 'stack_v3push' is implemented in nds32.md.  */
4462       nds32_emit_stack_v3push (Rb, Re, sp_adjust);
4463 
4464       /* Save fpu registers.  */
4465       if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
4466 	{
4467 	  /* Calculate fpr position.  */
4468 	  int fpr_position = cfun->machine->local_size
4469 			     + cfun->machine->out_args_size;
4470 	  /* Emit fpu store instruction, using [$sp + offset] store
4471 	     fpu registers.  */
4472 	  nds32_emit_push_fpr_callee_saved (fpr_position);
4473 	}
4474 
4475       /* Check frame_pointer_needed to see
4476 	 if we shall emit fp adjustment instruction.  */
4477       if (frame_pointer_needed)
4478 	{
4479 	  /* adjust $fp = $sp   + 4         ($fp size)
4480 				+ 4         ($gp size)
4481 				+ 4         ($lp size)
4482 				+ (4 * n)   (callee-saved registers)
4483 				+ sp_adjust ('push25 Re,imm8u')
4484 	     Note: Since we use 'push25 Re,imm8u',
4485 		   the position of stack pointer is further
4486 		   changed after push instruction.
4487 		   Hence, we need to take sp_adjust value
4488 		   into consideration.  */
4489 	  fp_adjust = cfun->machine->fp_size
4490 		      + cfun->machine->gp_size
4491 		      + cfun->machine->lp_size
4492 		      + cfun->machine->callee_saved_gpr_regs_size
4493 		      + sp_adjust;
4494 
4495 	  nds32_emit_adjust_frame (hard_frame_pointer_rtx,
4496 				   stack_pointer_rtx,
4497 				   fp_adjust);
4498 	}
4499     }
4500   else
4501     {
4502       if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
4503 	{
4504 	  /* Calculate fpr space.  */
4505 	  fpr_space = cfun->machine->callee_saved_area_gpr_padding_bytes
4506 		      + cfun->machine->callee_saved_fpr_regs_size;
4507 
4508 	  /* We have to use 'push25 Re, fpr_space', to pre-allocate
4509 	     callee saved fpr registers space.  */
4510 	  nds32_emit_stack_v3push (Rb, Re, fpr_space);
4511 	  nds32_emit_push_fpr_callee_saved (0);
4512 	}
4513       else
4514 	{
4515 	  /* We have to use 'push25 Re,0' and
4516 	     expand one more instruction to adjust $sp later.  */
4517 
4518 	  /* nds32_emit_stack_v3push(last_regno, sp_adjust),
4519 	     the pattern 'stack_v3push' is implemented in nds32.md.  */
4520 	  nds32_emit_stack_v3push (Rb, Re, 0);
4521 	}
4522 
4523       /* Check frame_pointer_needed to see
4524 	 if we shall emit fp adjustment instruction.  */
4525       if (frame_pointer_needed)
4526 	{
4527 	  /* adjust $fp = $sp + 4        ($fp size)
4528 			      + 4        ($gp size)
4529 			      + 4        ($lp size)
4530 			      + (4 * n)  (callee-saved registers)
4531 	     Note: Since we use 'push25 Re,0',
4532 		   the stack pointer is just at the position
4533 		   after push instruction.
4534 		   No need to take sp_adjust into consideration.  */
4535 	  fp_adjust = cfun->machine->fp_size
4536 		      + cfun->machine->gp_size
4537 		      + cfun->machine->lp_size
4538 		      + cfun->machine->callee_saved_gpr_regs_size;
4539 
4540 	  if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
4541 	    {
4542 	      /* We use 'push25 Re, fpr_space', the $sp is
4543 		 on callee saved fpr position, so need to consider
4544 		 fpr space.  */
4545 	      fp_adjust = fp_adjust + fpr_space;
4546 	    }
4547 
4548 	  nds32_emit_adjust_frame (hard_frame_pointer_rtx,
4549 				   stack_pointer_rtx,
4550 				   fp_adjust);
4551 	}
4552 
4553       if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
4554 	{
4555 	  /* We use 'push25 Re, fpr_space',
4556 	     the $sp is on callee saved fpr position,
4557 	     no need to consider fpr space.  */
4558 	  sp_adjust = sp_adjust - fpr_space;
4559 	}
4560 
4561       /* Because we use 'push25 Re,0',
4562 	 we need to expand one more instruction to adjust $sp.
4563 	 using NEGATIVE value to tell that we are decreasing address.  */
4564       nds32_emit_adjust_frame (stack_pointer_rtx,
4565 			       stack_pointer_rtx,
4566 			       -1 * sp_adjust);
4567     }
4568 
4569   /* Prevent the instruction scheduler from
4570      moving instructions across the boundary.  */
4571   emit_insn (gen_blockage ());
4572 }
4573 
4574 /* Function for v3pop epilogue.  */
4575 void
nds32_expand_epilogue_v3pop(bool sibcall_p)4576 nds32_expand_epilogue_v3pop (bool sibcall_p)
4577 {
4578   int sp_adjust;
4579   unsigned Rb, Re;
4580 
4581   /* Compute and setup stack frame size.
4582      The result will be in cfun->machine.  */
4583   nds32_compute_stack_frame ();
4584 
4585   /* Prevent the instruction scheduler from
4586      moving instructions across the boundary.  */
4587   emit_insn (gen_blockage ());
4588 
4589   /* If the function is 'naked', we do not have to generate
4590      epilogue code fragment BUT 'ret' instruction.  */
4591   if (cfun->machine->naked_p)
4592     {
4593       /* Generate return instruction by using 'return_internal' pattern.
4594 	 Make sure this instruction is after gen_blockage().  */
4595       if (!sibcall_p)
4596 	emit_jump_insn (gen_return_internal ());
4597       return;
4598     }
4599 
4600   /* Get callee_first_regno and callee_last_regno.  */
4601   Rb = cfun->machine->callee_saved_first_gpr_regno;
4602   Re = cfun->machine->callee_saved_last_gpr_regno;
4603 
4604   /* Calculate sp_adjust first to test if 'pop25 Re,imm8u' is available,
4605      where imm8u has to be 8-byte alignment.  */
4606   sp_adjust = cfun->machine->local_size
4607 	      + cfun->machine->out_args_size
4608 	      + cfun->machine->callee_saved_area_gpr_padding_bytes
4609 	      + cfun->machine->callee_saved_fpr_regs_size;
4610 
4611   /* We have to consider alloca issue as well.
4612      If the function does call alloca(), the stack pointer is not fixed.
4613      In that case, we cannot use 'pop25 Re,imm8u' directly.
4614      We have to caculate stack pointer from frame pointer
4615      and then use 'pop25 Re,0'.
4616      Of course, the frame_pointer_needed should be nonzero
4617      if the function calls alloca().  */
4618   if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
4619       && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)
4620       && !cfun->calls_alloca)
4621     {
4622       /* Restore fpu registers.  */
4623       if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
4624 	{
4625 	  int fpr_position = cfun->machine->local_size
4626 			     + cfun->machine->out_args_size;
4627 	  /* Emit fpu load instruction, using [$sp + offset] restore
4628 	     fpu registers.  */
4629 	  nds32_emit_v3pop_fpr_callee_saved (fpr_position);
4630 	}
4631 
4632       /* We can use 'pop25 Re,imm8u'.  */
4633 
4634       /* nds32_emit_stack_v3pop(last_regno, sp_adjust),
4635 	 the pattern 'stack_v3pop' is implementad in nds32.md.  */
4636       nds32_emit_stack_v3pop (Rb, Re, sp_adjust);
4637     }
4638   else
4639     {
4640       /* We have to use 'pop25 Re,0', and prior to it,
4641 	 we must expand one more instruction to adjust $sp.  */
4642 
4643       if (frame_pointer_needed)
4644 	{
4645 	  /* adjust $sp = $fp - 4        ($fp size)
4646 			      - 4        ($gp size)
4647 			      - 4        ($lp size)
4648 			      - (4 * n)  (callee-saved registers)
4649 	     Note: No need to adjust
4650 		   cfun->machine->callee_saved_area_gpr_padding_bytes,
4651 		   because we want to adjust stack pointer
4652 		   to the position for pop instruction.  */
4653 	  sp_adjust = cfun->machine->fp_size
4654 		      + cfun->machine->gp_size
4655 		      + cfun->machine->lp_size
4656 		      + cfun->machine->callee_saved_gpr_regs_size;
4657 
4658 	  /* Restore fpu registers.  */
4659 	  if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
4660 	    {
4661 	      /* Set $sp to callee saved fpr position, we need to restore
4662 		 fpr registers.  */
4663 	      sp_adjust = sp_adjust
4664 			  + cfun->machine->callee_saved_area_gpr_padding_bytes
4665 			  + cfun->machine->callee_saved_fpr_regs_size;
4666 
4667 	      nds32_emit_adjust_frame (stack_pointer_rtx,
4668 				       hard_frame_pointer_rtx,
4669 				       -1 * sp_adjust);
4670 
4671 	      /* Emit fpu load instruction, using [$sp + offset] restore
4672 		 fpu registers.  */
4673 	      nds32_emit_v3pop_fpr_callee_saved (0);
4674 	    }
4675 	  else
4676 	    {
4677 	      nds32_emit_adjust_frame (stack_pointer_rtx,
4678 				       hard_frame_pointer_rtx,
4679 				       -1 * sp_adjust);
4680 	    }
4681 	}
4682       else
4683 	{
4684 	  /* If frame pointer is NOT needed,
4685 	     we cannot calculate the sp adjustment from frame pointer.
4686 	     Instead, we calculate the adjustment by local_size,
4687 	     out_args_size, and callee_saved_area_padding_bytes.
4688 	     Notice that such sp adjustment value may be out of range,
4689 	     so we have to deal with it as well.  */
4690 
4691 	  /* Adjust $sp = $sp + local_size + out_args_size
4692 			      + callee_saved_area_gpr_padding_bytes
4693 			      + callee_saved_fpr_regs_size.  */
4694 	  sp_adjust = cfun->machine->local_size
4695 		      + cfun->machine->out_args_size
4696 		      + cfun->machine->callee_saved_area_gpr_padding_bytes
4697 		      + cfun->machine->callee_saved_fpr_regs_size;
4698 
4699 	  /* Restore fpu registers.  */
4700 	  if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
4701 	    {
4702 	      /* Set $sp to callee saved fpr position, we need to restore
4703 		 fpr registers.  */
4704 	      sp_adjust = sp_adjust
4705 			  - cfun->machine->callee_saved_area_gpr_padding_bytes
4706 			  - cfun->machine->callee_saved_fpr_regs_size;
4707 
4708 	      nds32_emit_adjust_frame (stack_pointer_rtx,
4709 				       stack_pointer_rtx,
4710 				       sp_adjust);
4711 
4712 	      /* Emit fpu load instruction, using [$sp + offset] restore
4713 		 fpu registers.  */
4714 	      nds32_emit_v3pop_fpr_callee_saved (0);
4715 	    }
4716 	  else
4717 	    {
4718 	       /* sp_adjust value may be out of range of the addi instruction,
4719 		  create alternative add behavior with TA_REGNUM if necessary,
4720 		  using POSITIVE value to tell that we are increasing
4721 		  address.  */
4722 	      nds32_emit_adjust_frame (stack_pointer_rtx,
4723 				       stack_pointer_rtx,
4724 				       sp_adjust);
4725 	    }
4726 	}
4727 
4728       if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
4729 	{
4730 	  /* We have fpr need to restore, so $sp is set on callee saved fpr
4731 	     position.  And we use 'pop25 Re, fpr_space' to adjust $sp.  */
4732 	  int fpr_space = cfun->machine->callee_saved_area_gpr_padding_bytes
4733 			  + cfun->machine->callee_saved_fpr_regs_size;
4734 	  nds32_emit_stack_v3pop (Rb, Re, fpr_space);
4735 	}
4736       else
4737 	{
4738 	  /* nds32_emit_stack_v3pop(last_regno, sp_adjust),
4739 	     the pattern 'stack_v3pop' is implementad in nds32.md.  */
4740 	  nds32_emit_stack_v3pop (Rb, Re, 0);
4741 	}
4742     }
4743   /* Generate return instruction.  */
4744   emit_jump_insn (gen_pop25return ());
4745 }
4746 
4747 /* Return nonzero if this function is known to have a null epilogue.
4748    This allows the optimizer to omit jumps to jumps if no stack
4749    was created.  */
4750 int
nds32_can_use_return_insn(void)4751 nds32_can_use_return_insn (void)
4752 {
4753   int sp_adjust;
4754 
4755   /* Prior to reloading, we can't tell how many registers must be saved.
4756      Thus we can not determine whether this function has null epilogue.  */
4757   if (!reload_completed)
4758     return 0;
4759 
4760   sp_adjust = cfun->machine->local_size
4761 	      + cfun->machine->out_args_size
4762 	      + cfun->machine->callee_saved_area_gpr_padding_bytes
4763 	      + cfun->machine->callee_saved_fpr_regs_size;
4764   if (!cfun->machine->fp_as_gp_p
4765       && satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
4766       && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)
4767       && !cfun->calls_alloca
4768       && NDS32_V3PUSH_AVAILABLE_P
4769       && !(TARGET_HARD_FLOAT
4770 	   && (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)))
4771     return 1;
4772 
4773   /* If no stack was created, two conditions must be satisfied:
4774      1. This is a naked function.
4775 	So there is no callee-saved, local size, or outgoing size.
4776      2. This is NOT a variadic function.
4777 	So there is no pushing arguement registers into the stack.  */
4778   return (cfun->machine->naked_p && (cfun->machine->va_args_size == 0));
4779 }
4780 
4781 scalar_int_mode
nds32_case_vector_shorten_mode(int min_offset,int max_offset,rtx body ATTRIBUTE_UNUSED)4782 nds32_case_vector_shorten_mode (int min_offset, int max_offset,
4783 				rtx body ATTRIBUTE_UNUSED)
4784 {
4785   if (min_offset < 0 || max_offset >= 0x2000)
4786     return SImode;
4787   else
4788     {
4789       /* The jump table maybe need to 2 byte alignment,
4790 	 so reserved 1 byte for check max_offset.  */
4791       if (max_offset >= 0xff)
4792 	return HImode;
4793       else
4794 	return QImode;
4795     }
4796 }
4797 
4798 /* ------------------------------------------------------------------------ */
4799 
4800 /* Return alignment for the label.  */
4801 int
nds32_target_alignment(rtx_insn * label)4802 nds32_target_alignment (rtx_insn *label)
4803 {
4804   rtx_insn *insn;
4805 
4806   if (!NDS32_ALIGN_P ())
4807     return 0;
4808 
4809   insn = next_active_insn (label);
4810 
4811   /* Always align to 4 byte when first instruction after label is jump
4812      instruction since length for that might changed, so let's always align
4813      it for make sure we don't lose any perfomance here.  */
4814   if (insn == 0
4815       || (get_attr_length (insn) == 2
4816 	  && !JUMP_P (insn) && !CALL_P (insn)))
4817     return 0;
4818   else
4819     return 2;
4820 }
4821 
4822 /* Return alignment for data.  */
4823 unsigned int
nds32_data_alignment(tree data,unsigned int basic_align)4824 nds32_data_alignment (tree data,
4825 		      unsigned int basic_align)
4826 {
4827   if ((basic_align < BITS_PER_WORD)
4828       && (TREE_CODE (data) == ARRAY_TYPE
4829 	 || TREE_CODE (data) == UNION_TYPE
4830 	 || TREE_CODE (data) == RECORD_TYPE))
4831     return BITS_PER_WORD;
4832   else
4833     return basic_align;
4834 }
4835 
4836 /* Return alignment for constant value.  */
4837 static HOST_WIDE_INT
nds32_constant_alignment(const_tree constant,HOST_WIDE_INT basic_align)4838 nds32_constant_alignment (const_tree constant,
4839 			  HOST_WIDE_INT basic_align)
4840 {
4841   /* Make string literal and constant for constructor to word align.  */
4842   if (((TREE_CODE (constant) == STRING_CST
4843 	|| TREE_CODE (constant) == CONSTRUCTOR
4844 	|| TREE_CODE (constant) == UNION_TYPE
4845 	|| TREE_CODE (constant) == RECORD_TYPE
4846 	|| TREE_CODE (constant) == ARRAY_TYPE)
4847        && basic_align < BITS_PER_WORD))
4848     return BITS_PER_WORD;
4849   else
4850     return basic_align;
4851 }
4852 
4853 /* Return alignment for local variable.  */
4854 unsigned int
nds32_local_alignment(tree local ATTRIBUTE_UNUSED,unsigned int basic_align)4855 nds32_local_alignment (tree local ATTRIBUTE_UNUSED,
4856 		       unsigned int basic_align)
4857 {
4858   bool at_least_align_to_word = false;
4859   /* Make local array, struct and union at least align to word for make
4860      sure it can unroll memcpy when initialize by constant.  */
4861   switch (TREE_CODE (local))
4862     {
4863     case ARRAY_TYPE:
4864     case RECORD_TYPE:
4865     case UNION_TYPE:
4866       at_least_align_to_word = true;
4867       break;
4868     default:
4869       at_least_align_to_word = false;
4870       break;
4871     }
4872   if (at_least_align_to_word
4873       && (basic_align < BITS_PER_WORD))
4874     return BITS_PER_WORD;
4875   else
4876     return basic_align;
4877 }
4878 
4879 bool
nds32_split_double_word_load_store_p(rtx * operands,bool load_p)4880 nds32_split_double_word_load_store_p(rtx *operands, bool load_p)
4881 {
4882   rtx mem = load_p ? operands[1] : operands[0];
4883   /* Do split at split2 if -O0 or schedule 2 not enable.  */
4884   if (optimize == 0 || !flag_schedule_insns_after_reload)
4885     return !satisfies_constraint_Da (mem) || MEM_VOLATILE_P (mem);
4886 
4887   /* Split double word load store after copy propgation.  */
4888   if (current_pass == NULL)
4889     return false;
4890 
4891   const char *pass_name = current_pass->name;
4892   if (pass_name && ((strcmp (pass_name, "split4") == 0)
4893 		     || (strcmp (pass_name, "split5") == 0)))
4894     return !satisfies_constraint_Da (mem) || MEM_VOLATILE_P (mem);
4895 
4896   return false;
4897 }
4898 
4899 static bool
nds32_use_blocks_for_constant_p(machine_mode mode,const_rtx x ATTRIBUTE_UNUSED)4900 nds32_use_blocks_for_constant_p (machine_mode mode,
4901 				 const_rtx x ATTRIBUTE_UNUSED)
4902 {
4903   if ((TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)
4904       && (mode == DFmode || mode == SFmode))
4905     return true;
4906   else
4907     return false;
4908 }
4909 
4910 /* ------------------------------------------------------------------------ */
4911 
4912 /* PART 5: Initialize target hook structure and definitions.  */
4913 
4914 /* Controlling the Compilation Driver.  */
4915 
4916 
4917 /* Run-time Target Specification.  */
4918 
4919 
4920 /* Defining Data Structures for Per-function Information.  */
4921 
4922 
4923 /* Storage Layout.  */
4924 
4925 #undef TARGET_PROMOTE_FUNCTION_MODE
4926 #define TARGET_PROMOTE_FUNCTION_MODE \
4927   default_promote_function_mode_always_promote
4928 
4929 #undef TARGET_EXPAND_TO_RTL_HOOK
4930 #define TARGET_EXPAND_TO_RTL_HOOK nds32_expand_to_rtl_hook
4931 
4932 #undef TARGET_CONSTANT_ALIGNMENT
4933 #define TARGET_CONSTANT_ALIGNMENT nds32_constant_alignment
4934 
4935 
4936 /* Layout of Source Language Data Types.  */
4937 
4938 
4939 /* Register Usage.  */
4940 
4941 /* -- Basic Characteristics of Registers.  */
4942 
4943 #undef TARGET_CONDITIONAL_REGISTER_USAGE
4944 #define TARGET_CONDITIONAL_REGISTER_USAGE nds32_conditional_register_usage
4945 
4946 /* -- Order of Allocation of Registers.  */
4947 
4948 /* -- How Values Fit in Registers.  */
4949 
4950 #undef TARGET_HARD_REGNO_NREGS
4951 #define TARGET_HARD_REGNO_NREGS nds32_hard_regno_nregs
4952 
4953 #undef TARGET_HARD_REGNO_MODE_OK
4954 #define TARGET_HARD_REGNO_MODE_OK nds32_hard_regno_mode_ok
4955 
4956 #undef TARGET_MODES_TIEABLE_P
4957 #define TARGET_MODES_TIEABLE_P nds32_modes_tieable_p
4958 
4959 /* -- Handling Leaf Functions.  */
4960 
4961 /* -- Registers That Form a Stack.  */
4962 
4963 
4964 /* Register Classes.  */
4965 
4966 #undef TARGET_CLASS_MAX_NREGS
4967 #define TARGET_CLASS_MAX_NREGS nds32_class_max_nregs
4968 
4969 #undef TARGET_REGISTER_PRIORITY
4970 #define TARGET_REGISTER_PRIORITY nds32_register_priority
4971 
4972 #undef TARGET_CAN_CHANGE_MODE_CLASS
4973 #define TARGET_CAN_CHANGE_MODE_CLASS nds32_can_change_mode_class
4974 
4975 
4976 /* Obsolete Macros for Defining Constraints.  */
4977 
4978 
4979 /* Stack Layout and Calling Conventions.  */
4980 
4981 /* -- Basic Stack Layout.  */
4982 
4983 /* -- Exception Handling Support.  */
4984 
4985 /* -- Specifying How Stack Checking is Done.  */
4986 
4987 /* -- Registers That Address the Stack Frame.  */
4988 
4989 /* -- Eliminating Frame Pointer and Arg Pointer.  */
4990 
4991 #undef TARGET_CAN_ELIMINATE
4992 #define TARGET_CAN_ELIMINATE nds32_can_eliminate
4993 
4994 /* -- Passing Function Arguments on the Stack.  */
4995 
4996 /* -- Passing Arguments in Registers.  */
4997 
4998 #undef TARGET_FUNCTION_ARG
4999 #define TARGET_FUNCTION_ARG nds32_function_arg
5000 
5001 #undef TARGET_MUST_PASS_IN_STACK
5002 #define TARGET_MUST_PASS_IN_STACK nds32_must_pass_in_stack
5003 
5004 #undef TARGET_ARG_PARTIAL_BYTES
5005 #define TARGET_ARG_PARTIAL_BYTES nds32_arg_partial_bytes
5006 
5007 #undef TARGET_FUNCTION_ARG_ADVANCE
5008 #define TARGET_FUNCTION_ARG_ADVANCE nds32_function_arg_advance
5009 
5010 #undef TARGET_FUNCTION_ARG_BOUNDARY
5011 #define TARGET_FUNCTION_ARG_BOUNDARY nds32_function_arg_boundary
5012 
5013 /* -- How Scalar Function Values Are Returned.  */
5014 
5015 #undef TARGET_FUNCTION_VALUE
5016 #define TARGET_FUNCTION_VALUE nds32_function_value
5017 
5018 #undef TARGET_LIBCALL_VALUE
5019 #define TARGET_LIBCALL_VALUE nds32_libcall_value
5020 
5021 #undef TARGET_FUNCTION_VALUE_REGNO_P
5022 #define TARGET_FUNCTION_VALUE_REGNO_P nds32_function_value_regno_p
5023 
5024 /* -- How Large Values Are Returned.  */
5025 
5026 #undef TARGET_RETURN_IN_MEMORY
5027 #define TARGET_RETURN_IN_MEMORY nds32_return_in_memory
5028 
5029 /* -- Caller-Saves Register Allocation.  */
5030 
5031 /* -- Function Entry and Exit.  */
5032 
5033 #undef TARGET_ASM_FUNCTION_PROLOGUE
5034 #define TARGET_ASM_FUNCTION_PROLOGUE nds32_asm_function_prologue
5035 
5036 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
5037 #define TARGET_ASM_FUNCTION_END_PROLOGUE nds32_asm_function_end_prologue
5038 
5039 #undef  TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
5040 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE nds32_asm_function_begin_epilogue
5041 
5042 #undef TARGET_ASM_FUNCTION_EPILOGUE
5043 #define TARGET_ASM_FUNCTION_EPILOGUE nds32_asm_function_epilogue
5044 
5045 #undef TARGET_ASM_OUTPUT_MI_THUNK
5046 #define TARGET_ASM_OUTPUT_MI_THUNK nds32_asm_output_mi_thunk
5047 
5048 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5049 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
5050 
5051 /* -- Generating Code for Profiling.  */
5052 
5053 /* -- Permitting tail calls.  */
5054 
5055 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5056 #define TARGET_FUNCTION_OK_FOR_SIBCALL nds32_function_ok_for_sibcall
5057 
5058 #undef TARGET_WARN_FUNC_RETURN
5059 #define TARGET_WARN_FUNC_RETURN nds32_warn_func_return
5060 
5061 /* Stack smashing protection.  */
5062 
5063 
5064 /* Implementing the Varargs Macros.  */
5065 
5066 #undef TARGET_SETUP_INCOMING_VARARGS
5067 #define TARGET_SETUP_INCOMING_VARARGS nds32_setup_incoming_varargs
5068 
5069 #undef TARGET_STRICT_ARGUMENT_NAMING
5070 #define TARGET_STRICT_ARGUMENT_NAMING nds32_strict_argument_naming
5071 
5072 
5073 /* Trampolines for Nested Functions.  */
5074 
5075 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
5076 #define TARGET_ASM_TRAMPOLINE_TEMPLATE nds32_asm_trampoline_template
5077 
5078 #undef TARGET_TRAMPOLINE_INIT
5079 #define TARGET_TRAMPOLINE_INIT nds32_trampoline_init
5080 
5081 
5082 /* Implicit Calls to Library Routines.  */
5083 
5084 
5085 /* Addressing Modes.  */
5086 
5087 #undef TARGET_LEGITIMATE_ADDRESS_P
5088 #define TARGET_LEGITIMATE_ADDRESS_P nds32_legitimate_address_p
5089 
5090 
5091 /* Anchored Addresses.  */
5092 
5093 
5094 /* Condition Code Status.  */
5095 
5096 /* -- Representation of condition codes using (cc0).  */
5097 
5098 /* -- Representation of condition codes using registers.  */
5099 
5100 #undef TARGET_CANONICALIZE_COMPARISON
5101 #define TARGET_CANONICALIZE_COMPARISON nds32_canonicalize_comparison
5102 
5103 /* -- Macros to control conditional execution.  */
5104 
5105 
5106 /* Describing Relative Costs of Operations.  */
5107 
5108 #undef TARGET_REGISTER_MOVE_COST
5109 #define TARGET_REGISTER_MOVE_COST nds32_register_move_cost
5110 
5111 #undef TARGET_MEMORY_MOVE_COST
5112 #define TARGET_MEMORY_MOVE_COST nds32_memory_move_cost
5113 
5114 #undef TARGET_RTX_COSTS
5115 #define TARGET_RTX_COSTS nds32_rtx_costs
5116 
5117 #undef TARGET_ADDRESS_COST
5118 #define TARGET_ADDRESS_COST nds32_address_cost
5119 
5120 
5121 /* Adjusting the Instruction Scheduler.  */
5122 
5123 
5124 /* Dividing the Output into Sections (Texts, Data, . . . ).  */
5125 
5126 #undef TARGET_ENCODE_SECTION_INFO
5127 #define TARGET_ENCODE_SECTION_INFO nds32_encode_section_info
5128 
5129 
5130 /* Position Independent Code.  */
5131 
5132 
5133 /* Defining the Output Assembler Language.  */
5134 
5135 /* -- The Overall Framework of an Assembler File.  */
5136 
5137 #undef TARGET_ASM_FILE_START
5138 #define TARGET_ASM_FILE_START nds32_asm_file_start
5139 #undef TARGET_ASM_FILE_END
5140 #define TARGET_ASM_FILE_END nds32_asm_file_end
5141 
5142 /* -- Output of Data.  */
5143 
5144 #undef TARGET_ASM_ALIGNED_HI_OP
5145 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
5146 
5147 #undef TARGET_ASM_ALIGNED_SI_OP
5148 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
5149 
5150 /* -- Output of Uninitialized Variables.  */
5151 
5152 /* -- Output and Generation of Labels.  */
5153 
5154 #undef TARGET_ASM_GLOBALIZE_LABEL
5155 #define TARGET_ASM_GLOBALIZE_LABEL nds32_asm_globalize_label
5156 
5157 /* -- How Initialization Functions Are Handled.  */
5158 
5159 /* -- Macros Controlling Initialization Routines.  */
5160 
5161 /* -- Output of Assembler Instructions.  */
5162 
5163 #undef TARGET_PRINT_OPERAND
5164 #define TARGET_PRINT_OPERAND nds32_print_operand
5165 #undef TARGET_PRINT_OPERAND_ADDRESS
5166 #define TARGET_PRINT_OPERAND_ADDRESS nds32_print_operand_address
5167 
5168 /* -- Output of Dispatch Tables.  */
5169 
5170 /* -- Assembler Commands for Exception Regions.  */
5171 
5172 #undef TARGET_DWARF_REGISTER_SPAN
5173 #define TARGET_DWARF_REGISTER_SPAN nds32_dwarf_register_span
5174 
5175 /* -- Assembler Commands for Alignment.  */
5176 
5177 
5178 /* Controlling Debugging Information Format.  */
5179 
5180 /* -- Macros Affecting All Debugging Formats.  */
5181 
5182 /* -- Specific Options for DBX Output.  */
5183 
5184 /* -- Open-Ended Hooks for DBX Format.  */
5185 
5186 /* -- File Names in DBX Format.  */
5187 
5188 /* -- Macros for DWARF Output.  */
5189 
5190 /* -- Macros for VMS Debug Format.  */
5191 
5192 
5193 /* Cross Compilation and Floating Point.  */
5194 
5195 
5196 /* Mode Switching Instructions.  */
5197 
5198 
5199 /* Defining target-specific uses of __attribute__.  */
5200 
5201 #undef TARGET_ATTRIBUTE_TABLE
5202 #define TARGET_ATTRIBUTE_TABLE nds32_attribute_table
5203 
5204 #undef TARGET_MERGE_DECL_ATTRIBUTES
5205 #define TARGET_MERGE_DECL_ATTRIBUTES nds32_merge_decl_attributes
5206 
5207 #undef TARGET_INSERT_ATTRIBUTES
5208 #define TARGET_INSERT_ATTRIBUTES nds32_insert_attributes
5209 
5210 #undef TARGET_OPTION_PRAGMA_PARSE
5211 #define TARGET_OPTION_PRAGMA_PARSE nds32_option_pragma_parse
5212 
5213 #undef TARGET_OPTION_OVERRIDE
5214 #define TARGET_OPTION_OVERRIDE nds32_option_override
5215 
5216 
5217 /* Emulating TLS.  */
5218 
5219 
5220 /* Defining coprocessor specifics for MIPS targets.  */
5221 
5222 
5223 /* Parameters for Precompiled Header Validity Checking.  */
5224 
5225 
5226 /* C++ ABI parameters.  */
5227 
5228 
5229 /* Adding support for named address spaces.  */
5230 
5231 
5232 /* Miscellaneous Parameters.  */
5233 
5234 #undef TARGET_MD_ASM_ADJUST
5235 #define TARGET_MD_ASM_ADJUST nds32_md_asm_adjust
5236 
5237 #undef TARGET_INIT_BUILTINS
5238 #define TARGET_INIT_BUILTINS nds32_init_builtins
5239 
5240 #undef  TARGET_BUILTIN_DECL
5241 #define TARGET_BUILTIN_DECL nds32_builtin_decl
5242 
5243 #undef TARGET_EXPAND_BUILTIN
5244 #define TARGET_EXPAND_BUILTIN nds32_expand_builtin
5245 
5246 
5247 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
5248 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P nds32_use_blocks_for_constant_p
5249 
5250 
5251 /* ------------------------------------------------------------------------ */
5252 
5253 /* Initialize the GCC target structure.  */
5254 
5255 struct gcc_target targetm = TARGET_INITIALIZER;
5256 
5257 /* ------------------------------------------------------------------------ */
5258