]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/nds32/nds32.c
use templates instead of gengtype for typed allocation functions
[thirdparty/gcc.git] / gcc / config / nds32 / nds32.c
1 /* Subroutines used for code generation of Andes NDS32 cpu for GNU compiler
2 Copyright (C) 2012-2014 Free Software Foundation, Inc.
3 Contributed by Andes Technology Corporation.
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 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "tree.h"
28 #include "stor-layout.h"
29 #include "varasm.h"
30 #include "calls.h"
31 #include "rtl.h"
32 #include "regs.h"
33 #include "hard-reg-set.h"
34 #include "insn-config.h" /* Required by recog.h. */
35 #include "conditions.h"
36 #include "output.h"
37 #include "insn-attr.h" /* For DFA state_t. */
38 #include "insn-codes.h" /* For CODE_FOR_xxx. */
39 #include "reload.h" /* For push_reload(). */
40 #include "flags.h"
41 #include "function.h"
42 #include "expr.h"
43 #include "recog.h"
44 #include "diagnostic-core.h"
45 #include "df.h"
46 #include "tm_p.h"
47 #include "tm-constrs.h"
48 #include "optabs.h" /* For GEN_FCN. */
49 #include "target.h"
50 #include "target-def.h"
51 #include "langhooks.h" /* For add_builtin_function(). */
52 #include "ggc.h"
53
54 /* ------------------------------------------------------------------------ */
55
56 /* This file is divided into five parts:
57
58 PART 1: Auxiliary static variable definitions and
59 target hook static variable definitions.
60
61 PART 2: Auxiliary static function definitions.
62
63 PART 3: Implement target hook stuff definitions.
64
65 PART 4: Implemet extern function definitions,
66 the prototype is in nds32-protos.h.
67
68 PART 5: Initialize target hook structure and definitions. */
69
70 /* ------------------------------------------------------------------------ */
71
72 /* PART 1: Auxiliary static variable definitions and
73 target hook static variable definitions. */
74
75 /* Refer to nds32.h, there are maximum 73 isr vectors in nds32 architecture.
76 0 for reset handler with __attribute__((reset())),
77 1-8 for exception handler with __attribute__((exception(1,...,8))),
78 and 9-72 for interrupt handler with __attribute__((interrupt(0,...,63))).
79 We use an array to record essential information for each vector. */
80 static struct nds32_isr_info nds32_isr_vectors[NDS32_N_ISR_VECTORS];
81
82 /* Define intrinsic register names.
83 Please refer to nds32_intrinsic.h file, the index is corresponding to
84 'enum nds32_intrinsic_registers' data type values.
85 NOTE that the base value starting from 1024. */
86 static const char * const nds32_intrinsic_register_names[] =
87 {
88 "$PSW", "$IPSW", "$ITYPE", "$IPC"
89 };
90
91 /* Defining target-specific uses of __attribute__. */
92 static const struct attribute_spec nds32_attribute_table[] =
93 {
94 /* Syntax: { name, min_len, max_len, decl_required, type_required,
95 function_type_required, handler, affects_type_identity } */
96
97 /* The interrupt vid: [0-63]+ (actual vector number starts from 9 to 72). */
98 { "interrupt", 1, 64, false, false, false, NULL, false },
99 /* The exception vid: [1-8]+ (actual vector number starts from 1 to 8). */
100 { "exception", 1, 8, false, false, false, NULL, false },
101 /* Argument is user's interrupt numbers. The vector number is always 0. */
102 { "reset", 1, 1, false, false, false, NULL, false },
103
104 /* The attributes describing isr nested type. */
105 { "nested", 0, 0, false, false, false, NULL, false },
106 { "not_nested", 0, 0, false, false, false, NULL, false },
107 { "nested_ready", 0, 0, false, false, false, NULL, false },
108
109 /* The attributes describing isr register save scheme. */
110 { "save_all", 0, 0, false, false, false, NULL, false },
111 { "partial_save", 0, 0, false, false, false, NULL, false },
112
113 /* The attributes used by reset attribute. */
114 { "nmi", 1, 1, false, false, false, NULL, false },
115 { "warm", 1, 1, false, false, false, NULL, false },
116
117 /* The attribute telling no prologue/epilogue. */
118 { "naked", 0, 0, false, false, false, NULL, false },
119
120 /* The last attribute spec is set to be NULL. */
121 { NULL, 0, 0, false, false, false, NULL, false }
122 };
123
124
125 /* ------------------------------------------------------------------------ */
126
127 /* PART 2: Auxiliary static function definitions. */
128
129 /* Function to save and restore machine-specific function data. */
130 static struct machine_function *
131 nds32_init_machine_status (void)
132 {
133 struct machine_function *machine;
134 machine = ggc_cleared_alloc<machine_function> ();
135
136 /* Initially assume this function needs prologue/epilogue. */
137 machine->naked_p = 0;
138
139 /* Initially assume this function does NOT use fp_as_gp optimization. */
140 machine->fp_as_gp_p = 0;
141
142 return machine;
143 }
144
145 /* Function to compute stack frame size and
146 store into cfun->machine structure. */
147 static void
148 nds32_compute_stack_frame (void)
149 {
150 int r;
151 int block_size;
152
153 /* Because nds32_compute_stack_frame() will be called from different place,
154 everytime we enter this function, we have to assume this function
155 needs prologue/epilogue. */
156 cfun->machine->naked_p = 0;
157
158 /* Get variadic arguments size to prepare pretend arguments and
159 push them into stack at prologue.
160 Currently, we do not push variadic arguments by ourself.
161 We have GCC handle all the works.
162 The caller will push all corresponding nameless arguments into stack,
163 and the callee is able to retrieve them without problems.
164 These variables are still preserved in case one day
165 we would like caller passing arguments with registers. */
166 cfun->machine->va_args_size = 0;
167 cfun->machine->va_args_first_regno = SP_REGNUM;
168 cfun->machine->va_args_last_regno = SP_REGNUM;
169
170 /* Get local variables, incoming variables, and temporary variables size.
171 Note that we need to make sure it is 8-byte alignment because
172 there may be no padding bytes if we are using LRA. */
173 cfun->machine->local_size = NDS32_ROUND_UP_DOUBLE_WORD (get_frame_size ());
174
175 /* Get outgoing arguments size. */
176 cfun->machine->out_args_size = crtl->outgoing_args_size;
177
178 /* If $fp value is required to be saved on stack, it needs 4 bytes space.
179 Check whether $fp is ever live. */
180 cfun->machine->fp_size = (df_regs_ever_live_p (FP_REGNUM)) ? 4 : 0;
181
182 /* If $gp value is required to be saved on stack, it needs 4 bytes space.
183 Check whether we are using PIC code genration. */
184 cfun->machine->gp_size = (flag_pic) ? 4 : 0;
185
186 /* If $lp value is required to be saved on stack, it needs 4 bytes space.
187 Check whether $lp is ever live. */
188 cfun->machine->lp_size = (df_regs_ever_live_p (LP_REGNUM)) ? 4 : 0;
189
190 /* Initially there is no padding bytes. */
191 cfun->machine->callee_saved_area_padding_bytes = 0;
192
193 /* Calculate the bytes of saving callee-saved registers on stack. */
194 cfun->machine->callee_saved_regs_size = 0;
195 cfun->machine->callee_saved_regs_first_regno = SP_REGNUM;
196 cfun->machine->callee_saved_regs_last_regno = SP_REGNUM;
197 /* Currently, there is no need to check $r28~$r31
198 because we will save them in another way. */
199 for (r = 0; r < 28; r++)
200 {
201 if (NDS32_REQUIRED_CALLEE_SAVED_P (r))
202 {
203 /* Mark the first required callee-saved register
204 (only need to set it once).
205 If first regno == SP_REGNUM, we can tell that
206 it is the first time to be here. */
207 if (cfun->machine->callee_saved_regs_first_regno == SP_REGNUM)
208 cfun->machine->callee_saved_regs_first_regno = r;
209 /* Mark the last required callee-saved register. */
210 cfun->machine->callee_saved_regs_last_regno = r;
211 }
212 }
213
214 /* Check if this function can omit prologue/epilogue code fragment.
215 If there is 'naked' attribute in this function,
216 we can set 'naked_p' flag to indicate that
217 we do not have to generate prologue/epilogue.
218 Or, if all the following conditions succeed,
219 we can set this function 'naked_p' as well:
220 condition 1: first_regno == last_regno == SP_REGNUM,
221 which means we do not have to save
222 any callee-saved registers.
223 condition 2: Both $lp and $fp are NOT live in this function,
224 which means we do not need to save them.
225 condition 3: There is no local_size, which means
226 we do not need to adjust $sp. */
227 if (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))
228 || (cfun->machine->callee_saved_regs_first_regno == SP_REGNUM
229 && cfun->machine->callee_saved_regs_last_regno == SP_REGNUM
230 && !df_regs_ever_live_p (FP_REGNUM)
231 && !df_regs_ever_live_p (LP_REGNUM)
232 && cfun->machine->local_size == 0))
233 {
234 /* Set this function 'naked_p' and
235 other functions can check this flag. */
236 cfun->machine->naked_p = 1;
237
238 /* No need to save $fp, $gp, and $lp.
239 We should set these value to be zero
240 so that nds32_initial_elimination_offset() can work properly. */
241 cfun->machine->fp_size = 0;
242 cfun->machine->gp_size = 0;
243 cfun->machine->lp_size = 0;
244
245 /* If stack usage computation is required,
246 we need to provide the static stack size. */
247 if (flag_stack_usage_info)
248 current_function_static_stack_size = 0;
249
250 /* No need to do following adjustment, return immediately. */
251 return;
252 }
253
254 /* Adjustment for v3push instructions:
255 If we are using v3push (push25/pop25) instructions,
256 we need to make sure Rb is $r6 and Re is
257 located on $r6, $r8, $r10, or $r14.
258 Some results above will be discarded and recomputed.
259 Note that it is only available under V3/V3M ISA. */
260 if (TARGET_V3PUSH)
261 {
262 /* Recompute:
263 cfun->machine->fp_size
264 cfun->machine->gp_size
265 cfun->machine->lp_size
266 cfun->machine->callee_saved_regs_first_regno
267 cfun->machine->callee_saved_regs_last_regno */
268
269 /* For v3push instructions, $fp, $gp, and $lp are always saved. */
270 cfun->machine->fp_size = 4;
271 cfun->machine->gp_size = 4;
272 cfun->machine->lp_size = 4;
273
274 /* Remember to set Rb = $r6. */
275 cfun->machine->callee_saved_regs_first_regno = 6;
276
277 if (cfun->machine->callee_saved_regs_last_regno <= 6)
278 {
279 /* Re = $r6 */
280 cfun->machine->callee_saved_regs_last_regno = 6;
281 }
282 else if (cfun->machine->callee_saved_regs_last_regno <= 8)
283 {
284 /* Re = $r8 */
285 cfun->machine->callee_saved_regs_last_regno = 8;
286 }
287 else if (cfun->machine->callee_saved_regs_last_regno <= 10)
288 {
289 /* Re = $r10 */
290 cfun->machine->callee_saved_regs_last_regno = 10;
291 }
292 else if (cfun->machine->callee_saved_regs_last_regno <= 14)
293 {
294 /* Re = $r14 */
295 cfun->machine->callee_saved_regs_last_regno = 14;
296 }
297 else if (cfun->machine->callee_saved_regs_last_regno == SP_REGNUM)
298 {
299 /* If last_regno is SP_REGNUM, which means
300 it is never changed, so set it to Re = $r6. */
301 cfun->machine->callee_saved_regs_last_regno = 6;
302 }
303 else
304 {
305 /* The program flow should not go here. */
306 gcc_unreachable ();
307 }
308 }
309
310 /* We have correctly set callee_saved_regs_first_regno
311 and callee_saved_regs_last_regno.
312 Initially, the callee_saved_regs_size is supposed to be 0.
313 As long as callee_saved_regs_last_regno is not SP_REGNUM,
314 we can update callee_saved_regs_size with new size. */
315 if (cfun->machine->callee_saved_regs_last_regno != SP_REGNUM)
316 {
317 /* Compute pushed size of callee-saved registers. */
318 cfun->machine->callee_saved_regs_size
319 = 4 * (cfun->machine->callee_saved_regs_last_regno
320 - cfun->machine->callee_saved_regs_first_regno
321 + 1);
322 }
323
324 /* Important: We need to make sure that
325 (va_args_size + fp_size + gp_size
326 + lp_size + callee_saved_regs_size)
327 is 8-byte alignment.
328 If it is not, calculate the padding bytes. */
329 block_size = cfun->machine->va_args_size
330 + cfun->machine->fp_size
331 + cfun->machine->gp_size
332 + cfun->machine->lp_size
333 + cfun->machine->callee_saved_regs_size;
334 if (!NDS32_DOUBLE_WORD_ALIGN_P (block_size))
335 {
336 cfun->machine->callee_saved_area_padding_bytes
337 = NDS32_ROUND_UP_DOUBLE_WORD (block_size) - block_size;
338 }
339
340 /* If stack usage computation is required,
341 we need to provide the static stack size. */
342 if (flag_stack_usage_info)
343 {
344 current_function_static_stack_size
345 = NDS32_ROUND_UP_DOUBLE_WORD (block_size)
346 + cfun->machine->local_size
347 + cfun->machine->out_args_size;
348 }
349 }
350
351 /* Function to create a parallel rtx pattern
352 which presents stack push multiple behavior.
353 The overall concept are:
354 "push registers to memory",
355 "adjust stack pointer". */
356 static rtx
357 nds32_gen_stack_push_multiple (rtx Rb, rtx Re,
358 rtx En4 ATTRIBUTE_UNUSED)
359 {
360 int regno;
361 int extra_count;
362 int num_use_regs;
363 int par_index;
364 int offset;
365
366 rtx reg;
367 rtx mem;
368 rtx push_rtx;
369 rtx adjust_sp_rtx;
370 rtx parallel_insn;
371
372 /* We need to provide a customized rtx which contains
373 necessary information for data analysis,
374 so we create a parallel rtx like this:
375 (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
376 (reg:SI Rb))
377 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
378 (reg:SI Rb+1))
379 ...
380 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
381 (reg:SI Re))
382 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
383 (reg:SI FP_REGNUM))
384 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
385 (reg:SI GP_REGNUM))
386 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
387 (reg:SI LP_REGNUM))
388 (set (reg:SI SP_REGNUM)
389 (plus (reg:SI SP_REGNUM) (const_int -32)))]) */
390
391 /* Calculate the number of registers that will be pushed. */
392 extra_count = 0;
393 if (cfun->machine->fp_size)
394 extra_count++;
395 if (cfun->machine->gp_size)
396 extra_count++;
397 if (cfun->machine->lp_size)
398 extra_count++;
399 /* Note that Rb and Re may be SP_REGNUM. DO NOT count it in. */
400 if (REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM)
401 num_use_regs = extra_count;
402 else
403 num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + extra_count;
404
405 /* In addition to used registers,
406 we need one more space for (set sp sp-x) rtx. */
407 parallel_insn = gen_rtx_PARALLEL (VOIDmode,
408 rtvec_alloc (num_use_regs + 1));
409 par_index = 0;
410
411 /* Initialize offset and start to create push behavior. */
412 offset = -(num_use_regs * 4);
413
414 /* Create (set mem regX) from Rb, Rb+1 up to Re. */
415 for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++)
416 {
417 /* Rb and Re may be SP_REGNUM.
418 We need to break this loop immediately. */
419 if (regno == SP_REGNUM)
420 break;
421
422 reg = gen_rtx_REG (SImode, regno);
423 mem = gen_frame_mem (SImode, plus_constant (Pmode,
424 stack_pointer_rtx,
425 offset));
426 push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
427 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
428 RTX_FRAME_RELATED_P (push_rtx) = 1;
429 offset = offset + 4;
430 par_index++;
431 }
432
433 /* Create (set mem fp), (set mem gp), and (set mem lp) if necessary. */
434 if (cfun->machine->fp_size)
435 {
436 reg = gen_rtx_REG (SImode, FP_REGNUM);
437 mem = gen_frame_mem (SImode, plus_constant (Pmode,
438 stack_pointer_rtx,
439 offset));
440 push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
441 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
442 RTX_FRAME_RELATED_P (push_rtx) = 1;
443 offset = offset + 4;
444 par_index++;
445 }
446 if (cfun->machine->gp_size)
447 {
448 reg = gen_rtx_REG (SImode, GP_REGNUM);
449 mem = gen_frame_mem (SImode, plus_constant (Pmode,
450 stack_pointer_rtx,
451 offset));
452 push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
453 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
454 RTX_FRAME_RELATED_P (push_rtx) = 1;
455 offset = offset + 4;
456 par_index++;
457 }
458 if (cfun->machine->lp_size)
459 {
460 reg = gen_rtx_REG (SImode, LP_REGNUM);
461 mem = gen_frame_mem (SImode, plus_constant (Pmode,
462 stack_pointer_rtx,
463 offset));
464 push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
465 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
466 RTX_FRAME_RELATED_P (push_rtx) = 1;
467 offset = offset + 4;
468 par_index++;
469 }
470
471 /* Create (set sp sp-x). */
472
473 /* We need to re-calculate the offset value again for adjustment. */
474 offset = -(num_use_regs * 4);
475 adjust_sp_rtx
476 = gen_rtx_SET (VOIDmode,
477 stack_pointer_rtx,
478 plus_constant (Pmode, stack_pointer_rtx, offset));
479 XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
480 RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1;
481
482 return parallel_insn;
483 }
484
485 /* Function to create a parallel rtx pattern
486 which presents stack pop multiple behavior.
487 The overall concept are:
488 "pop registers from memory",
489 "adjust stack pointer". */
490 static rtx
491 nds32_gen_stack_pop_multiple (rtx Rb, rtx Re,
492 rtx En4 ATTRIBUTE_UNUSED)
493 {
494 int regno;
495 int extra_count;
496 int num_use_regs;
497 int par_index;
498 int offset;
499
500 rtx reg;
501 rtx mem;
502 rtx pop_rtx;
503 rtx adjust_sp_rtx;
504 rtx parallel_insn;
505
506 /* We need to provide a customized rtx which contains
507 necessary information for data analysis,
508 so we create a parallel rtx like this:
509 (parallel [(set (reg:SI Rb)
510 (mem (reg:SI SP_REGNUM)))
511 (set (reg:SI Rb+1)
512 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
513 ...
514 (set (reg:SI Re)
515 (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
516 (set (reg:SI FP_REGNUM)
517 (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
518 (set (reg:SI GP_REGNUM)
519 (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
520 (set (reg:SI LP_REGNUM)
521 (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
522 (set (reg:SI SP_REGNUM)
523 (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
524
525 /* Calculate the number of registers that will be poped. */
526 extra_count = 0;
527 if (cfun->machine->fp_size)
528 extra_count++;
529 if (cfun->machine->gp_size)
530 extra_count++;
531 if (cfun->machine->lp_size)
532 extra_count++;
533 /* Note that Rb and Re may be SP_REGNUM. DO NOT count it in. */
534 if (REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM)
535 num_use_regs = extra_count;
536 else
537 num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + extra_count;
538
539 /* In addition to used registers,
540 we need one more space for (set sp sp+x) rtx. */
541 parallel_insn = gen_rtx_PARALLEL (VOIDmode,
542 rtvec_alloc (num_use_regs + 1));
543 par_index = 0;
544
545 /* Initialize offset and start to create pop behavior. */
546 offset = 0;
547
548 /* Create (set regX mem) from Rb, Rb+1 up to Re. */
549 for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++)
550 {
551 /* Rb and Re may be SP_REGNUM.
552 We need to break this loop immediately. */
553 if (regno == SP_REGNUM)
554 break;
555
556 reg = gen_rtx_REG (SImode, regno);
557 mem = gen_frame_mem (SImode, plus_constant (Pmode,
558 stack_pointer_rtx,
559 offset));
560 pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
561 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
562 RTX_FRAME_RELATED_P (pop_rtx) = 1;
563 offset = offset + 4;
564 par_index++;
565 }
566
567 /* Create (set fp mem), (set gp mem), and (set lp mem) if necessary. */
568 if (cfun->machine->fp_size)
569 {
570 reg = gen_rtx_REG (SImode, FP_REGNUM);
571 mem = gen_frame_mem (SImode, plus_constant (Pmode,
572 stack_pointer_rtx,
573 offset));
574 pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
575 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
576 RTX_FRAME_RELATED_P (pop_rtx) = 1;
577 offset = offset + 4;
578 par_index++;
579 }
580 if (cfun->machine->gp_size)
581 {
582 reg = gen_rtx_REG (SImode, GP_REGNUM);
583 mem = gen_frame_mem (SImode, plus_constant (Pmode,
584 stack_pointer_rtx,
585 offset));
586 pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
587 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
588 RTX_FRAME_RELATED_P (pop_rtx) = 1;
589 offset = offset + 4;
590 par_index++;
591 }
592 if (cfun->machine->lp_size)
593 {
594 reg = gen_rtx_REG (SImode, LP_REGNUM);
595 mem = gen_frame_mem (SImode, plus_constant (Pmode,
596 stack_pointer_rtx,
597 offset));
598 pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
599 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
600 RTX_FRAME_RELATED_P (pop_rtx) = 1;
601 offset = offset + 4;
602 par_index++;
603 }
604
605 /* Create (set sp sp+x). */
606
607 /* The offset value is already in place. No need to re-calculate it. */
608 adjust_sp_rtx
609 = gen_rtx_SET (VOIDmode,
610 stack_pointer_rtx,
611 plus_constant (Pmode, stack_pointer_rtx, offset));
612 XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
613 RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1;
614
615 return parallel_insn;
616 }
617
618 /* Function to create a parallel rtx pattern
619 which presents stack v3push behavior.
620 The overall concept are:
621 "push registers to memory",
622 "adjust stack pointer". */
623 static rtx
624 nds32_gen_stack_v3push (rtx Rb,
625 rtx Re,
626 rtx En4 ATTRIBUTE_UNUSED,
627 rtx imm8u)
628 {
629 int regno;
630 int num_use_regs;
631 int par_index;
632 int offset;
633
634 rtx reg;
635 rtx mem;
636 rtx push_rtx;
637 rtx adjust_sp_rtx;
638 rtx parallel_insn;
639
640 /* We need to provide a customized rtx which contains
641 necessary information for data analysis,
642 so we create a parallel rtx like this:
643 (parallel [
644 (set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
645 (reg:SI Rb))
646 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
647 (reg:SI Rb+1))
648 ...
649 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
650 (reg:SI Re))
651 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
652 (reg:SI FP_REGNUM))
653 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
654 (reg:SI GP_REGNUM))
655 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
656 (reg:SI LP_REGNUM))
657 (set (reg:SI SP_REGNUM)
658 (plus (reg:SI SP_REGNUM) (const_int -32-imm8u)))]) */
659
660 /* Calculate the number of registers that will be pushed.
661 Since $fp, $gp, and $lp is always pushed with v3push instruction,
662 we need to count these three registers.
663 Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
664 So there is no need to worry about Rb=Re=SP_REGNUM case. */
665 num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + 3;
666
667 /* In addition to used registers,
668 we need one more space for (set sp sp-x-imm8u) rtx. */
669 parallel_insn = gen_rtx_PARALLEL (VOIDmode,
670 rtvec_alloc (num_use_regs + 1));
671 par_index = 0;
672
673 /* Initialize offset and start to create push behavior. */
674 offset = -(num_use_regs * 4);
675
676 /* Create (set mem regX) from Rb, Rb+1 up to Re.
677 Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
678 So there is no need to worry about Rb=Re=SP_REGNUM case. */
679 for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++)
680 {
681 reg = gen_rtx_REG (SImode, regno);
682 mem = gen_frame_mem (SImode, plus_constant (Pmode,
683 stack_pointer_rtx,
684 offset));
685 push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
686 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
687 RTX_FRAME_RELATED_P (push_rtx) = 1;
688 offset = offset + 4;
689 par_index++;
690 }
691
692 /* Create (set mem fp). */
693 reg = gen_rtx_REG (SImode, FP_REGNUM);
694 mem = gen_frame_mem (SImode, plus_constant (Pmode,
695 stack_pointer_rtx,
696 offset));
697 push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
698 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
699 RTX_FRAME_RELATED_P (push_rtx) = 1;
700 offset = offset + 4;
701 par_index++;
702 /* Create (set mem gp). */
703 reg = gen_rtx_REG (SImode, GP_REGNUM);
704 mem = gen_frame_mem (SImode, plus_constant (Pmode,
705 stack_pointer_rtx,
706 offset));
707 push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
708 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
709 RTX_FRAME_RELATED_P (push_rtx) = 1;
710 offset = offset + 4;
711 par_index++;
712 /* Create (set mem lp). */
713 reg = gen_rtx_REG (SImode, LP_REGNUM);
714 mem = gen_frame_mem (SImode, plus_constant (Pmode,
715 stack_pointer_rtx,
716 offset));
717 push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
718 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
719 RTX_FRAME_RELATED_P (push_rtx) = 1;
720 offset = offset + 4;
721 par_index++;
722
723 /* Create (set sp sp-x-imm8u). */
724
725 /* We need to re-calculate the offset value again for adjustment. */
726 offset = -(num_use_regs * 4);
727 adjust_sp_rtx
728 = gen_rtx_SET (VOIDmode,
729 stack_pointer_rtx,
730 plus_constant (Pmode,
731 stack_pointer_rtx,
732 offset - INTVAL (imm8u)));
733 XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
734 RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1;
735
736 return parallel_insn;
737 }
738
739 /* Function to create a parallel rtx pattern
740 which presents stack v3pop behavior.
741 The overall concept are:
742 "pop registers from memory",
743 "adjust stack pointer". */
744 static rtx
745 nds32_gen_stack_v3pop (rtx Rb,
746 rtx Re,
747 rtx En4 ATTRIBUTE_UNUSED,
748 rtx imm8u)
749 {
750 int regno;
751 int num_use_regs;
752 int par_index;
753 int offset;
754
755 rtx reg;
756 rtx mem;
757 rtx pop_rtx;
758 rtx adjust_sp_rtx;
759 rtx parallel_insn;
760
761 /* We need to provide a customized rtx which contains
762 necessary information for data analysis,
763 so we create a parallel rtx like this:
764 (parallel [(set (reg:SI Rb)
765 (mem (reg:SI SP_REGNUM)))
766 (set (reg:SI Rb+1)
767 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
768 ...
769 (set (reg:SI Re)
770 (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
771 (set (reg:SI FP_REGNUM)
772 (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
773 (set (reg:SI GP_REGNUM)
774 (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
775 (set (reg:SI LP_REGNUM)
776 (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
777 (set (reg:SI SP_REGNUM)
778 (plus (reg:SI SP_REGNUM) (const_int 32+imm8u)))]) */
779
780 /* Calculate the number of registers that will be poped.
781 Since $fp, $gp, and $lp is always poped with v3pop instruction,
782 we need to count these three registers.
783 Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
784 So there is no need to worry about Rb=Re=SP_REGNUM case. */
785 num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + 3;
786
787 /* In addition to used registers,
788 we need one more space for (set sp sp+x+imm8u) rtx. */
789 parallel_insn = gen_rtx_PARALLEL (VOIDmode,
790 rtvec_alloc (num_use_regs + 1));
791 par_index = 0;
792
793 /* Initialize offset and start to create pop behavior. */
794 offset = 0;
795
796 /* Create (set regX mem) from Rb, Rb+1 up to Re.
797 Under v3pop, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
798 So there is no need to worry about Rb=Re=SP_REGNUM case. */
799 for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++)
800 {
801 reg = gen_rtx_REG (SImode, regno);
802 mem = gen_frame_mem (SImode, plus_constant (Pmode,
803 stack_pointer_rtx,
804 offset));
805 pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
806 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
807 RTX_FRAME_RELATED_P (pop_rtx) = 1;
808 offset = offset + 4;
809 par_index++;
810 }
811
812 /* Create (set fp mem). */
813 reg = gen_rtx_REG (SImode, FP_REGNUM);
814 mem = gen_frame_mem (SImode, plus_constant (Pmode,
815 stack_pointer_rtx,
816 offset));
817 pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
818 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
819 RTX_FRAME_RELATED_P (pop_rtx) = 1;
820 offset = offset + 4;
821 par_index++;
822 /* Create (set gp mem). */
823 reg = gen_rtx_REG (SImode, GP_REGNUM);
824 mem = gen_frame_mem (SImode, plus_constant (Pmode,
825 stack_pointer_rtx,
826 offset));
827 pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
828 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
829 RTX_FRAME_RELATED_P (pop_rtx) = 1;
830 offset = offset + 4;
831 par_index++;
832 /* Create (set lp mem ). */
833 reg = gen_rtx_REG (SImode, LP_REGNUM);
834 mem = gen_frame_mem (SImode, plus_constant (Pmode,
835 stack_pointer_rtx,
836 offset));
837 pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
838 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
839 RTX_FRAME_RELATED_P (pop_rtx) = 1;
840 offset = offset + 4;
841 par_index++;
842
843 /* Create (set sp sp+x+imm8u). */
844
845 /* The offset value is already in place. No need to re-calculate it. */
846 adjust_sp_rtx
847 = gen_rtx_SET (VOIDmode,
848 stack_pointer_rtx,
849 plus_constant (Pmode,
850 stack_pointer_rtx,
851 offset + INTVAL (imm8u)));
852 XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
853 RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1;
854
855 return parallel_insn;
856 }
857
858 /* A subroutine that checks multiple load and store
859 using consecutive registers.
860 OP is a parallel rtx we would like to check.
861 LOAD_P indicates whether we are checking load operation.
862 PAR_INDEX is starting element of parallel rtx.
863 FIRST_ELT_REGNO is used to tell starting register number.
864 COUNT helps us to check consecutive register numbers. */
865 static bool
866 nds32_consecutive_registers_load_store_p (rtx op,
867 bool load_p,
868 int par_index,
869 int first_elt_regno,
870 int count)
871 {
872 int i;
873 int check_regno;
874 rtx elt;
875 rtx elt_reg;
876 rtx elt_mem;
877
878 for (i = 0; i < count; i++)
879 {
880 /* Pick up each element from parallel rtx. */
881 elt = XVECEXP (op, 0, i + par_index);
882
883 /* If this element is not a 'set' rtx, return false immediately. */
884 if (GET_CODE (elt) != SET)
885 return false;
886
887 /* Pick up reg and mem of this element. */
888 elt_reg = load_p ? SET_DEST (elt) : SET_SRC (elt);
889 elt_mem = load_p ? SET_SRC (elt) : SET_DEST (elt);
890
891 /* If elt_reg is not a expected reg rtx, return false. */
892 if (GET_CODE (elt_reg) != REG || GET_MODE (elt_reg) != SImode)
893 return false;
894 /* If elt_mem is not a expected mem rtx, return false. */
895 if (GET_CODE (elt_mem) != MEM || GET_MODE (elt_mem) != SImode)
896 return false;
897
898 /* The consecutive registers should be in (Rb,Rb+1...Re) order. */
899 check_regno = first_elt_regno + i;
900
901 /* If the register number is not continuous, return false. */
902 if (REGNO (elt_reg) != (unsigned int) check_regno)
903 return false;
904 }
905
906 return true;
907 }
908
909 /* A helper function to emit section head template. */
910 static void
911 nds32_emit_section_head_template (char section_name[],
912 char symbol_name[],
913 int align_value,
914 bool object_p)
915 {
916 const char *flags_str;
917 const char *type_str;
918
919 flags_str = (object_p) ? "\"a\"" : "\"ax\"";
920 type_str = (object_p) ? "@object" : "@function";
921
922 fprintf (asm_out_file, "\t.section\t%s, %s\n", section_name, flags_str);
923 fprintf (asm_out_file, "\t.align\t%d\n", align_value);
924 fprintf (asm_out_file, "\t.global\t%s\n", symbol_name);
925 fprintf (asm_out_file, "\t.type\t%s, %s\n", symbol_name, type_str);
926 fprintf (asm_out_file, "%s:\n", symbol_name);
927 }
928
929 /* A helper function to emit section tail template. */
930 static void
931 nds32_emit_section_tail_template (char symbol_name[])
932 {
933 fprintf (asm_out_file, "\t.size\t%s, .-%s\n", symbol_name, symbol_name);
934 }
935
936 /* Function to emit isr jump table section. */
937 static void
938 nds32_emit_isr_jmptbl_section (int vector_id)
939 {
940 char section_name[100];
941 char symbol_name[100];
942
943 /* Prepare jmptbl section and symbol name. */
944 snprintf (section_name, sizeof (section_name),
945 ".nds32_jmptbl.%02d", vector_id);
946 snprintf (symbol_name, sizeof (symbol_name),
947 "_nds32_jmptbl_%02d", vector_id);
948
949 nds32_emit_section_head_template (section_name, symbol_name, 2, true);
950 fprintf (asm_out_file, "\t.word\t%s\n",
951 nds32_isr_vectors[vector_id].func_name);
952 nds32_emit_section_tail_template (symbol_name);
953 }
954
955 /* Function to emit isr vector section. */
956 static void
957 nds32_emit_isr_vector_section (int vector_id)
958 {
959 unsigned int vector_number_offset = 0;
960 const char *c_str = "CATEGORY";
961 const char *sr_str = "SR";
962 const char *nt_str = "NT";
963 const char *vs_str = "VS";
964 char first_level_handler_name[100];
965 char section_name[100];
966 char symbol_name[100];
967
968 /* Set the vector number offset so that we can calculate
969 the value that user specifies in the attribute.
970 We also prepare the category string for first level handler name. */
971 switch (nds32_isr_vectors[vector_id].category)
972 {
973 case NDS32_ISR_INTERRUPT:
974 vector_number_offset = 9;
975 c_str = "i";
976 break;
977 case NDS32_ISR_EXCEPTION:
978 vector_number_offset = 0;
979 c_str = "e";
980 break;
981 case NDS32_ISR_NONE:
982 case NDS32_ISR_RESET:
983 /* Normally it should not be here. */
984 gcc_unreachable ();
985 break;
986 }
987
988 /* Prepare save reg string for first level handler name. */
989 switch (nds32_isr_vectors[vector_id].save_reg)
990 {
991 case NDS32_SAVE_ALL:
992 sr_str = "sa";
993 break;
994 case NDS32_PARTIAL_SAVE:
995 sr_str = "ps";
996 break;
997 }
998
999 /* Prepare nested type string for first level handler name. */
1000 switch (nds32_isr_vectors[vector_id].nested_type)
1001 {
1002 case NDS32_NESTED:
1003 nt_str = "ns";
1004 break;
1005 case NDS32_NOT_NESTED:
1006 nt_str = "nn";
1007 break;
1008 case NDS32_NESTED_READY:
1009 nt_str = "nr";
1010 break;
1011 }
1012
1013 /* Currently we have 4-byte or 16-byte size for each vector.
1014 If it is 4-byte, the first level handler name has suffix string "_4b". */
1015 vs_str = (nds32_isr_vector_size == 4) ? "_4b" : "";
1016
1017 /* Now we can create first level handler name. */
1018 snprintf (first_level_handler_name, sizeof (first_level_handler_name),
1019 "_nds32_%s_%s_%s%s", c_str, sr_str, nt_str, vs_str);
1020
1021 /* Prepare vector section and symbol name. */
1022 snprintf (section_name, sizeof (section_name),
1023 ".nds32_vector.%02d", vector_id);
1024 snprintf (symbol_name, sizeof (symbol_name),
1025 "_nds32_vector_%02d%s", vector_id, vs_str);
1026
1027
1028 /* Everything is ready. We can start emit vector section content. */
1029 nds32_emit_section_head_template (section_name, symbol_name,
1030 floor_log2 (nds32_isr_vector_size), false);
1031
1032 /* According to the vector size, the instructions in the
1033 vector section may be different. */
1034 if (nds32_isr_vector_size == 4)
1035 {
1036 /* This block is for 4-byte vector size.
1037 Hardware $VID support is necessary and only one instruction
1038 is needed in vector section. */
1039 fprintf (asm_out_file, "\tj\t%s ! jump to first level handler\n",
1040 first_level_handler_name);
1041 }
1042 else
1043 {
1044 /* This block is for 16-byte vector size.
1045 There is NO hardware $VID so that we need several instructions
1046 such as pushing GPRs and preparing software vid at vector section.
1047 For pushing GPRs, there are four variations for
1048 16-byte vector content and we have to handle each combination.
1049 For preparing software vid, note that the vid need to
1050 be substracted vector_number_offset. */
1051 if (TARGET_REDUCED_REGS)
1052 {
1053 if (nds32_isr_vectors[vector_id].save_reg == NDS32_SAVE_ALL)
1054 {
1055 /* Case of reduced set registers and save_all attribute. */
1056 fprintf (asm_out_file, "\t! reduced set regs + save_all\n");
1057 fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r15, 0xf\n");
1058 fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r10, 0x0\n");
1059
1060 }
1061 else
1062 {
1063 /* Case of reduced set registers and partial_save attribute. */
1064 fprintf (asm_out_file, "\t! reduced set regs + partial_save\n");
1065 fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r15, 0x2\n");
1066 fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r5, 0x0\n");
1067 }
1068 }
1069 else
1070 {
1071 if (nds32_isr_vectors[vector_id].save_reg == NDS32_SAVE_ALL)
1072 {
1073 /* Case of full set registers and save_all attribute. */
1074 fprintf (asm_out_file, "\t! full set regs + save_all\n");
1075 fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r27, 0xf\n");
1076 }
1077 else
1078 {
1079 /* Case of full set registers and partial_save attribute. */
1080 fprintf (asm_out_file, "\t! full set regs + partial_save\n");
1081 fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r27, 0x2\n");
1082 fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r5, 0x0\n");
1083 }
1084 }
1085
1086 fprintf (asm_out_file, "\tmovi\t$r0, %d ! preparing software vid\n",
1087 vector_id - vector_number_offset);
1088 fprintf (asm_out_file, "\tj\t%s ! jump to first level handler\n",
1089 first_level_handler_name);
1090 }
1091
1092 nds32_emit_section_tail_template (symbol_name);
1093 }
1094
1095 /* Function to emit isr reset handler content.
1096 Including all jmptbl/vector references, jmptbl section,
1097 vector section, nmi handler section, and warm handler section. */
1098 static void
1099 nds32_emit_isr_reset_content (void)
1100 {
1101 unsigned int i;
1102 unsigned int total_n_vectors;
1103 const char *vs_str;
1104 char reset_handler_name[100];
1105 char section_name[100];
1106 char symbol_name[100];
1107
1108 total_n_vectors = nds32_isr_vectors[0].total_n_vectors;
1109 vs_str = (nds32_isr_vector_size == 4) ? "_4b" : "";
1110
1111 fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - BEGIN !\n");
1112
1113 /* Create references in .rodata according to total number of vectors. */
1114 fprintf (asm_out_file, "\t.section\t.rodata\n");
1115 fprintf (asm_out_file, "\t.align\t2\n");
1116
1117 /* Emit jmptbl references. */
1118 fprintf (asm_out_file, "\t ! references to jmptbl section entries\n");
1119 for (i = 0; i < total_n_vectors; i++)
1120 fprintf (asm_out_file, "\t.word\t_nds32_jmptbl_%02d\n", i);
1121
1122 /* Emit vector references. */
1123 fprintf (asm_out_file, "\t ! references to vector section entries\n");
1124 for (i = 0; i < total_n_vectors; i++)
1125 fprintf (asm_out_file, "\t.word\t_nds32_vector_%02d%s\n", i, vs_str);
1126
1127 /* Emit jmptbl_00 section. */
1128 snprintf (section_name, sizeof (section_name), ".nds32_jmptbl.00");
1129 snprintf (symbol_name, sizeof (symbol_name), "_nds32_jmptbl_00");
1130
1131 fprintf (asm_out_file, "\t! ....................................\n");
1132 nds32_emit_section_head_template (section_name, symbol_name, 2, true);
1133 fprintf (asm_out_file, "\t.word\t%s\n",
1134 nds32_isr_vectors[0].func_name);
1135 nds32_emit_section_tail_template (symbol_name);
1136
1137 /* Emit vector_00 section. */
1138 snprintf (section_name, sizeof (section_name), ".nds32_vector.00");
1139 snprintf (symbol_name, sizeof (symbol_name), "_nds32_vector_00%s", vs_str);
1140 snprintf (reset_handler_name, sizeof (reset_handler_name),
1141 "_nds32_reset%s", vs_str);
1142
1143 fprintf (asm_out_file, "\t! ....................................\n");
1144 nds32_emit_section_head_template (section_name, symbol_name,
1145 floor_log2 (nds32_isr_vector_size), false);
1146 fprintf (asm_out_file, "\tj\t%s ! jump to reset handler\n",
1147 reset_handler_name);
1148 nds32_emit_section_tail_template (symbol_name);
1149
1150 /* Emit nmi handler section. */
1151 snprintf (section_name, sizeof (section_name), ".nds32_nmih");
1152 snprintf (symbol_name, sizeof (symbol_name), "_nds32_nmih");
1153
1154 fprintf (asm_out_file, "\t! ....................................\n");
1155 nds32_emit_section_head_template (section_name, symbol_name, 2, true);
1156 fprintf (asm_out_file, "\t.word\t%s\n",
1157 (strlen (nds32_isr_vectors[0].nmi_name) == 0)
1158 ? "0"
1159 : nds32_isr_vectors[0].nmi_name);
1160 nds32_emit_section_tail_template (symbol_name);
1161
1162 /* Emit warm handler section. */
1163 snprintf (section_name, sizeof (section_name), ".nds32_wrh");
1164 snprintf (symbol_name, sizeof (symbol_name), "_nds32_wrh");
1165
1166 fprintf (asm_out_file, "\t! ....................................\n");
1167 nds32_emit_section_head_template (section_name, symbol_name, 2, true);
1168 fprintf (asm_out_file, "\t.word\t%s\n",
1169 (strlen (nds32_isr_vectors[0].warm_name) == 0)
1170 ? "0"
1171 : nds32_isr_vectors[0].warm_name);
1172 nds32_emit_section_tail_template (symbol_name);
1173
1174 fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - END !\n");
1175 }
1176
1177 /* Function for nds32_merge_decl_attributes() and nds32_insert_attributes()
1178 to check if there are any conflict isr-specific attributes being set.
1179 We need to check:
1180 1. Only 'save_all' or 'partial_save' in the attributes.
1181 2. Only 'nested', 'not_nested', or 'nested_ready' in the attributes.
1182 3. Only 'interrupt', 'exception', or 'reset' in the attributes. */
1183 static void
1184 nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs)
1185 {
1186 int save_all_p, partial_save_p;
1187 int nested_p, not_nested_p, nested_ready_p;
1188 int intr_p, excp_p, reset_p;
1189
1190 /* Initialize variables. */
1191 save_all_p = partial_save_p = 0;
1192 nested_p = not_nested_p = nested_ready_p = 0;
1193 intr_p = excp_p = reset_p = 0;
1194
1195 /* We must check at MOST one attribute to set save-reg. */
1196 if (lookup_attribute ("save_all", func_attrs))
1197 save_all_p = 1;
1198 if (lookup_attribute ("partial_save", func_attrs))
1199 partial_save_p = 1;
1200
1201 if ((save_all_p + partial_save_p) > 1)
1202 error ("multiple save reg attributes to function %qD", func_decl);
1203
1204 /* We must check at MOST one attribute to set nested-type. */
1205 if (lookup_attribute ("nested", func_attrs))
1206 nested_p = 1;
1207 if (lookup_attribute ("not_nested", func_attrs))
1208 not_nested_p = 1;
1209 if (lookup_attribute ("nested_ready", func_attrs))
1210 nested_ready_p = 1;
1211
1212 if ((nested_p + not_nested_p + nested_ready_p) > 1)
1213 error ("multiple nested types attributes to function %qD", func_decl);
1214
1215 /* We must check at MOST one attribute to
1216 set interrupt/exception/reset. */
1217 if (lookup_attribute ("interrupt", func_attrs))
1218 intr_p = 1;
1219 if (lookup_attribute ("exception", func_attrs))
1220 excp_p = 1;
1221 if (lookup_attribute ("reset", func_attrs))
1222 reset_p = 1;
1223
1224 if ((intr_p + excp_p + reset_p) > 1)
1225 error ("multiple interrupt attributes to function %qD", func_decl);
1226 }
1227
1228 /* Function to construct isr vectors information array.
1229 We DO NOT HAVE TO check if the attributes are valid
1230 because those works are supposed to be done on
1231 nds32_merge_decl_attributes() and nds32_insert_attributes(). */
1232 static void
1233 nds32_construct_isr_vectors_information (tree func_attrs,
1234 const char *func_name)
1235 {
1236 tree save_all, partial_save;
1237 tree nested, not_nested, nested_ready;
1238 tree intr, excp, reset;
1239
1240 save_all = lookup_attribute ("save_all", func_attrs);
1241 partial_save = lookup_attribute ("partial_save", func_attrs);
1242
1243 nested = lookup_attribute ("nested", func_attrs);
1244 not_nested = lookup_attribute ("not_nested", func_attrs);
1245 nested_ready = lookup_attribute ("nested_ready", func_attrs);
1246
1247 intr = lookup_attribute ("interrupt", func_attrs);
1248 excp = lookup_attribute ("exception", func_attrs);
1249 reset = lookup_attribute ("reset", func_attrs);
1250
1251 /* If there is no interrupt/exception/reset, we can return immediately. */
1252 if (!intr && !excp && !reset)
1253 return;
1254
1255 /* If we are here, either we have interrupt/exception,
1256 or reset attribute. */
1257 if (intr || excp)
1258 {
1259 tree id_list;
1260
1261 /* Prepare id list so that we can traverse and set vector id. */
1262 id_list = (intr) ? (TREE_VALUE (intr)) : (TREE_VALUE (excp));
1263
1264 while (id_list)
1265 {
1266 tree id;
1267 int vector_id;
1268 unsigned int vector_number_offset;
1269
1270 /* The way to handle interrupt or exception is the same,
1271 we just need to take care of actual vector number.
1272 For interrupt(0..63), the actual vector number is (9..72).
1273 For exception(1..8), the actual vector number is (1..8). */
1274 vector_number_offset = (intr) ? (9) : (0);
1275
1276 /* Pick up each vector id value. */
1277 id = TREE_VALUE (id_list);
1278 /* Add vector_number_offset to get actual vector number. */
1279 vector_id = TREE_INT_CST_LOW (id) + vector_number_offset;
1280
1281 /* Enable corresponding vector and set function name. */
1282 nds32_isr_vectors[vector_id].category = (intr)
1283 ? (NDS32_ISR_INTERRUPT)
1284 : (NDS32_ISR_EXCEPTION);
1285 strcpy (nds32_isr_vectors[vector_id].func_name, func_name);
1286
1287 /* Set register saving scheme. */
1288 if (save_all)
1289 nds32_isr_vectors[vector_id].save_reg = NDS32_SAVE_ALL;
1290 else if (partial_save)
1291 nds32_isr_vectors[vector_id].save_reg = NDS32_PARTIAL_SAVE;
1292
1293 /* Set nested type. */
1294 if (nested)
1295 nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED;
1296 else if (not_nested)
1297 nds32_isr_vectors[vector_id].nested_type = NDS32_NOT_NESTED;
1298 else if (nested_ready)
1299 nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED_READY;
1300
1301 /* Advance to next id. */
1302 id_list = TREE_CHAIN (id_list);
1303 }
1304 }
1305 else
1306 {
1307 tree id_list;
1308 tree id;
1309 tree nmi, warm;
1310
1311 /* Deal with reset attribute. Its vector number is always 0. */
1312 nds32_isr_vectors[0].category = NDS32_ISR_RESET;
1313
1314 /* Prepare id_list and identify id value so that
1315 we can set total number of vectors. */
1316 id_list = TREE_VALUE (reset);
1317 id = TREE_VALUE (id_list);
1318
1319 /* The total vectors = interrupt + exception numbers + reset.
1320 There are 8 exception and 1 reset in nds32 architecture. */
1321 nds32_isr_vectors[0].total_n_vectors = TREE_INT_CST_LOW (id) + 8 + 1;
1322 strcpy (nds32_isr_vectors[0].func_name, func_name);
1323
1324 /* Retrieve nmi and warm function. */
1325 nmi = lookup_attribute ("nmi", func_attrs);
1326 warm = lookup_attribute ("warm", func_attrs);
1327
1328 if (nmi != NULL_TREE)
1329 {
1330 tree nmi_func_list;
1331 tree nmi_func;
1332
1333 nmi_func_list = TREE_VALUE (nmi);
1334 nmi_func = TREE_VALUE (nmi_func_list);
1335
1336 /* Record nmi function name. */
1337 strcpy (nds32_isr_vectors[0].nmi_name,
1338 IDENTIFIER_POINTER (nmi_func));
1339 }
1340
1341 if (warm != NULL_TREE)
1342 {
1343 tree warm_func_list;
1344 tree warm_func;
1345
1346 warm_func_list = TREE_VALUE (warm);
1347 warm_func = TREE_VALUE (warm_func_list);
1348
1349 /* Record warm function name. */
1350 strcpy (nds32_isr_vectors[0].warm_name,
1351 IDENTIFIER_POINTER (warm_func));
1352 }
1353 }
1354 }
1355
1356 /* Function that may creates more instructions
1357 for large value on adjusting stack pointer.
1358
1359 In nds32 target, 'addi' can be used for stack pointer
1360 adjustment in prologue/epilogue stage.
1361 However, sometimes there are too many local variables so that
1362 the adjustment value is not able to be fit in the 'addi' instruction.
1363 One solution is to move value into a register
1364 and then use 'add' instruction.
1365 In practice, we use TA_REGNUM ($r15) to accomplish this purpose.
1366 Also, we need to return zero for sp adjustment so that
1367 proglogue/epilogue knows there is no need to create 'addi' instruction. */
1368 static int
1369 nds32_force_addi_stack_int (int full_value)
1370 {
1371 int adjust_value;
1372
1373 rtx tmp_reg;
1374 rtx sp_adjust_insn;
1375
1376 if (!satisfies_constraint_Is15 (GEN_INT (full_value)))
1377 {
1378 /* The value is not able to fit in single addi instruction.
1379 Create more instructions of moving value into a register
1380 and then add stack pointer with it. */
1381
1382 /* $r15 is going to be temporary register to hold the value. */
1383 tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
1384
1385 /* Create one more instruction to move value
1386 into the temporary register. */
1387 emit_move_insn (tmp_reg, GEN_INT (full_value));
1388
1389 /* Create new 'add' rtx. */
1390 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
1391 stack_pointer_rtx,
1392 tmp_reg);
1393 /* Emit rtx into insn list and receive its transformed insn rtx. */
1394 sp_adjust_insn = emit_insn (sp_adjust_insn);
1395
1396 /* At prologue, we need to tell GCC that this is frame related insn,
1397 so that we can consider this instruction to output debug information.
1398 If full_value is NEGATIVE, it means this function
1399 is invoked by expand_prologue. */
1400 if (full_value < 0)
1401 {
1402 /* Because (tmp_reg <- full_value) may be split into two
1403 rtl patterns, we can not set its RTX_FRAME_RELATED_P.
1404 We need to construct another (sp <- sp + full_value)
1405 and then insert it into sp_adjust_insn's reg note to
1406 represent a frame related expression.
1407 GCC knows how to refer it and output debug information. */
1408
1409 rtx plus_rtx;
1410 rtx set_rtx;
1411
1412 plus_rtx = plus_constant (Pmode, stack_pointer_rtx, full_value);
1413 set_rtx = gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_rtx);
1414 add_reg_note (sp_adjust_insn, REG_FRAME_RELATED_EXPR, set_rtx);
1415
1416 RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
1417 }
1418
1419 /* We have used alternative way to adjust stack pointer value.
1420 Return zero so that prologue/epilogue
1421 will not generate other instructions. */
1422 return 0;
1423 }
1424 else
1425 {
1426 /* The value is able to fit in addi instruction.
1427 However, remember to make it to be positive value
1428 because we want to return 'adjustment' result. */
1429 adjust_value = (full_value < 0) ? (-full_value) : (full_value);
1430
1431 return adjust_value;
1432 }
1433 }
1434
1435 /* Return true if MODE/TYPE need double word alignment. */
1436 static bool
1437 nds32_needs_double_word_align (enum machine_mode mode, const_tree type)
1438 {
1439 unsigned int align;
1440
1441 /* Pick up the alignment according to the mode or type. */
1442 align = NDS32_MODE_TYPE_ALIGN (mode, type);
1443
1444 return (align > PARM_BOUNDARY);
1445 }
1446
1447 /* Return true if FUNC is a naked function. */
1448 static bool
1449 nds32_naked_function_p (tree func)
1450 {
1451 tree t;
1452
1453 if (TREE_CODE (func) != FUNCTION_DECL)
1454 abort ();
1455
1456 t = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
1457
1458 return (t != NULL_TREE);
1459 }
1460
1461 /* Function that check if 'X' is a valid address register.
1462 The variable 'STRICT' is very important to
1463 make decision for register number.
1464
1465 STRICT : true
1466 => We are in reload pass or after reload pass.
1467 The register number should be strictly limited in general registers.
1468
1469 STRICT : false
1470 => Before reload pass, we are free to use any register number. */
1471 static bool
1472 nds32_address_register_rtx_p (rtx x, bool strict)
1473 {
1474 int regno;
1475
1476 if (GET_CODE (x) != REG)
1477 return false;
1478
1479 regno = REGNO (x);
1480
1481 if (strict)
1482 return REGNO_OK_FOR_BASE_P (regno);
1483 else
1484 return true;
1485 }
1486
1487 /* Function that check if 'INDEX' is valid to be a index rtx for address.
1488
1489 OUTER_MODE : Machine mode of outer address rtx.
1490 INDEX : Check if this rtx is valid to be a index for address.
1491 STRICT : If it is true, we are in reload pass or after reload pass. */
1492 static bool
1493 nds32_legitimate_index_p (enum machine_mode outer_mode,
1494 rtx index,
1495 bool strict)
1496 {
1497 int regno;
1498 rtx op0;
1499 rtx op1;
1500
1501 switch (GET_CODE (index))
1502 {
1503 case REG:
1504 regno = REGNO (index);
1505 /* If we are in reload pass or after reload pass,
1506 we need to limit it to general register. */
1507 if (strict)
1508 return REGNO_OK_FOR_INDEX_P (regno);
1509 else
1510 return true;
1511
1512 case CONST_INT:
1513 /* The alignment of the integer value is determined by 'outer_mode'. */
1514 if (GET_MODE_SIZE (outer_mode) == 1)
1515 {
1516 /* Further check if the value is legal for the 'outer_mode'. */
1517 if (!satisfies_constraint_Is15 (index))
1518 return false;
1519
1520 /* Pass all test, the value is valid, return true. */
1521 return true;
1522 }
1523 if (GET_MODE_SIZE (outer_mode) == 2
1524 && NDS32_HALF_WORD_ALIGN_P (INTVAL (index)))
1525 {
1526 /* Further check if the value is legal for the 'outer_mode'. */
1527 if (!satisfies_constraint_Is16 (index))
1528 return false;
1529
1530 /* Pass all test, the value is valid, return true. */
1531 return true;
1532 }
1533 if (GET_MODE_SIZE (outer_mode) == 4
1534 && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index)))
1535 {
1536 /* Further check if the value is legal for the 'outer_mode'. */
1537 if (!satisfies_constraint_Is17 (index))
1538 return false;
1539
1540 /* Pass all test, the value is valid, return true. */
1541 return true;
1542 }
1543 if (GET_MODE_SIZE (outer_mode) == 8
1544 && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index)))
1545 {
1546 /* Further check if the value is legal for the 'outer_mode'. */
1547 if (!satisfies_constraint_Is17 (gen_int_mode (INTVAL (index) + 4,
1548 SImode)))
1549 return false;
1550
1551 /* Pass all test, the value is valid, return true. */
1552 return true;
1553 }
1554
1555 return false;
1556
1557 case MULT:
1558 op0 = XEXP (index, 0);
1559 op1 = XEXP (index, 1);
1560
1561 if (REG_P (op0) && CONST_INT_P (op1))
1562 {
1563 int multiplier;
1564 multiplier = INTVAL (op1);
1565
1566 /* We only allow (mult reg const_int_1)
1567 or (mult reg const_int_2) or (mult reg const_int_4). */
1568 if (multiplier != 1 && multiplier != 2 && multiplier != 4)
1569 return false;
1570
1571 regno = REGNO (op0);
1572 /* Limit it in general registers if we are
1573 in reload pass or after reload pass. */
1574 if(strict)
1575 return REGNO_OK_FOR_INDEX_P (regno);
1576 else
1577 return true;
1578 }
1579
1580 return false;
1581
1582 case ASHIFT:
1583 op0 = XEXP (index, 0);
1584 op1 = XEXP (index, 1);
1585
1586 if (REG_P (op0) && CONST_INT_P (op1))
1587 {
1588 int sv;
1589 /* op1 is already the sv value for use to do left shift. */
1590 sv = INTVAL (op1);
1591
1592 /* We only allow (ashift reg const_int_0)
1593 or (ashift reg const_int_1) or (ashift reg const_int_2). */
1594 if (sv != 0 && sv != 1 && sv !=2)
1595 return false;
1596
1597 regno = REGNO (op0);
1598 /* Limit it in general registers if we are
1599 in reload pass or after reload pass. */
1600 if(strict)
1601 return REGNO_OK_FOR_INDEX_P (regno);
1602 else
1603 return true;
1604 }
1605
1606 return false;
1607
1608 default:
1609 return false;
1610 }
1611 }
1612
1613 /* Function to expand builtin function for
1614 '[(unspec_volatile [(reg)])]'. */
1615 static rtx
1616 nds32_expand_builtin_null_ftype_reg (enum insn_code icode,
1617 tree exp, rtx target)
1618 {
1619 /* Mapping:
1620 ops[0] <--> value0 <--> arg0 */
1621 struct expand_operand ops[1];
1622 tree arg0;
1623 rtx value0;
1624
1625 /* Grab the incoming arguments and extract its rtx. */
1626 arg0 = CALL_EXPR_ARG (exp, 0);
1627 value0 = expand_normal (arg0);
1628
1629 /* Create operands. */
1630 create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0)));
1631
1632 /* Emit new instruction. */
1633 if (!maybe_expand_insn (icode, 1, ops))
1634 error ("invalid argument to built-in function");
1635
1636 return target;
1637 }
1638
1639 /* Function to expand builtin function for
1640 '[(set (reg) (unspec_volatile [(imm)]))]'. */
1641 static rtx
1642 nds32_expand_builtin_reg_ftype_imm (enum insn_code icode,
1643 tree exp, rtx target)
1644 {
1645 /* Mapping:
1646 ops[0] <--> target <--> exp
1647 ops[1] <--> value0 <--> arg0 */
1648 struct expand_operand ops[2];
1649 tree arg0;
1650 rtx value0;
1651
1652 /* Grab the incoming arguments and extract its rtx. */
1653 arg0 = CALL_EXPR_ARG (exp, 0);
1654 value0 = expand_normal (arg0);
1655
1656 /* Create operands. */
1657 create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
1658 create_input_operand (&ops[1], value0, TYPE_MODE (TREE_TYPE (arg0)));
1659
1660 /* Emit new instruction. */
1661 if (!maybe_expand_insn (icode, 2, ops))
1662 error ("invalid argument to built-in function");
1663
1664 return target;
1665 }
1666
1667 /* Function to expand builtin function for
1668 '[(unspec_volatile [(reg) (imm)])]' pattern. */
1669 static rtx
1670 nds32_expand_builtin_null_ftype_reg_imm (enum insn_code icode,
1671 tree exp, rtx target)
1672 {
1673 /* Mapping:
1674 ops[0] <--> value0 <--> arg0
1675 ops[1] <--> value1 <--> arg1 */
1676 struct expand_operand ops[2];
1677 tree arg0, arg1;
1678 rtx value0, value1;
1679
1680 /* Grab the incoming arguments and extract its rtx. */
1681 arg0 = CALL_EXPR_ARG (exp, 0);
1682 arg1 = CALL_EXPR_ARG (exp, 1);
1683 value0 = expand_normal (arg0);
1684 value1 = expand_normal (arg1);
1685
1686 /* Create operands. */
1687 create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0)));
1688 create_input_operand (&ops[1], value1, TYPE_MODE (TREE_TYPE (arg1)));
1689
1690 /* Emit new instruction. */
1691 if (!maybe_expand_insn (icode, 2, ops))
1692 error ("invalid argument to built-in function");
1693
1694 return target;
1695 }
1696
1697 /* A helper function to return character based on byte size. */
1698 static char
1699 nds32_byte_to_size (int byte)
1700 {
1701 switch (byte)
1702 {
1703 case 4:
1704 return 'w';
1705 case 2:
1706 return 'h';
1707 case 1:
1708 return 'b';
1709 default:
1710 /* Normally it should not be here. */
1711 gcc_unreachable ();
1712 }
1713 }
1714
1715 /* A helper function to check if this function should contain prologue. */
1716 static int
1717 nds32_have_prologue_p (void)
1718 {
1719 int i;
1720
1721 for (i = 0; i < 28; i++)
1722 if (NDS32_REQUIRED_CALLEE_SAVED_P (i))
1723 return 1;
1724
1725 return (flag_pic
1726 || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM)
1727 || NDS32_REQUIRED_CALLEE_SAVED_P (LP_REGNUM));
1728 }
1729
1730 /* ------------------------------------------------------------------------ */
1731
1732 /* PART 3: Implement target hook stuff definitions. */
1733 \f
1734 /* Register Classes. */
1735
1736 static unsigned char
1737 nds32_class_max_nregs (reg_class_t rclass ATTRIBUTE_UNUSED,
1738 enum machine_mode mode)
1739 {
1740 /* Return the maximum number of consecutive registers
1741 needed to represent "mode" in a register of "rclass". */
1742 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1743 }
1744
1745 static int
1746 nds32_register_priority (int hard_regno)
1747 {
1748 /* Encourage to use r0-r7 for LRA when optimize for size. */
1749 if (optimize_size && hard_regno < 8)
1750 return 4;
1751 return 3;
1752 }
1753
1754 \f
1755 /* Stack Layout and Calling Conventions. */
1756
1757 /* There are three kinds of pointer concepts using in GCC compiler:
1758
1759 frame pointer: A pointer to the first location of local variables.
1760 stack pointer: A pointer to the top of a stack frame.
1761 argument pointer: A pointer to the incoming arguments.
1762
1763 In nds32 target calling convention, we are using 8-byte alignment.
1764 Besides, we would like to have each stack frame of a function includes:
1765
1766 [Block A]
1767 1. previous hard frame pointer
1768 2. return address
1769 3. callee-saved registers
1770 4. <padding bytes> (we will calculte in nds32_compute_stack_frame()
1771 and save it at
1772 cfun->machine->callee_saved_area_padding_bytes)
1773
1774 [Block B]
1775 1. local variables
1776 2. spilling location
1777 3. <padding bytes> (it will be calculated by GCC itself)
1778 4. incoming arguments
1779 5. <padding bytes> (it will be calculated by GCC itself)
1780
1781 [Block C]
1782 1. <padding bytes> (it will be calculated by GCC itself)
1783 2. outgoing arguments
1784
1785 We 'wrap' these blocks together with
1786 hard frame pointer ($r28) and stack pointer ($r31).
1787 By applying the basic frame/stack/argument pointers concept,
1788 the layout of a stack frame shoule be like this:
1789
1790 | |
1791 old stack pointer -> ----
1792 | | \
1793 | | saved arguments for
1794 | | vararg functions
1795 | | /
1796 hard frame pointer -> --
1797 & argument pointer | | \
1798 | | previous hardware frame pointer
1799 | | return address
1800 | | callee-saved registers
1801 | | /
1802 frame pointer -> --
1803 | | \
1804 | | local variables
1805 | | and incoming arguments
1806 | | /
1807 --
1808 | | \
1809 | | outgoing
1810 | | arguments
1811 | | /
1812 stack pointer -> ----
1813
1814 $SFP and $AP are used to represent frame pointer and arguments pointer,
1815 which will be both eliminated as hard frame pointer. */
1816
1817 /* -- Eliminating Frame Pointer and Arg Pointer. */
1818
1819 static bool nds32_can_eliminate (const int from_reg, const int to_reg)
1820 {
1821 if (from_reg == ARG_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM)
1822 return true;
1823
1824 if (from_reg == ARG_POINTER_REGNUM && to_reg == HARD_FRAME_POINTER_REGNUM)
1825 return true;
1826
1827 if (from_reg == FRAME_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM)
1828 return true;
1829
1830 if (from_reg == FRAME_POINTER_REGNUM && to_reg == HARD_FRAME_POINTER_REGNUM)
1831 return true;
1832
1833 return false;
1834 }
1835
1836 /* -- Passing Arguments in Registers. */
1837
1838 static rtx
1839 nds32_function_arg (cumulative_args_t ca, enum machine_mode mode,
1840 const_tree type, bool named)
1841 {
1842 CUMULATIVE_ARGS *cum = get_cumulative_args (ca);
1843
1844 /* The last time this hook is called,
1845 it is called with MODE == VOIDmode. */
1846 if (mode == VOIDmode)
1847 return NULL_RTX;
1848
1849 /* For nameless arguments, they are passed on the stack. */
1850 if (!named)
1851 return NULL_RTX;
1852
1853 /* If there are still registers available, return it. */
1854 if (NDS32_ARG_PASS_IN_REG_P (cum->reg_offset, mode, type))
1855 {
1856 /* Pick up the next available register number. */
1857 unsigned int regno;
1858
1859 regno = NDS32_AVAILABLE_REGNUM_FOR_ARG (cum->reg_offset, mode, type);
1860 return gen_rtx_REG (mode, regno);
1861 }
1862 else
1863 {
1864 /* No register available, return NULL_RTX.
1865 The compiler will use stack to pass argument instead. */
1866 return NULL_RTX;
1867 }
1868 }
1869
1870 static void
1871 nds32_function_arg_advance (cumulative_args_t ca, enum machine_mode mode,
1872 const_tree type, bool named)
1873 {
1874 CUMULATIVE_ARGS *cum = get_cumulative_args (ca);
1875
1876 /* Advance next register for use.
1877 Only named argument could be advanced. */
1878 if (named)
1879 {
1880 cum->reg_offset
1881 = NDS32_AVAILABLE_REGNUM_FOR_ARG (cum->reg_offset, mode, type)
1882 - NDS32_GPR_ARG_FIRST_REGNUM
1883 + NDS32_NEED_N_REGS_FOR_ARG (mode, type);
1884 }
1885 }
1886
1887 static unsigned int
1888 nds32_function_arg_boundary (enum machine_mode mode, const_tree type)
1889 {
1890 return (nds32_needs_double_word_align (mode, type)
1891 ? NDS32_DOUBLE_WORD_ALIGNMENT
1892 : PARM_BOUNDARY);
1893 }
1894
1895 /* -- How Scalar Function Values Are Returned. */
1896
1897 static rtx
1898 nds32_function_value (const_tree ret_type,
1899 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1900 bool outgoing ATTRIBUTE_UNUSED)
1901 {
1902 enum machine_mode mode;
1903 int unsignedp;
1904
1905 mode = TYPE_MODE (ret_type);
1906 unsignedp = TYPE_UNSIGNED (ret_type);
1907
1908 mode = promote_mode (ret_type, mode, &unsignedp);
1909
1910 return gen_rtx_REG (mode, NDS32_GPR_RET_FIRST_REGNUM);
1911 }
1912
1913 static rtx
1914 nds32_libcall_value (enum machine_mode mode,
1915 const_rtx fun ATTRIBUTE_UNUSED)
1916 {
1917 return gen_rtx_REG (mode, NDS32_GPR_RET_FIRST_REGNUM);
1918 }
1919
1920 static bool
1921 nds32_function_value_regno_p (const unsigned int regno)
1922 {
1923 return (regno == NDS32_GPR_RET_FIRST_REGNUM);
1924 }
1925
1926 /* -- Function Entry and Exit. */
1927
1928 /* The content produced from this function
1929 will be placed before prologue body. */
1930 static void
1931 nds32_asm_function_prologue (FILE *file,
1932 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
1933 {
1934 int r;
1935 const char *func_name;
1936 tree attrs;
1937 tree name;
1938
1939 /* All stack frame information is supposed to be
1940 already computed when expanding prologue.
1941 The result is in cfun->machine.
1942 DO NOT call nds32_compute_stack_frame() here
1943 because it may corrupt the essential information. */
1944
1945 fprintf (file, "\t! BEGIN PROLOGUE\n");
1946 fprintf (file, "\t! fp needed: %d\n", frame_pointer_needed);
1947 fprintf (file, "\t! pretend_args: %d\n", cfun->machine->va_args_size);
1948 fprintf (file, "\t! local_size: %d\n", cfun->machine->local_size);
1949 fprintf (file, "\t! out_args_size: %d\n", cfun->machine->out_args_size);
1950
1951 /* Use df_regs_ever_live_p() to detect if the register
1952 is ever used in the current function. */
1953 fprintf (file, "\t! registers ever_live: ");
1954 for (r = 0; r < 32; r++)
1955 {
1956 if (df_regs_ever_live_p (r))
1957 fprintf (file, "%s, ", reg_names[r]);
1958 }
1959 fputc ('\n', file);
1960
1961 /* Display the attributes of this function. */
1962 fprintf (file, "\t! function attributes: ");
1963 /* Get the attributes tree list.
1964 Note that GCC builds attributes list with reverse order. */
1965 attrs = DECL_ATTRIBUTES (current_function_decl);
1966
1967 /* If there is no any attribute, print out "None". */
1968 if (!attrs)
1969 fprintf (file, "None");
1970
1971 /* If there are some attributes, try if we need to
1972 construct isr vector information. */
1973 func_name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
1974 nds32_construct_isr_vectors_information (attrs, func_name);
1975
1976 /* Display all attributes of this function. */
1977 while (attrs)
1978 {
1979 name = TREE_PURPOSE (attrs);
1980 fprintf (file, "%s ", IDENTIFIER_POINTER (name));
1981
1982 /* Pick up the next attribute. */
1983 attrs = TREE_CHAIN (attrs);
1984 }
1985 fputc ('\n', file);
1986 }
1987
1988 /* After rtl prologue has been expanded, this function is used. */
1989 static void
1990 nds32_asm_function_end_prologue (FILE *file)
1991 {
1992 fprintf (file, "\t! END PROLOGUE\n");
1993
1994 /* If frame pointer is NOT needed and -mfp-as-gp is issued,
1995 we can generate special directive: ".omit_fp_begin"
1996 to guide linker doing fp-as-gp optimization.
1997 However, for a naked function, which means
1998 it should not have prologue/epilogue,
1999 using fp-as-gp still requires saving $fp by push/pop behavior and
2000 there is no benefit to use fp-as-gp on such small function.
2001 So we need to make sure this function is NOT naked as well. */
2002 if (!frame_pointer_needed
2003 && !cfun->machine->naked_p
2004 && cfun->machine->fp_as_gp_p)
2005 {
2006 fprintf (file, "\t! ----------------------------------------\n");
2007 fprintf (file, "\t! Guide linker to do "
2008 "link time optimization: fp-as-gp\n");
2009 fprintf (file, "\t! We add one more instruction to "
2010 "initialize $fp near to $gp location.\n");
2011 fprintf (file, "\t! If linker fails to use fp-as-gp transformation,\n");
2012 fprintf (file, "\t! this extra instruction should be "
2013 "eliminated at link stage.\n");
2014 fprintf (file, "\t.omit_fp_begin\n");
2015 fprintf (file, "\tla\t$fp,_FP_BASE_\n");
2016 fprintf (file, "\t! ----------------------------------------\n");
2017 }
2018 }
2019
2020 /* Before rtl epilogue has been expanded, this function is used. */
2021 static void
2022 nds32_asm_function_begin_epilogue (FILE *file)
2023 {
2024 /* If frame pointer is NOT needed and -mfp-as-gp is issued,
2025 we can generate special directive: ".omit_fp_end"
2026 to claim fp-as-gp optimization range.
2027 However, for a naked function,
2028 which means it should not have prologue/epilogue,
2029 using fp-as-gp still requires saving $fp by push/pop behavior and
2030 there is no benefit to use fp-as-gp on such small function.
2031 So we need to make sure this function is NOT naked as well. */
2032 if (!frame_pointer_needed
2033 && !cfun->machine->naked_p
2034 && cfun->machine->fp_as_gp_p)
2035 {
2036 fprintf (file, "\t! ----------------------------------------\n");
2037 fprintf (file, "\t! Claim the range of fp-as-gp "
2038 "link time optimization\n");
2039 fprintf (file, "\t.omit_fp_end\n");
2040 fprintf (file, "\t! ----------------------------------------\n");
2041 }
2042
2043 fprintf (file, "\t! BEGIN EPILOGUE\n");
2044 }
2045
2046 /* The content produced from this function
2047 will be placed after epilogue body. */
2048 static void
2049 nds32_asm_function_epilogue (FILE *file,
2050 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
2051 {
2052 fprintf (file, "\t! END EPILOGUE\n");
2053 }
2054
2055 static void
2056 nds32_asm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
2057 HOST_WIDE_INT delta,
2058 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
2059 tree function)
2060 {
2061 int this_regno;
2062
2063 /* Make sure unwind info is emitted for the thunk if needed. */
2064 final_start_function (emit_barrier (), file, 1);
2065
2066 this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)
2067 ? 1
2068 : 0);
2069
2070 if (delta != 0)
2071 {
2072 if (satisfies_constraint_Is15 (GEN_INT (delta)))
2073 {
2074 fprintf (file, "\taddi\t$r%d, $r%d, %ld\n",
2075 this_regno, this_regno, delta);
2076 }
2077 else if (satisfies_constraint_Is20 (GEN_INT (delta)))
2078 {
2079 fprintf (file, "\tmovi\t$ta, %ld\n", delta);
2080 fprintf (file, "\tadd\t$r%d, $r%d, $ta\n", this_regno, this_regno);
2081 }
2082 else
2083 {
2084 fprintf (file, "\tsethi\t$ta, hi20(%ld)\n", delta);
2085 fprintf (file, "\tori\t$ta, $ta, lo12(%ld)\n", delta);
2086 fprintf (file, "\tadd\t$r%d, $r%d, $ta\n", this_regno, this_regno);
2087 }
2088 }
2089
2090 fprintf (file, "\tb\t");
2091 assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
2092 fprintf (file, "\n");
2093
2094 final_end_function ();
2095 }
2096
2097 /* -- Permitting tail calls. */
2098
2099 /* Determine whether we need to enable warning for function return check. */
2100 static bool
2101 nds32_warn_func_return (tree decl)
2102 {
2103 /* Naked functions are implemented entirely in assembly, including the
2104 return sequence, so suppress warnings about this. */
2105 return !nds32_naked_function_p (decl);
2106 }
2107
2108 \f
2109 /* Implementing the Varargs Macros. */
2110
2111 static bool
2112 nds32_strict_argument_naming (cumulative_args_t ca ATTRIBUTE_UNUSED)
2113 {
2114 /* Return true so that all the named arguments for FUNCTION_ARG have named=1.
2115 If return false, for the variadic function, all named arguments EXCEPT
2116 the last are treated as named. */
2117 return true;
2118 }
2119
2120 \f
2121 /* Trampolines for Nested Functions. */
2122
2123 static void
2124 nds32_asm_trampoline_template (FILE *f)
2125 {
2126 if (TARGET_REDUCED_REGS)
2127 {
2128 /* Trampoline is not supported on reduced-set registers yet. */
2129 sorry ("a nested function is not supported for reduced registers");
2130 }
2131 else
2132 {
2133 asm_fprintf (f, "\t! Trampoline code template\n");
2134 asm_fprintf (f, "\t! This code fragment will be copied "
2135 "into stack on demand\n");
2136
2137 asm_fprintf (f, "\tmfusr\t$r16,$pc\n");
2138 asm_fprintf (f, "\tlwi\t$r15,[$r16 + 20] "
2139 "! load nested function address\n");
2140 asm_fprintf (f, "\tlwi\t$r16,[$r16 + 16] "
2141 "! load chain_value\n");
2142 asm_fprintf (f, "\tjr\t$r15\n");
2143 }
2144
2145 /* Preserve space ($pc + 16) for saving chain_value,
2146 nds32_trampoline_init will fill the value in this slot. */
2147 asm_fprintf (f, "\t! space for saving chain_value\n");
2148 assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
2149
2150 /* Preserve space ($pc + 20) for saving nested function address,
2151 nds32_trampoline_init will fill the value in this slot. */
2152 asm_fprintf (f, "\t! space for saving nested function address\n");
2153 assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
2154 }
2155
2156 /* Emit RTL insns to initialize the variable parts of a trampoline. */
2157 static void
2158 nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
2159 {
2160 int i;
2161
2162 /* Nested function address. */
2163 rtx fnaddr;
2164 /* The memory rtx that is going to
2165 be filled with chain_value. */
2166 rtx chain_value_mem;
2167 /* The memory rtx that is going to
2168 be filled with nested function address. */
2169 rtx nested_func_mem;
2170
2171 /* Start address of trampoline code in stack, for doing cache sync. */
2172 rtx sync_cache_addr;
2173 /* Temporary register for sync instruction. */
2174 rtx tmp_reg;
2175 /* Instruction-cache sync instruction,
2176 requesting an argument as starting address. */
2177 rtx isync_insn;
2178 /* For convenience reason of doing comparison. */
2179 int tramp_align_in_bytes;
2180
2181 /* Trampoline is not supported on reduced-set registers yet. */
2182 if (TARGET_REDUCED_REGS)
2183 sorry ("a nested function is not supported for reduced registers");
2184
2185 /* STEP 1: Copy trampoline code template into stack,
2186 fill up essential data into stack. */
2187
2188 /* Extract nested function address rtx. */
2189 fnaddr = XEXP (DECL_RTL (fndecl), 0);
2190
2191 /* m_tramp is memory rtx that is going to be filled with trampoline code.
2192 We have nds32_asm_trampoline_template() to emit template pattern. */
2193 emit_block_move (m_tramp, assemble_trampoline_template (),
2194 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
2195
2196 /* After copying trampoline code into stack,
2197 fill chain_value into stack. */
2198 chain_value_mem = adjust_address (m_tramp, SImode, 16);
2199 emit_move_insn (chain_value_mem, chain_value);
2200 /* After copying trampoline code int stack,
2201 fill nested function address into stack. */
2202 nested_func_mem = adjust_address (m_tramp, SImode, 20);
2203 emit_move_insn (nested_func_mem, fnaddr);
2204
2205 /* STEP 2: Sync instruction-cache. */
2206
2207 /* We have successfully filled trampoline code into stack.
2208 However, in order to execute code in stack correctly,
2209 we must sync instruction cache. */
2210 sync_cache_addr = XEXP (m_tramp, 0);
2211 tmp_reg = gen_reg_rtx (SImode);
2212 isync_insn = gen_unspec_volatile_isync (tmp_reg);
2213
2214 /* Because nds32_cache_block_size is in bytes,
2215 we get trampoline alignment in bytes for convenient comparison. */
2216 tramp_align_in_bytes = TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT;
2217
2218 if (tramp_align_in_bytes >= nds32_cache_block_size
2219 && (tramp_align_in_bytes % nds32_cache_block_size) == 0)
2220 {
2221 /* Under this condition, the starting address of trampoline
2222 must be aligned to the starting address of each cache block
2223 and we do not have to worry about cross-boundary issue. */
2224 for (i = 0;
2225 i < (TRAMPOLINE_SIZE + nds32_cache_block_size - 1)
2226 / nds32_cache_block_size;
2227 i++)
2228 {
2229 emit_move_insn (tmp_reg,
2230 plus_constant (Pmode, sync_cache_addr,
2231 nds32_cache_block_size * i));
2232 emit_insn (isync_insn);
2233 }
2234 }
2235 else if (TRAMPOLINE_SIZE > nds32_cache_block_size)
2236 {
2237 /* The starting address of trampoline code
2238 may not be aligned to the cache block,
2239 so the trampoline code may be across two cache block.
2240 We need to sync the last element, which is 4-byte size,
2241 of trampoline template. */
2242 for (i = 0;
2243 i < (TRAMPOLINE_SIZE + nds32_cache_block_size - 1)
2244 / nds32_cache_block_size;
2245 i++)
2246 {
2247 emit_move_insn (tmp_reg,
2248 plus_constant (Pmode, sync_cache_addr,
2249 nds32_cache_block_size * i));
2250 emit_insn (isync_insn);
2251 }
2252
2253 /* The last element of trampoline template is 4-byte size. */
2254 emit_move_insn (tmp_reg,
2255 plus_constant (Pmode, sync_cache_addr,
2256 TRAMPOLINE_SIZE - 4));
2257 emit_insn (isync_insn);
2258 }
2259 else
2260 {
2261 /* This is the simplest case.
2262 Because TRAMPOLINE_SIZE is less than or
2263 equal to nds32_cache_block_size,
2264 we can just sync start address and
2265 the last element of trampoline code. */
2266
2267 /* Sync starting address of tampoline code. */
2268 emit_move_insn (tmp_reg, sync_cache_addr);
2269 emit_insn (isync_insn);
2270 /* Sync the last element, which is 4-byte size,
2271 of trampoline template. */
2272 emit_move_insn (tmp_reg,
2273 plus_constant (Pmode, sync_cache_addr,
2274 TRAMPOLINE_SIZE - 4));
2275 emit_insn (isync_insn);
2276 }
2277
2278 /* Set instruction serialization barrier
2279 to guarantee the correct operations. */
2280 emit_insn (gen_unspec_volatile_isb ());
2281 }
2282
2283 \f
2284 /* Addressing Modes. */
2285
2286 static bool
2287 nds32_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
2288 {
2289 /* For (mem:DI addr) or (mem:DF addr) case,
2290 we only allow 'addr' to be [reg], [symbol_ref],
2291 [const], or [reg + const_int] pattern. */
2292 if (mode == DImode || mode == DFmode)
2293 {
2294 /* Allow [Reg + const_int] addressing mode. */
2295 if (GET_CODE (x) == PLUS)
2296 {
2297 if (nds32_address_register_rtx_p (XEXP (x, 0), strict)
2298 && nds32_legitimate_index_p (mode, XEXP (x, 1), strict)
2299 && CONST_INT_P (XEXP (x, 1)))
2300 return true;
2301
2302 else if (nds32_address_register_rtx_p (XEXP (x, 1), strict)
2303 && nds32_legitimate_index_p (mode, XEXP (x, 0), strict)
2304 && CONST_INT_P (XEXP (x, 0)))
2305 return true;
2306 }
2307
2308 /* Now check [reg], [symbol_ref], and [const]. */
2309 if (GET_CODE (x) != REG
2310 && GET_CODE (x) != SYMBOL_REF
2311 && GET_CODE (x) != CONST)
2312 return false;
2313 }
2314
2315 /* Check if 'x' is a valid address. */
2316 switch (GET_CODE (x))
2317 {
2318 case REG:
2319 /* (mem (reg A)) => [Ra] */
2320 return nds32_address_register_rtx_p (x, strict);
2321
2322 case SYMBOL_REF:
2323
2324 if (!TARGET_GP_DIRECT
2325 && (reload_completed
2326 || reload_in_progress
2327 || lra_in_progress))
2328 return false;
2329
2330 /* (mem (symbol_ref A)) => [symbol_ref] */
2331 return !currently_expanding_to_rtl;
2332
2333 case CONST:
2334
2335 if (!TARGET_GP_DIRECT
2336 && (reload_completed
2337 || reload_in_progress
2338 || lra_in_progress))
2339 return false;
2340
2341 /* (mem (const (...)))
2342 => [ + const_addr ], where const_addr = symbol_ref + const_int */
2343 if (GET_CODE (XEXP (x, 0)) == PLUS)
2344 {
2345 rtx plus_op = XEXP (x, 0);
2346
2347 rtx op0 = XEXP (plus_op, 0);
2348 rtx op1 = XEXP (plus_op, 1);
2349
2350 if (GET_CODE (op0) == SYMBOL_REF && CONST_INT_P (op1))
2351 return true;
2352 else
2353 return false;
2354 }
2355
2356 return false;
2357
2358 case POST_MODIFY:
2359 /* (mem (post_modify (reg) (plus (reg) (reg))))
2360 => [Ra], Rb */
2361 /* (mem (post_modify (reg) (plus (reg) (const_int))))
2362 => [Ra], const_int */
2363 if (GET_CODE (XEXP (x, 0)) == REG
2364 && GET_CODE (XEXP (x, 1)) == PLUS)
2365 {
2366 rtx plus_op = XEXP (x, 1);
2367
2368 rtx op0 = XEXP (plus_op, 0);
2369 rtx op1 = XEXP (plus_op, 1);
2370
2371 if (nds32_address_register_rtx_p (op0, strict)
2372 && nds32_legitimate_index_p (mode, op1, strict))
2373 return true;
2374 else
2375 return false;
2376 }
2377
2378 return false;
2379
2380 case POST_INC:
2381 case POST_DEC:
2382 /* (mem (post_inc reg)) => [Ra], 1/2/4 */
2383 /* (mem (post_dec reg)) => [Ra], -1/-2/-4 */
2384 /* The 1/2/4 or -1/-2/-4 have been displayed in nds32.md.
2385 We only need to deal with register Ra. */
2386 if (nds32_address_register_rtx_p (XEXP (x, 0), strict))
2387 return true;
2388 else
2389 return false;
2390
2391 case PLUS:
2392 /* (mem (plus reg const_int))
2393 => [Ra + imm] */
2394 /* (mem (plus reg reg))
2395 => [Ra + Rb] */
2396 /* (mem (plus (mult reg const_int) reg))
2397 => [Ra + Rb << sv] */
2398 if (nds32_address_register_rtx_p (XEXP (x, 0), strict)
2399 && nds32_legitimate_index_p (mode, XEXP (x, 1), strict))
2400 return true;
2401 else if (nds32_address_register_rtx_p (XEXP (x, 1), strict)
2402 && nds32_legitimate_index_p (mode, XEXP (x, 0), strict))
2403 return true;
2404 else
2405 return false;
2406
2407 case LO_SUM:
2408 if (!TARGET_GP_DIRECT)
2409 return true;
2410
2411 default:
2412 return false;
2413 }
2414 }
2415
2416 \f
2417 /* Describing Relative Costs of Operations. */
2418
2419 static int nds32_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2420 reg_class_t from,
2421 reg_class_t to)
2422 {
2423 if (from == HIGH_REGS || to == HIGH_REGS)
2424 return 6;
2425
2426 return 2;
2427 }
2428
2429 static int nds32_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2430 reg_class_t rclass ATTRIBUTE_UNUSED,
2431 bool in ATTRIBUTE_UNUSED)
2432 {
2433 return 8;
2434 }
2435
2436 /* This target hook describes the relative costs of RTL expressions.
2437 Return 'true' when all subexpressions of x have been processed.
2438 Return 'false' to sum the costs of sub-rtx, plus cost of this operation.
2439 Refer to gcc/rtlanal.c for more information. */
2440 static bool
2441 nds32_rtx_costs (rtx x,
2442 int code,
2443 int outer_code,
2444 int opno ATTRIBUTE_UNUSED,
2445 int *total,
2446 bool speed)
2447 {
2448 /* According to 'speed', goto suitable cost model section. */
2449 if (speed)
2450 goto performance_cost;
2451 else
2452 goto size_cost;
2453
2454
2455 performance_cost:
2456 /* This is section for performance cost model. */
2457
2458 /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4.
2459 We treat it as 4-cycle cost for each instruction
2460 under performance consideration. */
2461 switch (code)
2462 {
2463 case SET:
2464 /* For 'SET' rtx, we need to return false
2465 so that it can recursively calculate costs. */
2466 return false;
2467
2468 case USE:
2469 /* Used in combine.c as a marker. */
2470 *total = 0;
2471 break;
2472
2473 case MULT:
2474 *total = COSTS_N_INSNS (1);
2475 break;
2476
2477 case DIV:
2478 case UDIV:
2479 case MOD:
2480 case UMOD:
2481 *total = COSTS_N_INSNS (7);
2482 break;
2483
2484 default:
2485 *total = COSTS_N_INSNS (1);
2486 break;
2487 }
2488
2489 return true;
2490
2491
2492 size_cost:
2493 /* This is section for size cost model. */
2494
2495 /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4.
2496 We treat it as 4-byte cost for each instruction
2497 under code size consideration. */
2498 switch (code)
2499 {
2500 case SET:
2501 /* For 'SET' rtx, we need to return false
2502 so that it can recursively calculate costs. */
2503 return false;
2504
2505 case USE:
2506 /* Used in combine.c as a marker. */
2507 *total = 0;
2508 break;
2509
2510 case CONST_INT:
2511 /* All instructions involving constant operation
2512 need to be considered for cost evaluation. */
2513 if (outer_code == SET)
2514 {
2515 /* (set X imm5s), use movi55, 2-byte cost.
2516 (set X imm20s), use movi, 4-byte cost.
2517 (set X BIG_INT), use sethi/ori, 8-byte cost. */
2518 if (satisfies_constraint_Is05 (x))
2519 *total = COSTS_N_INSNS (1) - 2;
2520 else if (satisfies_constraint_Is20 (x))
2521 *total = COSTS_N_INSNS (1);
2522 else
2523 *total = COSTS_N_INSNS (2);
2524 }
2525 else if (outer_code == PLUS || outer_code == MINUS)
2526 {
2527 /* Possible addi333/subi333 or subi45/addi45, 2-byte cost.
2528 General case, cost 1 instruction with 4-byte. */
2529 if (satisfies_constraint_Iu05 (x))
2530 *total = COSTS_N_INSNS (1) - 2;
2531 else
2532 *total = COSTS_N_INSNS (1);
2533 }
2534 else if (outer_code == ASHIFT)
2535 {
2536 /* Possible slli333, 2-byte cost.
2537 General case, cost 1 instruction with 4-byte. */
2538 if (satisfies_constraint_Iu03 (x))
2539 *total = COSTS_N_INSNS (1) - 2;
2540 else
2541 *total = COSTS_N_INSNS (1);
2542 }
2543 else if (outer_code == ASHIFTRT || outer_code == LSHIFTRT)
2544 {
2545 /* Possible srai45 or srli45, 2-byte cost.
2546 General case, cost 1 instruction with 4-byte. */
2547 if (satisfies_constraint_Iu05 (x))
2548 *total = COSTS_N_INSNS (1) - 2;
2549 else
2550 *total = COSTS_N_INSNS (1);
2551 }
2552 else
2553 {
2554 /* For other cases, simply set it 4-byte cost. */
2555 *total = COSTS_N_INSNS (1);
2556 }
2557 break;
2558
2559 case CONST_DOUBLE:
2560 /* It requires high part and low part processing, set it 8-byte cost. */
2561 *total = COSTS_N_INSNS (2);
2562 break;
2563
2564 default:
2565 /* For other cases, generally we set it 4-byte cost
2566 and stop resurively traversing. */
2567 *total = COSTS_N_INSNS (1);
2568 break;
2569 }
2570
2571 return true;
2572 }
2573
2574 static int nds32_address_cost (rtx address,
2575 enum machine_mode mode ATTRIBUTE_UNUSED,
2576 addr_space_t as ATTRIBUTE_UNUSED,
2577 bool speed)
2578 {
2579 rtx plus0, plus1;
2580 enum rtx_code code;
2581
2582 code = GET_CODE (address);
2583
2584 /* According to 'speed', goto suitable cost model section. */
2585 if (speed)
2586 goto performance_cost;
2587 else
2588 goto size_cost;
2589
2590 performance_cost:
2591 /* This is section for performance cost model. */
2592
2593 /* FALLTHRU, currently we use same cost model as size_cost. */
2594
2595 size_cost:
2596 /* This is section for size cost model. */
2597
2598 switch (code)
2599 {
2600 case POST_MODIFY:
2601 case POST_INC:
2602 case POST_DEC:
2603 /* We encourage that rtx contains
2604 POST_MODIFY/POST_INC/POST_DEC behavior. */
2605 return 0;
2606
2607 case SYMBOL_REF:
2608 /* We can have gp-relative load/store for symbol_ref.
2609 Have it 4-byte cost. */
2610 return COSTS_N_INSNS (1);
2611
2612 case CONST:
2613 /* It is supposed to be the pattern (const (plus symbol_ref const_int)).
2614 Have it 4-byte cost. */
2615 return COSTS_N_INSNS (1);
2616
2617 case REG:
2618 /* Simply return 4-byte costs. */
2619 return COSTS_N_INSNS (1);
2620
2621 case PLUS:
2622 /* We do not need to check if the address is a legitimate address,
2623 because this hook is never called with an invalid address.
2624 But we better check the range of
2625 const_int value for cost, if it exists. */
2626 plus0 = XEXP (address, 0);
2627 plus1 = XEXP (address, 1);
2628
2629 if (REG_P (plus0) && CONST_INT_P (plus1))
2630 {
2631 /* If it is possible to be lwi333/swi333 form,
2632 make it 2-byte cost. */
2633 if (satisfies_constraint_Iu05 (plus1))
2634 return (COSTS_N_INSNS (1) - 2);
2635 else
2636 return COSTS_N_INSNS (1);
2637 }
2638
2639 /* For other 'plus' situation, make it cost 4-byte. */
2640 return COSTS_N_INSNS (1);
2641
2642 default:
2643 break;
2644 }
2645
2646 return COSTS_N_INSNS (4);
2647 }
2648
2649 \f
2650 /* Defining the Output Assembler Language. */
2651
2652 /* -- The Overall Framework of an Assembler File. */
2653
2654 static void
2655 nds32_asm_file_start (void)
2656 {
2657 int i;
2658
2659 default_file_start ();
2660
2661 /* Tell assembler which ABI we are using. */
2662 fprintf (asm_out_file, "\t! ABI version\n");
2663 fprintf (asm_out_file, "\t.abi_2\n");
2664
2665 /* Tell assembler that this asm code is generated by compiler. */
2666 fprintf (asm_out_file, "\t! This asm file is generated by compiler\n");
2667 fprintf (asm_out_file, "\t.flag\tverbatim\n");
2668 /* Give assembler the size of each vector for interrupt handler. */
2669 fprintf (asm_out_file, "\t! This vector size directive is required "
2670 "for checking inconsistency on interrupt handler\n");
2671 fprintf (asm_out_file, "\t.vec_size\t%d\n", nds32_isr_vector_size);
2672
2673 /* If user enables '-mforce-fp-as-gp' or compiles programs with -Os,
2674 the compiler may produce 'la $fp,_FP_BASE_' instruction
2675 at prologue for fp-as-gp optimization.
2676 We should emit weak reference of _FP_BASE_ to avoid undefined reference
2677 in case user does not pass '--relax' option to linker. */
2678 if (TARGET_FORCE_FP_AS_GP || optimize_size)
2679 {
2680 fprintf (asm_out_file, "\t! This weak reference is required to do "
2681 "fp-as-gp link time optimization\n");
2682 fprintf (asm_out_file, "\t.weak\t_FP_BASE_\n");
2683 }
2684 /* If user enables '-mex9', we should emit relaxation directive
2685 to tell linker that this file is allowed to do ex9 optimization. */
2686 if (TARGET_EX9)
2687 {
2688 fprintf (asm_out_file, "\t! This relaxation directive is required "
2689 "to do ex9 link time optimization\n");
2690 fprintf (asm_out_file, "\t.relax\tex9\n");
2691 }
2692
2693 fprintf (asm_out_file, "\t! ------------------------------------\n");
2694
2695 if (TARGET_ISA_V2)
2696 fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V2");
2697 if (TARGET_ISA_V3)
2698 fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V3");
2699 if (TARGET_ISA_V3M)
2700 fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V3M");
2701
2702 fprintf (asm_out_file, "\t! Endian setting\t: %s\n",
2703 ((TARGET_BIG_ENDIAN) ? "big-endian"
2704 : "little-endian"));
2705
2706 fprintf (asm_out_file, "\t! ------------------------------------\n");
2707
2708 fprintf (asm_out_file, "\t! Use conditional move\t\t: %s\n",
2709 ((TARGET_CMOV) ? "Yes"
2710 : "No"));
2711 fprintf (asm_out_file, "\t! Use performance extension\t: %s\n",
2712 ((TARGET_PERF_EXT) ? "Yes"
2713 : "No"));
2714
2715 fprintf (asm_out_file, "\t! ------------------------------------\n");
2716
2717 fprintf (asm_out_file, "\t! V3PUSH instructions\t: %s\n",
2718 ((TARGET_V3PUSH) ? "Yes"
2719 : "No"));
2720 fprintf (asm_out_file, "\t! 16-bit instructions\t: %s\n",
2721 ((TARGET_16_BIT) ? "Yes"
2722 : "No"));
2723 fprintf (asm_out_file, "\t! GP base access\t: %s\n",
2724 ((TARGET_GP_DIRECT) ? "Yes"
2725 : "No"));
2726 fprintf (asm_out_file, "\t! Reduced registers set\t: %s\n",
2727 ((TARGET_REDUCED_REGS) ? "Yes"
2728 : "No"));
2729
2730 fprintf (asm_out_file, "\t! ------------------------------------\n");
2731
2732 if (optimize_size)
2733 fprintf (asm_out_file, "\t! Optimization level\t: -Os\n");
2734 else
2735 fprintf (asm_out_file, "\t! Optimization level\t: -O%d\n", optimize);
2736
2737 fprintf (asm_out_file, "\t! ------------------------------------\n");
2738
2739 fprintf (asm_out_file, "\t! Cache block size\t: %d\n",
2740 nds32_cache_block_size);
2741
2742 fprintf (asm_out_file, "\t! ------------------------------------\n");
2743
2744 /* Initialize isr vector information array before compiling functions. */
2745 for (i = 0; i < NDS32_N_ISR_VECTORS; i++)
2746 {
2747 nds32_isr_vectors[i].category = NDS32_ISR_NONE;
2748 strcpy (nds32_isr_vectors[i].func_name, "");
2749 nds32_isr_vectors[i].save_reg = NDS32_PARTIAL_SAVE;
2750 nds32_isr_vectors[i].nested_type = NDS32_NOT_NESTED;
2751 nds32_isr_vectors[i].total_n_vectors = 0;
2752 strcpy (nds32_isr_vectors[i].nmi_name, "");
2753 strcpy (nds32_isr_vectors[i].warm_name, "");
2754 }
2755 }
2756
2757 static void
2758 nds32_asm_file_end (void)
2759 {
2760 int i;
2761
2762 /* If all the vectors are NDS32_ISR_NONE, we can return immediately. */
2763 for (i = 0; i < NDS32_N_ISR_VECTORS; i++)
2764 if (nds32_isr_vectors[i].category != NDS32_ISR_NONE)
2765 break;
2766
2767 if (i == NDS32_N_ISR_VECTORS)
2768 return;
2769
2770 /* At least one vector is NOT NDS32_ISR_NONE,
2771 we should output isr vector information. */
2772 fprintf (asm_out_file, "\t! ------------------------------------\n");
2773 fprintf (asm_out_file, "\t! The isr vector information:\n");
2774 fprintf (asm_out_file, "\t! ------------------------------------\n");
2775
2776 /* Check reset handler first. Its vector number is always 0. */
2777 if (nds32_isr_vectors[0].category == NDS32_ISR_RESET)
2778 {
2779 nds32_emit_isr_reset_content ();
2780 fprintf (asm_out_file, "\t! ------------------------------------\n");
2781 }
2782
2783 /* Check other vectors, starting from vector number 1. */
2784 for (i = 1; i < NDS32_N_ISR_VECTORS; i++)
2785 {
2786 if (nds32_isr_vectors[i].category == NDS32_ISR_INTERRUPT
2787 || nds32_isr_vectors[i].category == NDS32_ISR_EXCEPTION)
2788 {
2789 /* Found one vector which is interupt or exception.
2790 Output its jmptbl and vector section content. */
2791 fprintf (asm_out_file, "\t! interrupt/exception vector %02d\n", i);
2792 fprintf (asm_out_file, "\t! ------------------------------------\n");
2793 nds32_emit_isr_jmptbl_section (i);
2794 fprintf (asm_out_file, "\t! ....................................\n");
2795 nds32_emit_isr_vector_section (i);
2796 fprintf (asm_out_file, "\t! ------------------------------------\n");
2797 }
2798 }
2799
2800 fprintf (asm_out_file, "\t! ------------------------------------\n");
2801 }
2802
2803 /* -- Output and Generation of Labels. */
2804
2805 static void
2806 nds32_asm_globalize_label (FILE *stream, const char *name)
2807 {
2808 fputs ("\t.global\t", stream);
2809 assemble_name (stream, name);
2810 fputs ("\n", stream);
2811 }
2812
2813 /* -- Output of Assembler Instructions. */
2814
2815 static void
2816 nds32_print_operand (FILE *stream, rtx x, int code)
2817 {
2818 int op_value;
2819
2820 switch (code)
2821 {
2822 case 0 :
2823 /* Do nothing special. */
2824 break;
2825
2826 case 'V':
2827 /* 'x' is supposed to be CONST_INT, get the value. */
2828 gcc_assert (CONST_INT_P (x));
2829 op_value = INTVAL (x);
2830
2831 /* According to the Andes architecture,
2832 the system/user register index range is 0 ~ 1023.
2833 In order to avoid conflict between user-specified-integer value
2834 and enum-specified-register value,
2835 the 'enum nds32_intrinsic_registers' value
2836 in nds32_intrinsic.h starts from 1024. */
2837 if (op_value < 1024 && op_value >= 0)
2838 {
2839 /* If user gives integer value directly (0~1023),
2840 we just print out the value. */
2841 fprintf (stream, "%d", op_value);
2842 }
2843 else if (op_value < 0
2844 || op_value >= ((int) ARRAY_SIZE (nds32_intrinsic_register_names)
2845 + 1024))
2846 {
2847 /* The enum index value for array size is out of range. */
2848 error ("intrinsic register index is out of range");
2849 }
2850 else
2851 {
2852 /* If user applies normal way with __NDS32_REG_XXX__ enum data,
2853 we can print out register name. Remember to substract 1024. */
2854 fprintf (stream, "%s",
2855 nds32_intrinsic_register_names[op_value - 1024]);
2856 }
2857
2858 /* No need to handle following process, so return immediately. */
2859 return;
2860
2861 default :
2862 /* Unknown flag. */
2863 output_operand_lossage ("invalid operand output code");
2864 break;
2865 }
2866
2867 switch (GET_CODE (x))
2868 {
2869 case LABEL_REF:
2870 case SYMBOL_REF:
2871 output_addr_const (stream, x);
2872 break;
2873
2874 case REG:
2875 /* Forbid using static chain register ($r16)
2876 on reduced-set registers configuration. */
2877 if (TARGET_REDUCED_REGS
2878 && REGNO (x) == STATIC_CHAIN_REGNUM)
2879 sorry ("a nested function is not supported for reduced registers");
2880
2881 /* Normal cases, print out register name. */
2882 fputs (reg_names[REGNO (x)], stream);
2883 break;
2884
2885 case MEM:
2886 output_address (XEXP (x, 0));
2887 break;
2888
2889 case CODE_LABEL:
2890 case CONST_INT:
2891 case CONST:
2892 output_addr_const (stream, x);
2893 break;
2894
2895 default:
2896 /* Generally, output_addr_const () is able to handle most cases.
2897 We want to see what CODE could appear,
2898 so we use gcc_unreachable() to stop it. */
2899 debug_rtx (x);
2900 gcc_unreachable ();
2901 break;
2902 }
2903 }
2904
2905 static void
2906 nds32_print_operand_address (FILE *stream, rtx x)
2907 {
2908 rtx op0, op1;
2909
2910 switch (GET_CODE (x))
2911 {
2912 case SYMBOL_REF:
2913 case CONST:
2914 /* [ + symbol_ref] */
2915 /* [ + const_addr], where const_addr = symbol_ref + const_int */
2916 fputs ("[ + ", stream);
2917 output_addr_const (stream, x);
2918 fputs ("]", stream);
2919 break;
2920
2921 case REG:
2922 /* Forbid using static chain register ($r16)
2923 on reduced-set registers configuration. */
2924 if (TARGET_REDUCED_REGS
2925 && REGNO (x) == STATIC_CHAIN_REGNUM)
2926 sorry ("a nested function is not supported for reduced registers");
2927
2928 /* [Ra] */
2929 fprintf (stream, "[%s]", reg_names[REGNO (x)]);
2930 break;
2931
2932 case PLUS:
2933 op0 = XEXP (x, 0);
2934 op1 = XEXP (x, 1);
2935
2936 /* Checking op0, forbid using static chain register ($r16)
2937 on reduced-set registers configuration. */
2938 if (TARGET_REDUCED_REGS
2939 && REG_P (op0)
2940 && REGNO (op0) == STATIC_CHAIN_REGNUM)
2941 sorry ("a nested function is not supported for reduced registers");
2942 /* Checking op1, forbid using static chain register ($r16)
2943 on reduced-set registers configuration. */
2944 if (TARGET_REDUCED_REGS
2945 && REG_P (op1)
2946 && REGNO (op1) == STATIC_CHAIN_REGNUM)
2947 sorry ("a nested function is not supported for reduced registers");
2948
2949 if (REG_P (op0) && CONST_INT_P (op1))
2950 {
2951 /* [Ra + imm] */
2952 fprintf (stream, "[%s + (%d)]",
2953 reg_names[REGNO (op0)], (int)INTVAL (op1));
2954 }
2955 else if (REG_P (op0) && REG_P (op1))
2956 {
2957 /* [Ra + Rb] */
2958 fprintf (stream, "[%s + %s]",
2959 reg_names[REGNO (op0)], reg_names[REGNO (op1)]);
2960 }
2961 else if (GET_CODE (op0) == MULT && REG_P (op1))
2962 {
2963 /* [Ra + Rb << sv]
2964 From observation, the pattern looks like:
2965 (plus:SI (mult:SI (reg:SI 58)
2966 (const_int 4 [0x4]))
2967 (reg/f:SI 57)) */
2968 int sv;
2969
2970 /* We need to set sv to output shift value. */
2971 if (INTVAL (XEXP (op0, 1)) == 1)
2972 sv = 0;
2973 else if (INTVAL (XEXP (op0, 1)) == 2)
2974 sv = 1;
2975 else if (INTVAL (XEXP (op0, 1)) == 4)
2976 sv = 2;
2977 else
2978 gcc_unreachable ();
2979
2980 fprintf (stream, "[%s + %s << %d]",
2981 reg_names[REGNO (op1)],
2982 reg_names[REGNO (XEXP (op0, 0))],
2983 sv);
2984 }
2985 else
2986 {
2987 /* The control flow is not supposed to be here. */
2988 debug_rtx (x);
2989 gcc_unreachable ();
2990 }
2991
2992 break;
2993
2994 case POST_MODIFY:
2995 /* (post_modify (regA) (plus (regA) (regB)))
2996 (post_modify (regA) (plus (regA) (const_int)))
2997 We would like to extract
2998 regA and regB (or const_int) from plus rtx. */
2999 op0 = XEXP (XEXP (x, 1), 0);
3000 op1 = XEXP (XEXP (x, 1), 1);
3001
3002 /* Checking op0, forbid using static chain register ($r16)
3003 on reduced-set registers configuration. */
3004 if (TARGET_REDUCED_REGS
3005 && REG_P (op0)
3006 && REGNO (op0) == STATIC_CHAIN_REGNUM)
3007 sorry ("a nested function is not supported for reduced registers");
3008 /* Checking op1, forbid using static chain register ($r16)
3009 on reduced-set registers configuration. */
3010 if (TARGET_REDUCED_REGS
3011 && REG_P (op1)
3012 && REGNO (op1) == STATIC_CHAIN_REGNUM)
3013 sorry ("a nested function is not supported for reduced registers");
3014
3015 if (REG_P (op0) && REG_P (op1))
3016 {
3017 /* [Ra], Rb */
3018 fprintf (stream, "[%s], %s",
3019 reg_names[REGNO (op0)], reg_names[REGNO (op1)]);
3020 }
3021 else if (REG_P (op0) && CONST_INT_P (op1))
3022 {
3023 /* [Ra], imm */
3024 fprintf (stream, "[%s], %d",
3025 reg_names[REGNO (op0)], (int)INTVAL (op1));
3026 }
3027 else
3028 {
3029 /* The control flow is not supposed to be here. */
3030 debug_rtx (x);
3031 gcc_unreachable ();
3032 }
3033
3034 break;
3035
3036 case POST_INC:
3037 case POST_DEC:
3038 op0 = XEXP (x, 0);
3039
3040 /* Checking op0, forbid using static chain register ($r16)
3041 on reduced-set registers configuration. */
3042 if (TARGET_REDUCED_REGS
3043 && REG_P (op0)
3044 && REGNO (op0) == STATIC_CHAIN_REGNUM)
3045 sorry ("a nested function is not supported for reduced registers");
3046
3047 if (REG_P (op0))
3048 {
3049 /* "[Ra], 1/2/4" or "[Ra], -1/-2/-4"
3050 The 1/2/4 or -1/-2/-4 have been displayed in nds32.md.
3051 We only need to deal with register Ra. */
3052 fprintf (stream, "[%s]", reg_names[REGNO (op0)]);
3053 }
3054 else
3055 {
3056 /* The control flow is not supposed to be here. */
3057 debug_rtx (x);
3058 gcc_unreachable ();
3059 }
3060
3061 break;
3062
3063 default :
3064 /* Generally, output_addr_const () is able to handle most cases.
3065 We want to see what CODE could appear,
3066 so we use gcc_unreachable() to stop it. */
3067 debug_rtx (x);
3068 gcc_unreachable ();
3069 break;
3070 }
3071 }
3072
3073 \f
3074 /* Defining target-specific uses of __attribute__. */
3075
3076 /* Add some checking after merging attributes. */
3077 static tree
3078 nds32_merge_decl_attributes (tree olddecl, tree newdecl)
3079 {
3080 tree combined_attrs;
3081
3082 /* Create combined attributes. */
3083 combined_attrs = merge_attributes (DECL_ATTRIBUTES (olddecl),
3084 DECL_ATTRIBUTES (newdecl));
3085
3086 /* Since newdecl is acutally a duplicate of olddecl,
3087 we can take olddecl for some operations. */
3088 if (TREE_CODE (olddecl) == FUNCTION_DECL)
3089 {
3090 /* Check isr-specific attributes conflict. */
3091 nds32_check_isr_attrs_conflict (olddecl, combined_attrs);
3092 }
3093
3094 return combined_attrs;
3095 }
3096
3097 /* Add some checking when inserting attributes. */
3098 static void
3099 nds32_insert_attributes (tree decl, tree *attributes)
3100 {
3101 /* For function declaration, we need to check isr-specific attributes:
3102 1. Call nds32_check_isr_attrs_conflict() to check any conflict.
3103 2. Check valid integer value for interrupt/exception.
3104 3. Check valid integer value for reset.
3105 4. Check valid function for nmi/warm. */
3106 if (TREE_CODE (decl) == FUNCTION_DECL)
3107 {
3108 tree func_attrs;
3109 tree intr, excp, reset;
3110
3111 /* Pick up function attributes. */
3112 func_attrs = *attributes;
3113
3114 /* 1. Call nds32_check_isr_attrs_conflict() to check any conflict. */
3115 nds32_check_isr_attrs_conflict (decl, func_attrs);
3116
3117 /* Now we are starting to check valid id value
3118 for interrupt/exception/reset.
3119 Note that we ONLY check its validity here.
3120 To construct isr vector information, it is still performed
3121 by nds32_construct_isr_vectors_information(). */
3122 intr = lookup_attribute ("interrupt", func_attrs);
3123 excp = lookup_attribute ("exception", func_attrs);
3124 reset = lookup_attribute ("reset", func_attrs);
3125
3126 if (intr || excp)
3127 {
3128 /* Deal with interrupt/exception. */
3129 tree id_list;
3130 unsigned int lower_bound, upper_bound;
3131
3132 /* The way to handle interrupt or exception is the same,
3133 we just need to take care of actual vector number.
3134 For interrupt(0..63), the actual vector number is (9..72).
3135 For exception(1..8), the actual vector number is (1..8). */
3136 lower_bound = (intr) ? (0) : (1);
3137 upper_bound = (intr) ? (63) : (8);
3138
3139 /* Prepare id list so that we can traverse id value. */
3140 id_list = (intr) ? (TREE_VALUE (intr)) : (TREE_VALUE (excp));
3141
3142 /* 2. Check valid integer value for interrupt/exception. */
3143 while (id_list)
3144 {
3145 tree id;
3146
3147 /* Pick up each vector id value. */
3148 id = TREE_VALUE (id_list);
3149 /* Issue error if it is not a valid integer value. */
3150 if (TREE_CODE (id) != INTEGER_CST
3151 || wi::ltu_p (id, lower_bound)
3152 || wi::gtu_p (id, upper_bound))
3153 error ("invalid id value for interrupt/exception attribute");
3154
3155 /* Advance to next id. */
3156 id_list = TREE_CHAIN (id_list);
3157 }
3158 }
3159 else if (reset)
3160 {
3161 /* Deal with reset. */
3162 tree id_list;
3163 tree id;
3164 tree nmi, warm;
3165 unsigned int lower_bound;
3166 unsigned int upper_bound;
3167
3168 /* Prepare id_list and identify id value so that
3169 we can check if total number of vectors is valid. */
3170 id_list = TREE_VALUE (reset);
3171 id = TREE_VALUE (id_list);
3172
3173 /* The maximum numbers for user's interrupt is 64. */
3174 lower_bound = 0;
3175 upper_bound = 64;
3176
3177 /* 3. Check valid integer value for reset. */
3178 if (TREE_CODE (id) != INTEGER_CST
3179 || wi::ltu_p (id, lower_bound)
3180 || wi::gtu_p (id, upper_bound))
3181 error ("invalid id value for reset attribute");
3182
3183 /* 4. Check valid function for nmi/warm. */
3184 nmi = lookup_attribute ("nmi", func_attrs);
3185 warm = lookup_attribute ("warm", func_attrs);
3186
3187 if (nmi != NULL_TREE)
3188 {
3189 tree nmi_func_list;
3190 tree nmi_func;
3191
3192 nmi_func_list = TREE_VALUE (nmi);
3193 nmi_func = TREE_VALUE (nmi_func_list);
3194
3195 /* Issue error if it is not a valid nmi function. */
3196 if (TREE_CODE (nmi_func) != IDENTIFIER_NODE)
3197 error ("invalid nmi function for reset attribute");
3198 }
3199
3200 if (warm != NULL_TREE)
3201 {
3202 tree warm_func_list;
3203 tree warm_func;
3204
3205 warm_func_list = TREE_VALUE (warm);
3206 warm_func = TREE_VALUE (warm_func_list);
3207
3208 /* Issue error if it is not a valid warm function. */
3209 if (TREE_CODE (warm_func) != IDENTIFIER_NODE)
3210 error ("invalid warm function for reset attribute");
3211 }
3212 }
3213 else
3214 {
3215 /* No interrupt, exception, or reset attribute is set. */
3216 return;
3217 }
3218 }
3219 }
3220
3221 static bool
3222 nds32_option_pragma_parse (tree args ATTRIBUTE_UNUSED,
3223 tree pop_target ATTRIBUTE_UNUSED)
3224 {
3225 /* Currently, we do not parse any pragma target by ourself,
3226 so just simply return false. */
3227 return false;
3228 }
3229
3230 static void
3231 nds32_option_override (void)
3232 {
3233 /* After all the command options have been parsed,
3234 we shall deal with some flags for changing compiler settings. */
3235
3236 /* At first, we check if we have to strictly
3237 set some flags based on ISA family. */
3238 if (TARGET_ISA_V2)
3239 {
3240 /* Under V2 ISA, we need to strictly disable TARGET_V3PUSH. */
3241 target_flags &= ~MASK_V3PUSH;
3242 }
3243 if (TARGET_ISA_V3)
3244 {
3245 /* Under V3 ISA, currently nothing should be strictly set. */
3246 }
3247 if (TARGET_ISA_V3M)
3248 {
3249 /* Under V3M ISA, we need to strictly enable TARGET_REDUCED_REGS. */
3250 target_flags |= MASK_REDUCED_REGS;
3251 /* Under V3M ISA, we need to strictly disable TARGET_PERF_EXT. */
3252 target_flags &= ~MASK_PERF_EXT;
3253 }
3254
3255 /* See if we are using reduced-set registers:
3256 $r0~$r5, $r6~$r10, $r15, $r28, $r29, $r30, $r31
3257 If so, we must forbid using $r11~$r14, $r16~$r27. */
3258 if (TARGET_REDUCED_REGS)
3259 {
3260 int r;
3261
3262 /* Prevent register allocator from
3263 choosing it as doing register allocation. */
3264 for (r = 11; r <= 14; r++)
3265 fixed_regs[r] = call_used_regs[r] = 1;
3266 for (r = 16; r <= 27; r++)
3267 fixed_regs[r] = call_used_regs[r] = 1;
3268 }
3269
3270 /* See if user explicitly would like to use fp-as-gp optimization.
3271 If so, we must prevent $fp from being allocated
3272 during register allocation. */
3273 if (TARGET_FORCE_FP_AS_GP)
3274 fixed_regs[FP_REGNUM] = call_used_regs[FP_REGNUM] = 1;
3275
3276 if (!TARGET_16_BIT)
3277 {
3278 /* Under no 16 bit ISA, we need to strictly disable TARGET_V3PUSH. */
3279 target_flags &= ~MASK_V3PUSH;
3280 }
3281
3282 /* Currently, we don't support PIC code generation yet. */
3283 if (flag_pic)
3284 sorry ("not support -fpic");
3285 }
3286
3287 \f
3288 /* Miscellaneous Parameters. */
3289
3290 static void
3291 nds32_init_builtins (void)
3292 {
3293 tree pointer_type_node = build_pointer_type (integer_type_node);
3294
3295 tree void_ftype_void = build_function_type (void_type_node,
3296 void_list_node);
3297
3298 tree void_ftype_pint = build_function_type_list (void_type_node,
3299 pointer_type_node,
3300 NULL_TREE);
3301
3302 tree int_ftype_int = build_function_type_list (integer_type_node,
3303 integer_type_node,
3304 NULL_TREE);
3305
3306 tree void_ftype_int_int = build_function_type_list (void_type_node,
3307 integer_type_node,
3308 integer_type_node,
3309 NULL_TREE);
3310
3311 /* Cache. */
3312 add_builtin_function ("__builtin_nds32_isync", void_ftype_pint,
3313 NDS32_BUILTIN_ISYNC,
3314 BUILT_IN_MD, NULL, NULL_TREE);
3315 add_builtin_function ("__builtin_nds32_isb", void_ftype_void,
3316 NDS32_BUILTIN_ISB,
3317 BUILT_IN_MD, NULL, NULL_TREE);
3318
3319 /* Register Transfer. */
3320 add_builtin_function ("__builtin_nds32_mfsr", int_ftype_int,
3321 NDS32_BUILTIN_MFSR,
3322 BUILT_IN_MD, NULL, NULL_TREE);
3323 add_builtin_function ("__builtin_nds32_mfusr", int_ftype_int,
3324 NDS32_BUILTIN_MFUSR,
3325 BUILT_IN_MD, NULL, NULL_TREE);
3326 add_builtin_function ("__builtin_nds32_mtsr", void_ftype_int_int,
3327 NDS32_BUILTIN_MTSR,
3328 BUILT_IN_MD, NULL, NULL_TREE);
3329 add_builtin_function ("__builtin_nds32_mtusr", void_ftype_int_int,
3330 NDS32_BUILTIN_MTUSR,
3331 BUILT_IN_MD, NULL, NULL_TREE);
3332
3333 /* Interrupt. */
3334 add_builtin_function ("__builtin_nds32_setgie_en", void_ftype_void,
3335 NDS32_BUILTIN_SETGIE_EN,
3336 BUILT_IN_MD, NULL, NULL_TREE);
3337 add_builtin_function ("__builtin_nds32_setgie_dis", void_ftype_void,
3338 NDS32_BUILTIN_SETGIE_DIS,
3339 BUILT_IN_MD, NULL, NULL_TREE);
3340 }
3341
3342 static rtx
3343 nds32_expand_builtin (tree exp,
3344 rtx target,
3345 rtx subtarget ATTRIBUTE_UNUSED,
3346 enum machine_mode mode ATTRIBUTE_UNUSED,
3347 int ignore ATTRIBUTE_UNUSED)
3348 {
3349 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
3350
3351 int fcode = DECL_FUNCTION_CODE (fndecl);
3352
3353 switch (fcode)
3354 {
3355 /* Cache. */
3356 case NDS32_BUILTIN_ISYNC:
3357 return nds32_expand_builtin_null_ftype_reg
3358 (CODE_FOR_unspec_volatile_isync, exp, target);
3359 case NDS32_BUILTIN_ISB:
3360 /* Since there are no result and operands for isb instruciton,
3361 we can simply emit this rtx. */
3362 emit_insn (gen_unspec_volatile_isb ());
3363 return target;
3364
3365 /* Register Transfer. */
3366 case NDS32_BUILTIN_MFSR:
3367 return nds32_expand_builtin_reg_ftype_imm
3368 (CODE_FOR_unspec_volatile_mfsr, exp, target);
3369 case NDS32_BUILTIN_MFUSR:
3370 return nds32_expand_builtin_reg_ftype_imm
3371 (CODE_FOR_unspec_volatile_mfusr, exp, target);
3372 case NDS32_BUILTIN_MTSR:
3373 return nds32_expand_builtin_null_ftype_reg_imm
3374 (CODE_FOR_unspec_volatile_mtsr, exp, target);
3375 case NDS32_BUILTIN_MTUSR:
3376 return nds32_expand_builtin_null_ftype_reg_imm
3377 (CODE_FOR_unspec_volatile_mtusr, exp, target);
3378
3379 /* Interrupt. */
3380 case NDS32_BUILTIN_SETGIE_EN:
3381 /* Since there are no result and operands for setgie.e instruciton,
3382 we can simply emit this rtx. */
3383 emit_insn (gen_unspec_volatile_setgie_en ());
3384 return target;
3385 case NDS32_BUILTIN_SETGIE_DIS:
3386 /* Since there are no result and operands for setgie.d instruciton,
3387 we can simply emit this rtx. */
3388 emit_insn (gen_unspec_volatile_setgie_dis ());
3389 return target;
3390
3391 default:
3392 gcc_unreachable ();
3393 }
3394
3395 return NULL_RTX;
3396 }
3397
3398
3399 /* ------------------------------------------------------------------------ */
3400
3401 /* PART 4: Implemet extern function definitions,
3402 the prototype is in nds32-protos.h. */
3403 \f
3404 /* Defining Data Structures for Per-function Information. */
3405
3406 void
3407 nds32_init_expanders (void)
3408 {
3409 /* Arrange to initialize and mark the machine per-function status. */
3410 init_machine_status = nds32_init_machine_status;
3411 }
3412
3413 \f
3414 /* Register Usage. */
3415
3416 /* -- How Values Fit in Registers. */
3417
3418 int
3419 nds32_hard_regno_nregs (int regno ATTRIBUTE_UNUSED,
3420 enum machine_mode mode)
3421 {
3422 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
3423 }
3424
3425 int
3426 nds32_hard_regno_mode_ok (int regno, enum machine_mode mode)
3427 {
3428 /* Restrict double-word quantities to even register pairs. */
3429 if (HARD_REGNO_NREGS (regno, mode) == 1
3430 || !((regno) & 1))
3431 return 1;
3432
3433 return 0;
3434 }
3435
3436 \f
3437 /* Register Classes. */
3438
3439 enum reg_class
3440 nds32_regno_reg_class (int regno)
3441 {
3442 /* Refer to nds32.h for more register class details. */
3443
3444 if (regno >= 0 && regno <= 7)
3445 return LOW_REGS;
3446 else if (regno >= 8 && regno <= 11)
3447 return MIDDLE_REGS;
3448 else if (regno >= 12 && regno <= 14)
3449 return HIGH_REGS;
3450 else if (regno == 15)
3451 return R15_TA_REG;
3452 else if (regno >= 16 && regno <= 19)
3453 return MIDDLE_REGS;
3454 else if (regno >= 20 && regno <= 31)
3455 return HIGH_REGS;
3456 else if (regno == 32 || regno == 33)
3457 return FRAME_REGS;
3458 else
3459 return NO_REGS;
3460 }
3461
3462 \f
3463 /* Stack Layout and Calling Conventions. */
3464
3465 /* -- Basic Stack Layout. */
3466
3467 rtx
3468 nds32_return_addr_rtx (int count,
3469 rtx frameaddr ATTRIBUTE_UNUSED)
3470 {
3471 /* There is no way to determine the return address
3472 if frameaddr is the frame that has 'count' steps
3473 up from current frame. */
3474 if (count != 0)
3475 return NULL_RTX;
3476
3477 /* If count == 0, it means we are at current frame,
3478 the return address is $r30 ($lp). */
3479 return get_hard_reg_initial_val (Pmode, LP_REGNUM);
3480 }
3481
3482 /* -- Eliminating Frame Pointer and Arg Pointer. */
3483
3484 HOST_WIDE_INT
3485 nds32_initial_elimination_offset (unsigned int from_reg, unsigned int to_reg)
3486 {
3487 HOST_WIDE_INT offset;
3488
3489 /* Compute and setup stack frame size.
3490 The result will be in cfun->machine. */
3491 nds32_compute_stack_frame ();
3492
3493 /* Remember to consider
3494 cfun->machine->callee_saved_area_padding_bytes
3495 when calculating offset. */
3496 if (from_reg == ARG_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM)
3497 {
3498 offset = (cfun->machine->fp_size
3499 + cfun->machine->gp_size
3500 + cfun->machine->lp_size
3501 + cfun->machine->callee_saved_regs_size
3502 + cfun->machine->callee_saved_area_padding_bytes
3503 + cfun->machine->local_size
3504 + cfun->machine->out_args_size);
3505 }
3506 else if (from_reg == ARG_POINTER_REGNUM
3507 && to_reg == HARD_FRAME_POINTER_REGNUM)
3508 {
3509 offset = 0;
3510 }
3511 else if (from_reg == FRAME_POINTER_REGNUM
3512 && to_reg == STACK_POINTER_REGNUM)
3513 {
3514 offset = (cfun->machine->local_size + cfun->machine->out_args_size);
3515 }
3516 else if (from_reg == FRAME_POINTER_REGNUM
3517 && to_reg == HARD_FRAME_POINTER_REGNUM)
3518 {
3519 offset = (-1) * (cfun->machine->fp_size
3520 + cfun->machine->gp_size
3521 + cfun->machine->lp_size
3522 + cfun->machine->callee_saved_regs_size
3523 + cfun->machine->callee_saved_area_padding_bytes);
3524 }
3525 else
3526 {
3527 gcc_unreachable ();
3528 }
3529
3530 return offset;
3531 }
3532
3533 /* -- Passing Arguments in Registers. */
3534
3535 void
3536 nds32_init_cumulative_args (CUMULATIVE_ARGS *cum,
3537 tree fntype ATTRIBUTE_UNUSED,
3538 rtx libname ATTRIBUTE_UNUSED,
3539 tree fndecl ATTRIBUTE_UNUSED,
3540 int n_named_args ATTRIBUTE_UNUSED)
3541 {
3542 /* Initial available registers
3543 (in offset, corresponding to NDS32_GPR_ARG_FIRST_REGNUM)
3544 for passing arguments. */
3545 cum->reg_offset = 0;
3546 }
3547
3548 /* -- Function Entry and Exit. */
3549
3550 /* Function for normal multiple push prologue. */
3551 void
3552 nds32_expand_prologue (void)
3553 {
3554 int fp_adjust;
3555 int sp_adjust;
3556 int en4_const;
3557
3558 rtx Rb, Re;
3559 rtx push_insn;
3560 rtx fp_adjust_insn, sp_adjust_insn;
3561
3562 /* Before computing everything for stack frame size,
3563 we check if it is still worth to use fp_as_gp optimization.
3564 If it is, the 'df_regs_ever_live_p (FP_REGNUM)' will be set
3565 so that $fp will be saved on stack. */
3566 cfun->machine->fp_as_gp_p = nds32_fp_as_gp_check_available ();
3567
3568 /* Compute and setup stack frame size.
3569 The result will be in cfun->machine. */
3570 nds32_compute_stack_frame ();
3571
3572 /* If the function is 'naked',
3573 we do not have to generate prologue code fragment. */
3574 if (cfun->machine->naked_p)
3575 return;
3576
3577 /* Get callee_first_regno and callee_last_regno. */
3578 Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno);
3579 Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno);
3580
3581 /* push_insn = gen_stack_push_multiple(first_regno, last_regno),
3582 the pattern 'stack_push_multiple' is implemented in nds32.md.
3583 For En4 field, we have to calculate its constant value.
3584 Refer to Andes ISA for more information. */
3585 en4_const = 0;
3586 if (cfun->machine->fp_size)
3587 en4_const += 8;
3588 if (cfun->machine->gp_size)
3589 en4_const += 4;
3590 if (cfun->machine->lp_size)
3591 en4_const += 2;
3592
3593 /* If $fp, $gp, $lp, and all callee-save registers are NOT required
3594 to be saved, we don't have to create multiple push instruction.
3595 Otherwise, a multiple push instruction is needed. */
3596 if (!(REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM && en4_const == 0))
3597 {
3598 /* Create multiple push instruction rtx. */
3599 push_insn = nds32_gen_stack_push_multiple (Rb, Re, GEN_INT (en4_const));
3600 /* Emit rtx into instructions list and receive INSN rtx form. */
3601 push_insn = emit_insn (push_insn);
3602
3603 /* The insn rtx 'push_insn' will change frame layout.
3604 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3605 generate CFI (Call Frame Information) stuff. */
3606 RTX_FRAME_RELATED_P (push_insn) = 1;
3607 }
3608
3609 /* Check frame_pointer_needed to see
3610 if we shall emit fp adjustment instruction. */
3611 if (frame_pointer_needed)
3612 {
3613 /* adjust $fp = $sp + ($fp size) + ($gp size) + ($lp size)
3614 + (4 * callee-saved-registers)
3615 Note: No need to adjust
3616 cfun->machine->callee_saved_area_padding_bytes,
3617 because, at this point, stack pointer is just
3618 at the position after push instruction. */
3619 fp_adjust = cfun->machine->fp_size
3620 + cfun->machine->gp_size
3621 + cfun->machine->lp_size
3622 + cfun->machine->callee_saved_regs_size;
3623 fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx,
3624 stack_pointer_rtx,
3625 GEN_INT (fp_adjust));
3626 /* Emit rtx into instructions list and receive INSN rtx form. */
3627 fp_adjust_insn = emit_insn (fp_adjust_insn);
3628 }
3629
3630 /* Adjust $sp = $sp - local_size - out_args_size
3631 - callee_saved_area_padding_bytes. */
3632 sp_adjust = cfun->machine->local_size
3633 + cfun->machine->out_args_size
3634 + cfun->machine->callee_saved_area_padding_bytes;
3635 /* sp_adjust value may be out of range of the addi instruction,
3636 create alternative add behavior with TA_REGNUM if necessary,
3637 using NEGATIVE value to tell that we are decreasing address. */
3638 sp_adjust = nds32_force_addi_stack_int ( (-1) * sp_adjust);
3639 if (sp_adjust)
3640 {
3641 /* Generate sp adjustment instruction if and only if sp_adjust != 0. */
3642 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
3643 stack_pointer_rtx,
3644 GEN_INT (-1 * sp_adjust));
3645 /* Emit rtx into instructions list and receive INSN rtx form. */
3646 sp_adjust_insn = emit_insn (sp_adjust_insn);
3647
3648 /* The insn rtx 'sp_adjust_insn' will change frame layout.
3649 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3650 generate CFI (Call Frame Information) stuff. */
3651 RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
3652 }
3653
3654 /* Prevent the instruction scheduler from
3655 moving instructions across the boundary. */
3656 emit_insn (gen_blockage ());
3657 }
3658
3659 /* Function for normal multiple pop epilogue. */
3660 void
3661 nds32_expand_epilogue (void)
3662 {
3663 int sp_adjust;
3664 int en4_const;
3665
3666 rtx Rb, Re;
3667 rtx pop_insn;
3668 rtx sp_adjust_insn;
3669
3670 /* Compute and setup stack frame size.
3671 The result will be in cfun->machine. */
3672 nds32_compute_stack_frame ();
3673
3674 /* Prevent the instruction scheduler from
3675 moving instructions across the boundary. */
3676 emit_insn (gen_blockage ());
3677
3678 /* If the function is 'naked', we do not have to generate
3679 epilogue code fragment BUT 'ret' instruction. */
3680 if (cfun->machine->naked_p)
3681 {
3682 /* Generate return instruction by using
3683 unspec_volatile_func_return pattern.
3684 Make sure this instruction is after gen_blockage().
3685 NOTE that $lp will become 'live'
3686 after this instruction has been emitted. */
3687 emit_insn (gen_unspec_volatile_func_return ());
3688 return;
3689 }
3690
3691 if (frame_pointer_needed)
3692 {
3693 /* adjust $sp = $fp - ($fp size) - ($gp size) - ($lp size)
3694 - (4 * callee-saved-registers)
3695 Note: No need to adjust
3696 cfun->machine->callee_saved_area_padding_bytes,
3697 because we want to adjust stack pointer
3698 to the position for pop instruction. */
3699 sp_adjust = cfun->machine->fp_size
3700 + cfun->machine->gp_size
3701 + cfun->machine->lp_size
3702 + cfun->machine->callee_saved_regs_size;
3703 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
3704 hard_frame_pointer_rtx,
3705 GEN_INT (-1 * sp_adjust));
3706 /* Emit rtx into instructions list and receive INSN rtx form. */
3707 sp_adjust_insn = emit_insn (sp_adjust_insn);
3708 }
3709 else
3710 {
3711 /* If frame pointer is NOT needed,
3712 we cannot calculate the sp adjustment from frame pointer.
3713 Instead, we calculate the adjustment by local_size,
3714 out_args_size, and callee_saved_area_padding_bytes.
3715 Notice that such sp adjustment value may be out of range,
3716 so we have to deal with it as well. */
3717
3718 /* Adjust $sp = $sp + local_size + out_args_size
3719 + callee_saved_area_padding_bytes. */
3720 sp_adjust = cfun->machine->local_size
3721 + cfun->machine->out_args_size
3722 + cfun->machine->callee_saved_area_padding_bytes;
3723 /* sp_adjust value may be out of range of the addi instruction,
3724 create alternative add behavior with TA_REGNUM if necessary,
3725 using POSITIVE value to tell that we are increasing address. */
3726 sp_adjust = nds32_force_addi_stack_int (sp_adjust);
3727 if (sp_adjust)
3728 {
3729 /* Generate sp adjustment instruction
3730 if and only if sp_adjust != 0. */
3731 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
3732 stack_pointer_rtx,
3733 GEN_INT (sp_adjust));
3734 /* Emit rtx into instructions list and receive INSN rtx form. */
3735 sp_adjust_insn = emit_insn (sp_adjust_insn);
3736 }
3737 }
3738
3739 /* Get callee_first_regno and callee_last_regno. */
3740 Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno);
3741 Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno);
3742
3743 /* pop_insn = gen_stack_pop_multiple(first_regno, last_regno),
3744 the pattern 'stack_pop_multiple' is implementad in nds32.md.
3745 For En4 field, we have to calculate its constant value.
3746 Refer to Andes ISA for more information. */
3747 en4_const = 0;
3748 if (cfun->machine->fp_size)
3749 en4_const += 8;
3750 if (cfun->machine->gp_size)
3751 en4_const += 4;
3752 if (cfun->machine->lp_size)
3753 en4_const += 2;
3754
3755 /* If $fp, $gp, $lp, and all callee-save registers are NOT required
3756 to be saved, we don't have to create multiple pop instruction.
3757 Otherwise, a multiple pop instruction is needed. */
3758 if (!(REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM && en4_const == 0))
3759 {
3760 /* Create multiple pop instruction rtx. */
3761 pop_insn = nds32_gen_stack_pop_multiple (Rb, Re, GEN_INT (en4_const));
3762 /* Emit pop instruction. */
3763 emit_insn (pop_insn);
3764 }
3765
3766 /* Generate return instruction by using
3767 unspec_volatile_func_return pattern. */
3768 emit_insn (gen_unspec_volatile_func_return ());
3769 }
3770
3771 /* Function for v3push prologue. */
3772 void
3773 nds32_expand_prologue_v3push (void)
3774 {
3775 int fp_adjust;
3776 int sp_adjust;
3777
3778 rtx Rb, Re;
3779 rtx push_insn;
3780 rtx fp_adjust_insn, sp_adjust_insn;
3781
3782 /* Before computing everything for stack frame size,
3783 we check if it is still worth to use fp_as_gp optimization.
3784 If it is, the 'df_regs_ever_live_p (FP_REGNUM)' will be set
3785 so that $fp will be saved on stack. */
3786 cfun->machine->fp_as_gp_p = nds32_fp_as_gp_check_available ();
3787
3788 /* Compute and setup stack frame size.
3789 The result will be in cfun->machine. */
3790 nds32_compute_stack_frame ();
3791
3792 /* If the function is 'naked',
3793 we do not have to generate prologue code fragment. */
3794 if (cfun->machine->naked_p)
3795 return;
3796
3797 /* Get callee_first_regno and callee_last_regno. */
3798 Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno);
3799 Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno);
3800
3801 /* Calculate sp_adjust first to test if 'push25 Re,imm8u' is available,
3802 where imm8u has to be 8-byte alignment. */
3803 sp_adjust = cfun->machine->local_size
3804 + cfun->machine->out_args_size
3805 + cfun->machine->callee_saved_area_padding_bytes;
3806
3807 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
3808 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust))
3809 {
3810 /* We can use 'push25 Re,imm8u'. */
3811
3812 /* push_insn = gen_stack_v3push(last_regno, sp_adjust),
3813 the pattern 'stack_v3push' is implemented in nds32.md.
3814 The (const_int 14) means v3push always push { $fp $gp $lp }. */
3815 push_insn = nds32_gen_stack_v3push (Rb, Re,
3816 GEN_INT (14), GEN_INT (sp_adjust));
3817 /* emit rtx into instructions list and receive INSN rtx form */
3818 push_insn = emit_insn (push_insn);
3819
3820 /* The insn rtx 'push_insn' will change frame layout.
3821 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3822 generate CFI (Call Frame Information) stuff. */
3823 RTX_FRAME_RELATED_P (push_insn) = 1;
3824
3825 /* Check frame_pointer_needed to see
3826 if we shall emit fp adjustment instruction. */
3827 if (frame_pointer_needed)
3828 {
3829 /* adjust $fp = $sp + 4 ($fp size)
3830 + 4 ($gp size)
3831 + 4 ($lp size)
3832 + (4 * n) (callee-saved registers)
3833 + sp_adjust ('push25 Re,imm8u')
3834 Note: Since we use 'push25 Re,imm8u',
3835 the position of stack pointer is further
3836 changed after push instruction.
3837 Hence, we need to take sp_adjust value
3838 into consideration. */
3839 fp_adjust = cfun->machine->fp_size
3840 + cfun->machine->gp_size
3841 + cfun->machine->lp_size
3842 + cfun->machine->callee_saved_regs_size
3843 + sp_adjust;
3844 fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx,
3845 stack_pointer_rtx,
3846 GEN_INT (fp_adjust));
3847 /* Emit rtx into instructions list and receive INSN rtx form. */
3848 fp_adjust_insn = emit_insn (fp_adjust_insn);
3849 }
3850 }
3851 else
3852 {
3853 /* We have to use 'push25 Re,0' and
3854 expand one more instruction to adjust $sp later. */
3855
3856 /* push_insn = gen_stack_v3push(last_regno, sp_adjust),
3857 the pattern 'stack_v3push' is implemented in nds32.md.
3858 The (const_int 14) means v3push always push { $fp $gp $lp }. */
3859 push_insn = nds32_gen_stack_v3push (Rb, Re,
3860 GEN_INT (14), GEN_INT (0));
3861 /* Emit rtx into instructions list and receive INSN rtx form. */
3862 push_insn = emit_insn (push_insn);
3863
3864 /* The insn rtx 'push_insn' will change frame layout.
3865 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3866 generate CFI (Call Frame Information) stuff. */
3867 RTX_FRAME_RELATED_P (push_insn) = 1;
3868
3869 /* Check frame_pointer_needed to see
3870 if we shall emit fp adjustment instruction. */
3871 if (frame_pointer_needed)
3872 {
3873 /* adjust $fp = $sp + 4 ($fp size)
3874 + 4 ($gp size)
3875 + 4 ($lp size)
3876 + (4 * n) (callee-saved registers)
3877 Note: Since we use 'push25 Re,0',
3878 the stack pointer is just at the position
3879 after push instruction.
3880 No need to take sp_adjust into consideration. */
3881 fp_adjust = cfun->machine->fp_size
3882 + cfun->machine->gp_size
3883 + cfun->machine->lp_size
3884 + cfun->machine->callee_saved_regs_size;
3885 fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx,
3886 stack_pointer_rtx,
3887 GEN_INT (fp_adjust));
3888 /* Emit rtx into instructions list and receive INSN rtx form. */
3889 fp_adjust_insn = emit_insn (fp_adjust_insn);
3890 }
3891
3892 /* Because we use 'push25 Re,0',
3893 we need to expand one more instruction to adjust $sp.
3894 However, sp_adjust value may be out of range of the addi instruction,
3895 create alternative add behavior with TA_REGNUM if necessary,
3896 using NEGATIVE value to tell that we are decreasing address. */
3897 sp_adjust = nds32_force_addi_stack_int ( (-1) * sp_adjust);
3898 if (sp_adjust)
3899 {
3900 /* Generate sp adjustment instruction
3901 if and only if sp_adjust != 0. */
3902 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
3903 stack_pointer_rtx,
3904 GEN_INT (-1 * sp_adjust));
3905 /* Emit rtx into instructions list and receive INSN rtx form. */
3906 sp_adjust_insn = emit_insn (sp_adjust_insn);
3907
3908 /* The insn rtx 'sp_adjust_insn' will change frame layout.
3909 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3910 generate CFI (Call Frame Information) stuff. */
3911 RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
3912 }
3913 }
3914
3915 /* Prevent the instruction scheduler from
3916 moving instructions across the boundary. */
3917 emit_insn (gen_blockage ());
3918 }
3919
3920 /* Function for v3pop epilogue. */
3921 void
3922 nds32_expand_epilogue_v3pop (void)
3923 {
3924 int sp_adjust;
3925
3926 rtx Rb, Re;
3927 rtx pop_insn;
3928 rtx sp_adjust_insn;
3929
3930 /* Compute and setup stack frame size.
3931 The result will be in cfun->machine. */
3932 nds32_compute_stack_frame ();
3933
3934 /* Prevent the instruction scheduler from
3935 moving instructions across the boundary. */
3936 emit_insn (gen_blockage ());
3937
3938 /* If the function is 'naked', we do not have to generate
3939 epilogue code fragment BUT 'ret' instruction. */
3940 if (cfun->machine->naked_p)
3941 {
3942 /* Generate return instruction by using
3943 unspec_volatile_func_return pattern.
3944 Make sure this instruction is after gen_blockage().
3945 NOTE that $lp will become 'live'
3946 after this instruction has been emitted. */
3947 emit_insn (gen_unspec_volatile_func_return ());
3948 return;
3949 }
3950
3951 /* Get callee_first_regno and callee_last_regno. */
3952 Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno);
3953 Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno);
3954
3955 /* Calculate sp_adjust first to test if 'pop25 Re,imm8u' is available,
3956 where imm8u has to be 8-byte alignment. */
3957 sp_adjust = cfun->machine->local_size
3958 + cfun->machine->out_args_size
3959 + cfun->machine->callee_saved_area_padding_bytes;
3960
3961 /* We have to consider alloca issue as well.
3962 If the function does call alloca(), the stack pointer is not fixed.
3963 In that case, we cannot use 'pop25 Re,imm8u' directly.
3964 We have to caculate stack pointer from frame pointer
3965 and then use 'pop25 Re,0'.
3966 Of course, the frame_pointer_needed should be nonzero
3967 if the function calls alloca(). */
3968 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
3969 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)
3970 && !cfun->calls_alloca)
3971 {
3972 /* We can use 'pop25 Re,imm8u'. */
3973
3974 /* pop_insn = gen_stack_v3pop(last_regno, sp_adjust),
3975 the pattern 'stack_v3pop' is implementad in nds32.md.
3976 The (const_int 14) means v3pop always pop { $fp $gp $lp }. */
3977 pop_insn = nds32_gen_stack_v3pop (Rb, Re,
3978 GEN_INT (14), GEN_INT (sp_adjust));
3979
3980 /* Emit pop instruction. */
3981 emit_insn (pop_insn);
3982 }
3983 else
3984 {
3985 /* We have to use 'pop25 Re,0', and prior to it,
3986 we must expand one more instruction to adjust $sp. */
3987
3988 if (frame_pointer_needed)
3989 {
3990 /* adjust $sp = $fp - 4 ($fp size)
3991 - 4 ($gp size)
3992 - 4 ($lp size)
3993 - (4 * n) (callee-saved registers)
3994 Note: No need to adjust
3995 cfun->machine->callee_saved_area_padding_bytes,
3996 because we want to adjust stack pointer
3997 to the position for pop instruction. */
3998 sp_adjust = cfun->machine->fp_size
3999 + cfun->machine->gp_size
4000 + cfun->machine->lp_size
4001 + cfun->machine->callee_saved_regs_size;
4002 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
4003 hard_frame_pointer_rtx,
4004 GEN_INT (-1 * sp_adjust));
4005 /* Emit rtx into instructions list and receive INSN rtx form. */
4006 sp_adjust_insn = emit_insn (sp_adjust_insn);
4007 }
4008 else
4009 {
4010 /* If frame pointer is NOT needed,
4011 we cannot calculate the sp adjustment from frame pointer.
4012 Instead, we calculate the adjustment by local_size,
4013 out_args_size, and callee_saved_area_padding_bytes.
4014 Notice that such sp adjustment value may be out of range,
4015 so we have to deal with it as well. */
4016
4017 /* Adjust $sp = $sp + local_size + out_args_size
4018 + callee_saved_area_padding_bytes. */
4019 sp_adjust = cfun->machine->local_size
4020 + cfun->machine->out_args_size
4021 + cfun->machine->callee_saved_area_padding_bytes;
4022 /* sp_adjust value may be out of range of the addi instruction,
4023 create alternative add behavior with TA_REGNUM if necessary,
4024 using POSITIVE value to tell that we are increasing address. */
4025 sp_adjust = nds32_force_addi_stack_int (sp_adjust);
4026 if (sp_adjust)
4027 {
4028 /* Generate sp adjustment instruction
4029 if and only if sp_adjust != 0. */
4030 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
4031 stack_pointer_rtx,
4032 GEN_INT (sp_adjust));
4033 /* Emit rtx into instructions list and receive INSN rtx form. */
4034 sp_adjust_insn = emit_insn (sp_adjust_insn);
4035 }
4036 }
4037
4038 /* pop_insn = gen_stack_v3pop(last_regno, sp_adjust),
4039 the pattern 'stack_v3pop' is implementad in nds32.md. */
4040 /* The (const_int 14) means v3pop always pop { $fp $gp $lp }. */
4041 pop_insn = nds32_gen_stack_v3pop (Rb, Re,
4042 GEN_INT (14), GEN_INT (0));
4043
4044 /* Emit pop instruction. */
4045 emit_insn (pop_insn);
4046 }
4047 }
4048
4049 /* ------------------------------------------------------------------------ */
4050
4051 /* Function to test 333-form for load/store instructions.
4052 This is auxiliary extern function for auxiliary macro in nds32.h.
4053 Because it is a little complicated, we use function instead of macro. */
4054 bool
4055 nds32_ls_333_p (rtx rt, rtx ra, rtx imm, enum machine_mode mode)
4056 {
4057 if (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS
4058 && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS)
4059 {
4060 if (GET_MODE_SIZE (mode) == 4)
4061 return satisfies_constraint_Iu05 (imm);
4062
4063 if (GET_MODE_SIZE (mode) == 2)
4064 return satisfies_constraint_Iu04 (imm);
4065
4066 if (GET_MODE_SIZE (mode) == 1)
4067 return satisfies_constraint_Iu03 (imm);
4068 }
4069
4070 return false;
4071 }
4072
4073
4074 /* Functions to expand load_multiple and store_multiple.
4075 They are auxiliary extern functions to help create rtx template.
4076 Check nds32-multiple.md file for the patterns. */
4077 rtx
4078 nds32_expand_load_multiple (int base_regno, int count,
4079 rtx base_addr, rtx basemem)
4080 {
4081 int par_index;
4082 int offset;
4083 rtx result;
4084 rtx new_addr, mem, reg;
4085
4086 /* Create the pattern that is presented in nds32-multiple.md. */
4087
4088 result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
4089
4090 for (par_index = 0; par_index < count; par_index++)
4091 {
4092 offset = par_index * 4;
4093 /* 4-byte for loading data to each register. */
4094 new_addr = plus_constant (Pmode, base_addr, offset);
4095 mem = adjust_automodify_address_nv (basemem, SImode,
4096 new_addr, offset);
4097 reg = gen_rtx_REG (SImode, base_regno + par_index);
4098
4099 XVECEXP (result, 0, par_index) = gen_rtx_SET (VOIDmode, reg, mem);
4100 }
4101
4102 return result;
4103 }
4104
4105 rtx
4106 nds32_expand_store_multiple (int base_regno, int count,
4107 rtx base_addr, rtx basemem)
4108 {
4109 int par_index;
4110 int offset;
4111 rtx result;
4112 rtx new_addr, mem, reg;
4113
4114 /* Create the pattern that is presented in nds32-multiple.md. */
4115
4116 result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
4117
4118 for (par_index = 0; par_index < count; par_index++)
4119 {
4120 offset = par_index * 4;
4121 /* 4-byte for storing data to memory. */
4122 new_addr = plus_constant (Pmode, base_addr, offset);
4123 mem = adjust_automodify_address_nv (basemem, SImode,
4124 new_addr, offset);
4125 reg = gen_rtx_REG (SImode, base_regno + par_index);
4126
4127 XVECEXP (result, 0, par_index) = gen_rtx_SET (VOIDmode, mem, reg);
4128 }
4129
4130 return result;
4131 }
4132
4133 /* Function to move block memory content by
4134 using load_multiple and store_multiple.
4135 This is auxiliary extern function to help create rtx template.
4136 Check nds32-multiple.md file for the patterns. */
4137 int
4138 nds32_expand_movmemqi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment)
4139 {
4140 HOST_WIDE_INT in_words, out_words;
4141 rtx dst_base_reg, src_base_reg;
4142 int maximum_bytes;
4143
4144 /* Because reduced-set regsiters has few registers
4145 (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31'
4146 cannot be used for register allocation),
4147 using 8 registers (32 bytes) for moving memory block
4148 may easily consume all of them.
4149 It makes register allocation/spilling hard to work.
4150 So we only allow maximum=4 registers (16 bytes) for
4151 moving memory block under reduced-set registers. */
4152 if (TARGET_REDUCED_REGS)
4153 maximum_bytes = 16;
4154 else
4155 maximum_bytes = 32;
4156
4157 /* 1. Total_bytes is integer for sure.
4158 2. Alignment is integer for sure.
4159 3. Maximum 4 or 8 registers, 4 * 4 = 16 bytes, 8 * 4 = 32 bytes.
4160 4. Requires (n * 4) block size.
4161 5. Requires 4-byte alignment. */
4162 if (GET_CODE (total_bytes) != CONST_INT
4163 || GET_CODE (alignment) != CONST_INT
4164 || INTVAL (total_bytes) > maximum_bytes
4165 || INTVAL (total_bytes) & 3
4166 || INTVAL (alignment) & 3)
4167 return 0;
4168
4169 dst_base_reg = copy_to_mode_reg (SImode, XEXP (dstmem, 0));
4170 src_base_reg = copy_to_mode_reg (SImode, XEXP (srcmem, 0));
4171
4172 out_words = in_words = INTVAL (total_bytes) / UNITS_PER_WORD;
4173
4174 emit_insn (nds32_expand_load_multiple (0, in_words, src_base_reg, srcmem));
4175 emit_insn (nds32_expand_store_multiple (0, out_words, dst_base_reg, dstmem));
4176
4177 /* Successfully create patterns, return 1. */
4178 return 1;
4179 }
4180
4181 /* Function to check whether the OP is a valid load/store operation.
4182 This is a helper function for the predicates:
4183 'nds32_load_multiple_operation' and 'nds32_store_multiple_operation'
4184 in predicates.md file.
4185
4186 The OP is supposed to be a parallel rtx.
4187 For each element within this parallel rtx:
4188 (set (reg) (mem addr)) is the form for load operation.
4189 (set (mem addr) (reg)) is the form for store operation.
4190 We have to extract reg and mem of every element and
4191 check if the information is valid for multiple load/store operation. */
4192 bool
4193 nds32_valid_multiple_load_store (rtx op, bool load_p)
4194 {
4195 int count;
4196 int first_elt_regno;
4197 rtx elt;
4198
4199 /* Get the counts of elements in the parallel rtx. */
4200 count = XVECLEN (op, 0);
4201 /* Pick up the first element. */
4202 elt = XVECEXP (op, 0, 0);
4203
4204 /* Perform some quick check for the first element in the parallel rtx. */
4205 if (GET_CODE (elt) != SET
4206 || count <= 1
4207 || count > 8)
4208 return false;
4209
4210 /* Pick up regno of first element for further detail checking.
4211 Note that the form is different between load and store operation. */
4212 if (load_p)
4213 {
4214 if (GET_CODE (SET_DEST (elt)) != REG
4215 || GET_CODE (SET_SRC (elt)) != MEM)
4216 return false;
4217
4218 first_elt_regno = REGNO (SET_DEST (elt));
4219 }
4220 else
4221 {
4222 if (GET_CODE (SET_SRC (elt)) != REG
4223 || GET_CODE (SET_DEST (elt)) != MEM)
4224 return false;
4225
4226 first_elt_regno = REGNO (SET_SRC (elt));
4227 }
4228
4229 /* Perform detail check for each element.
4230 Refer to nds32-multiple.md for more information
4231 about following checking.
4232 The starting element of parallel rtx is index 0. */
4233 if (!nds32_consecutive_registers_load_store_p (op, load_p, 0,
4234 first_elt_regno,
4235 count))
4236 return false;
4237
4238 /* Pass all test, this is a valid rtx. */
4239 return true;
4240 }
4241
4242 /* Function to check whether the OP is a valid stack push/pop operation.
4243 For a valid stack operation, it must satisfy following conditions:
4244 1. Consecutive registers push/pop operations.
4245 2. Valid $fp/$gp/$lp push/pop operations.
4246 3. The last element must be stack adjustment rtx.
4247 See the prologue/epilogue implementation for details. */
4248 bool
4249 nds32_valid_stack_push_pop (rtx op, bool push_p)
4250 {
4251 int index;
4252 int total_count;
4253 int rest_count;
4254 int first_regno;
4255 rtx elt;
4256 rtx elt_reg;
4257 rtx elt_mem;
4258 rtx elt_plus;
4259
4260 /* Get the counts of elements in the parallel rtx. */
4261 total_count = XVECLEN (op, 0);
4262
4263 /* Perform some quick check for that every element should be 'set'. */
4264 for (index = 0; index < total_count; index++)
4265 {
4266 elt = XVECEXP (op, 0, index);
4267 if (GET_CODE (elt) != SET)
4268 return false;
4269 }
4270
4271 /* For push operation, the parallel rtx looks like:
4272 (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
4273 (reg:SI Rb))
4274 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
4275 (reg:SI Rb+1))
4276 ...
4277 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
4278 (reg:SI Re))
4279 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
4280 (reg:SI FP_REGNUM))
4281 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
4282 (reg:SI GP_REGNUM))
4283 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
4284 (reg:SI LP_REGNUM))
4285 (set (reg:SI SP_REGNUM)
4286 (plus (reg:SI SP_REGNUM) (const_int -32)))])
4287
4288 For pop operation, the parallel rtx looks like:
4289 (parallel [(set (reg:SI Rb)
4290 (mem (reg:SI SP_REGNUM)))
4291 (set (reg:SI Rb+1)
4292 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
4293 ...
4294 (set (reg:SI Re)
4295 (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
4296 (set (reg:SI FP_REGNUM)
4297 (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
4298 (set (reg:SI GP_REGNUM)
4299 (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
4300 (set (reg:SI LP_REGNUM)
4301 (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
4302 (set (reg:SI SP_REGNUM)
4303 (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
4304
4305 /* 1. Consecutive registers push/pop operations.
4306 We need to calculate how many registers should be consecutive.
4307 The $sp adjustment rtx, $fp push rtx, $gp push rtx,
4308 and $lp push rtx are excluded. */
4309
4310 /* Exclude last $sp adjustment rtx. */
4311 rest_count = total_count - 1;
4312 /* Exclude $fp, $gp, and $lp if they are in the parallel rtx. */
4313 if (cfun->machine->fp_size)
4314 rest_count--;
4315 if (cfun->machine->gp_size)
4316 rest_count--;
4317 if (cfun->machine->lp_size)
4318 rest_count--;
4319
4320 if (rest_count > 0)
4321 {
4322 elt = XVECEXP (op, 0, 0);
4323 /* Pick up register element. */
4324 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
4325 first_regno = REGNO (elt_reg);
4326
4327 /* The 'push' operation is a kind of store operation.
4328 The 'pop' operation is a kind of load operation.
4329 Pass corresponding false/true as second argument (bool load_p).
4330 The par_index is supposed to start with index 0. */
4331 if (!nds32_consecutive_registers_load_store_p (op,
4332 !push_p ? true : false,
4333 0,
4334 first_regno,
4335 rest_count))
4336 return false;
4337 }
4338
4339 /* 2. Valid $fp/$gp/$lp push/pop operations.
4340 Remember to set start index for checking them. */
4341
4342 /* The rest_count is the start index for checking $fp/$gp/$lp. */
4343 index = rest_count;
4344 /* If index < 0, this parallel rtx is definitely
4345 not a valid stack push/pop operation. */
4346 if (index < 0)
4347 return false;
4348
4349 /* Check $fp/$gp/$lp one by one.
4350 We use 'push_p' to pick up reg rtx and mem rtx. */
4351 if (cfun->machine->fp_size)
4352 {
4353 elt = XVECEXP (op, 0, index);
4354 elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
4355 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
4356 index++;
4357
4358 if (GET_CODE (elt_mem) != MEM
4359 || GET_CODE (elt_reg) != REG
4360 || REGNO (elt_reg) != FP_REGNUM)
4361 return false;
4362 }
4363 if (cfun->machine->gp_size)
4364 {
4365 elt = XVECEXP (op, 0, index);
4366 elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
4367 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
4368 index++;
4369
4370 if (GET_CODE (elt_mem) != MEM
4371 || GET_CODE (elt_reg) != REG
4372 || REGNO (elt_reg) != GP_REGNUM)
4373 return false;
4374 }
4375 if (cfun->machine->lp_size)
4376 {
4377 elt = XVECEXP (op, 0, index);
4378 elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
4379 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
4380 index++;
4381
4382 if (GET_CODE (elt_mem) != MEM
4383 || GET_CODE (elt_reg) != REG
4384 || REGNO (elt_reg) != LP_REGNUM)
4385 return false;
4386 }
4387
4388 /* 3. The last element must be stack adjustment rtx.
4389 Its form of rtx should be:
4390 (set (reg:SI SP_REGNUM)
4391 (plus (reg:SI SP_REGNUM) (const_int X)))
4392 The X could be positive or negative value. */
4393
4394 /* Pick up the last element. */
4395 elt = XVECEXP (op, 0, total_count - 1);
4396
4397 /* Extract its destination and source rtx. */
4398 elt_reg = SET_DEST (elt);
4399 elt_plus = SET_SRC (elt);
4400
4401 /* Check this is (set (stack_reg) (plus stack_reg const)) pattern. */
4402 if (GET_CODE (elt_reg) != REG
4403 || GET_CODE (elt_plus) != PLUS
4404 || REGNO (elt_reg) != SP_REGNUM)
4405 return false;
4406
4407 /* Pass all test, this is a valid rtx. */
4408 return true;
4409 }
4410
4411 /* Computing the Length of an Insn.
4412 Modifies the length assigned to instruction INSN.
4413 LEN is the initially computed length of the insn. */
4414 int
4415 nds32_adjust_insn_length (rtx insn, int length)
4416 {
4417 rtx src, dst;
4418
4419 switch (recog_memoized (insn))
4420 {
4421 case CODE_FOR_move_df:
4422 case CODE_FOR_move_di:
4423 /* Adjust length of movd44 to 2. */
4424 src = XEXP (PATTERN (insn), 1);
4425 dst = XEXP (PATTERN (insn), 0);
4426
4427 if (REG_P (src)
4428 && REG_P (dst)
4429 && (REGNO (src) % 2) == 0
4430 && (REGNO (dst) % 2) == 0)
4431 length = 2;
4432 break;
4433
4434 default:
4435 break;
4436 }
4437
4438 return length;
4439 }
4440
4441
4442 /* Function to check if 'bclr' instruction can be used with IVAL. */
4443 int
4444 nds32_can_use_bclr_p (int ival)
4445 {
4446 int one_bit_count;
4447
4448 /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit,
4449 it means the original ival has only one 0-bit,
4450 So it is ok to perform 'bclr' operation. */
4451
4452 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival));
4453
4454 /* 'bclr' is a performance extension instruction. */
4455 return (TARGET_PERF_EXT && (one_bit_count == 1));
4456 }
4457
4458 /* Function to check if 'bset' instruction can be used with IVAL. */
4459 int
4460 nds32_can_use_bset_p (int ival)
4461 {
4462 int one_bit_count;
4463
4464 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
4465 it is ok to perform 'bset' operation. */
4466
4467 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
4468
4469 /* 'bset' is a performance extension instruction. */
4470 return (TARGET_PERF_EXT && (one_bit_count == 1));
4471 }
4472
4473 /* Function to check if 'btgl' instruction can be used with IVAL. */
4474 int
4475 nds32_can_use_btgl_p (int ival)
4476 {
4477 int one_bit_count;
4478
4479 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
4480 it is ok to perform 'btgl' operation. */
4481
4482 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
4483
4484 /* 'btgl' is a performance extension instruction. */
4485 return (TARGET_PERF_EXT && (one_bit_count == 1));
4486 }
4487
4488 /* Function to check if 'bitci' instruction can be used with IVAL. */
4489 int
4490 nds32_can_use_bitci_p (int ival)
4491 {
4492 /* If we are using V3 ISA, we have 'bitci' instruction.
4493 Try to see if we can present 'andi' semantic with
4494 such 'bit-clear-immediate' operation.
4495 For example, 'andi $r0,$r0,0xfffffffc' can be
4496 presented with 'bitci $r0,$r0,3'. */
4497 return (TARGET_ISA_V3
4498 && (ival < 0)
4499 && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode)));
4500 }
4501
4502
4503 /* Return true if is load/store with SYMBOL_REF addressing mode
4504 and memory mode is SImode. */
4505 bool
4506 nds32_symbol_load_store_p (rtx insn)
4507 {
4508 rtx mem_src = NULL_RTX;
4509
4510 switch (get_attr_type (insn))
4511 {
4512 case TYPE_LOAD:
4513 mem_src = SET_SRC (PATTERN (insn));
4514 break;
4515 case TYPE_STORE:
4516 mem_src = SET_DEST (PATTERN (insn));
4517 break;
4518 default:
4519 break;
4520 }
4521
4522 /* Find load/store insn with addressing mode is SYMBOL_REF. */
4523 if (mem_src != NULL_RTX)
4524 {
4525 if ((GET_CODE (mem_src) == ZERO_EXTEND)
4526 || (GET_CODE (mem_src) == SIGN_EXTEND))
4527 mem_src = XEXP (mem_src, 0);
4528
4529 if ((GET_CODE (XEXP (mem_src, 0)) == SYMBOL_REF)
4530 || (GET_CODE (XEXP (mem_src, 0)) == LO_SUM))
4531 return true;
4532 }
4533
4534 return false;
4535 }
4536
4537 /* Function to determine whether it is worth to do fp_as_gp optimization.
4538 Return 0: It is NOT worth to do fp_as_gp optimization.
4539 Return 1: It is APPROXIMATELY worth to do fp_as_gp optimization.
4540 Note that if it is worth to do fp_as_gp optimization,
4541 we MUST set FP_REGNUM ever live in this function. */
4542 int
4543 nds32_fp_as_gp_check_available (void)
4544 {
4545 /* If there exists ANY of following conditions,
4546 we DO NOT perform fp_as_gp optimization:
4547 1. TARGET_FORBID_FP_AS_GP is set
4548 regardless of the TARGET_FORCE_FP_AS_GP.
4549 2. User explicitly uses 'naked' attribute.
4550 3. Not optimize for size.
4551 4. Need frame pointer.
4552 5. If $fp is already required to be saved,
4553 it means $fp is already choosen by register allocator.
4554 Thus we better not to use it for fp_as_gp optimization.
4555 6. This function is a vararg function.
4556 DO NOT apply fp_as_gp optimization on this function
4557 because it may change and break stack frame.
4558 7. The epilogue is empty.
4559 This happens when the function uses exit()
4560 or its attribute is no_return.
4561 In that case, compiler will not expand epilogue
4562 so that we have no chance to output .omit_fp_end directive. */
4563 if (TARGET_FORBID_FP_AS_GP
4564 || lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))
4565 || !optimize_size
4566 || frame_pointer_needed
4567 || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM)
4568 || (cfun->stdarg == 1)
4569 || (find_fallthru_edge (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == NULL))
4570 return 0;
4571
4572 /* Now we can check the possibility of using fp_as_gp optimization. */
4573 if (TARGET_FORCE_FP_AS_GP)
4574 {
4575 /* User explicitly issues -mforce-fp-as-gp option. */
4576 df_set_regs_ever_live (FP_REGNUM, 1);
4577 return 1;
4578 }
4579 else
4580 {
4581 /* In the following we are going to evaluate whether
4582 it is worth to do fp_as_gp optimization. */
4583 int good_gain = 0;
4584 int symbol_count = 0;
4585
4586 int threshold;
4587 rtx insn;
4588
4589 /* We check if there already requires prologue.
4590 Note that $gp will be saved in prologue for PIC code generation.
4591 After that, we can set threshold by the existence of prologue.
4592 Each fp-implied instruction will gain 2-byte code size
4593 from gp-aware instruction, so we have following heuristics. */
4594 if (flag_pic
4595 || nds32_have_prologue_p ())
4596 {
4597 /* Have-prologue:
4598 Compiler already intends to generate prologue content,
4599 so the fp_as_gp optimization will only insert
4600 'la $fp,_FP_BASE_' instruction, which will be
4601 converted into 4-byte instruction at link time.
4602 The threshold is "3" symbol accesses, 2 + 2 + 2 > 4. */
4603 threshold = 3;
4604 }
4605 else
4606 {
4607 /* None-prologue:
4608 Compiler originally does not generate prologue content,
4609 so the fp_as_gp optimization will NOT ONLY insert
4610 'la $fp,_FP_BASE' instruction, but also causes
4611 push/pop instructions.
4612 If we are using v3push (push25/pop25),
4613 the threshold is "5" symbol accesses, 5*2 > 4 + 2 + 2;
4614 If we are using normal push (smw/lmw),
4615 the threshold is "5+2" symbol accesses 7*2 > 4 + 4 + 4. */
4616 threshold = 5 + (TARGET_V3PUSH ? 0 : 2);
4617 }
4618
4619 /* We would like to traverse every instruction in this function.
4620 So we need to have push_topmost_sequence()/pop_topmost_sequence()
4621 surrounding our for-loop evaluation. */
4622 push_topmost_sequence ();
4623 /* Counting the insn number which the addressing mode is symbol. */
4624 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4625 {
4626 if (single_set (insn) && nds32_symbol_load_store_p (insn))
4627 symbol_count++;
4628
4629 if (symbol_count == threshold)
4630 {
4631 good_gain = 1;
4632 break;
4633 }
4634 }
4635 pop_topmost_sequence ();
4636
4637 /* Enable fp_as_gp optimization when potential gain is good enough. */
4638 if (good_gain)
4639 {
4640 df_set_regs_ever_live (FP_REGNUM, 1);
4641 return 1;
4642 }
4643 }
4644
4645 /* By default we return 0. */
4646 return 0;
4647 }
4648
4649
4650 /* Function to generate PC relative jump table.
4651 Refer to nds32.md for more details.
4652
4653 The following is the sample for the case that diff value
4654 can be presented in '.short' size.
4655
4656 addi $r1, $r1, -(case_lower_bound)
4657 slti $ta, $r1, (case_number)
4658 beqz $ta, .L_skip_label
4659
4660 la $ta, .L35 ! get jump table address
4661 lh $r1, [$ta + $r1 << 1] ! load symbol diff from jump table entry
4662 addi $ta, $r1, $ta
4663 jr5 $ta
4664
4665 ! jump table entry
4666 L35:
4667 .short .L25-.L35
4668 .short .L26-.L35
4669 .short .L27-.L35
4670 .short .L28-.L35
4671 .short .L29-.L35
4672 .short .L30-.L35
4673 .short .L31-.L35
4674 .short .L32-.L35
4675 .short .L33-.L35
4676 .short .L34-.L35 */
4677 const char *
4678 nds32_output_casesi_pc_relative (rtx *operands)
4679 {
4680 enum machine_mode mode;
4681 rtx diff_vec;
4682
4683 diff_vec = PATTERN (NEXT_INSN (operands[1]));
4684
4685 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
4686
4687 /* Step C: "t <-- operands[1]". */
4688 output_asm_insn ("la\t$ta, %l1", operands);
4689
4690 /* Get the mode of each element in the difference vector. */
4691 mode = GET_MODE (diff_vec);
4692
4693 /* Step D: "z <-- (mem (plus (operands[0] << m) t))",
4694 where m is 0, 1, or 2 to load address-diff value from table. */
4695 switch (mode)
4696 {
4697 case QImode:
4698 output_asm_insn ("lb\t%2, [$ta + %0 << 0]", operands);
4699 break;
4700 case HImode:
4701 output_asm_insn ("lh\t%2, [$ta + %0 << 1]", operands);
4702 break;
4703 case SImode:
4704 output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands);
4705 break;
4706 default:
4707 gcc_unreachable ();
4708 }
4709
4710 /* Step E: "t <-- z + t".
4711 Add table label_ref with address-diff value to
4712 obtain target case address. */
4713 output_asm_insn ("add\t$ta, %2, $ta", operands);
4714
4715 /* Step F: jump to target with register t. */
4716 if (TARGET_16_BIT)
4717 return "jr5\t$ta";
4718 else
4719 return "jr\t$ta";
4720 }
4721
4722 /* Function to generate normal jump table. */
4723 const char *
4724 nds32_output_casesi (rtx *operands)
4725 {
4726 /* Step C: "t <-- operands[1]". */
4727 output_asm_insn ("la\t$ta, %l1", operands);
4728
4729 /* Step D: "z <-- (mem (plus (operands[0] << 2) t))". */
4730 output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands);
4731
4732 /* No need to perform Step E, which is only used for
4733 pc relative jump table. */
4734
4735 /* Step F: jump to target with register z. */
4736 if (TARGET_16_BIT)
4737 return "jr5\t%2";
4738 else
4739 return "jr\t%2";
4740 }
4741
4742
4743 /* Function to return memory format. */
4744 enum nds32_16bit_address_type
4745 nds32_mem_format (rtx op)
4746 {
4747 enum machine_mode mode_test;
4748 int val;
4749 int regno;
4750
4751 if (!TARGET_16_BIT)
4752 return ADDRESS_NOT_16BIT_FORMAT;
4753
4754 mode_test = GET_MODE (op);
4755
4756 op = XEXP (op, 0);
4757
4758 /* 45 format. */
4759 if (GET_CODE (op) == REG && (mode_test == SImode))
4760 return ADDRESS_REG;
4761
4762 /* 333 format for QI/HImode. */
4763 if (GET_CODE (op) == REG && (REGNO (op) < R8_REGNUM))
4764 return ADDRESS_LO_REG_IMM3U;
4765
4766 /* post_inc 333 format. */
4767 if ((GET_CODE (op) == POST_INC) && (mode_test == SImode))
4768 {
4769 regno = REGNO(XEXP (op, 0));
4770
4771 if (regno < 8)
4772 return ADDRESS_POST_INC_LO_REG_IMM3U;
4773 }
4774
4775 /* post_inc 333 format. */
4776 if ((GET_CODE (op) == POST_MODIFY)
4777 && (mode_test == SImode)
4778 && (REG_P (XEXP (XEXP (op, 1), 0)))
4779 && (CONST_INT_P (XEXP (XEXP (op, 1), 1))))
4780 {
4781 regno = REGNO (XEXP (XEXP (op, 1), 0));
4782 val = INTVAL (XEXP (XEXP (op, 1), 1));
4783 if (regno < 8 && val < 32)
4784 return ADDRESS_POST_INC_LO_REG_IMM3U;
4785 }
4786
4787 if ((GET_CODE (op) == PLUS)
4788 && (GET_CODE (XEXP (op, 0)) == REG)
4789 && (GET_CODE (XEXP (op, 1)) == CONST_INT))
4790 {
4791 val = INTVAL (XEXP (op, 1));
4792
4793 regno = REGNO(XEXP (op, 0));
4794
4795 if (regno > 7
4796 && regno != SP_REGNUM
4797 && regno != FP_REGNUM)
4798 return ADDRESS_NOT_16BIT_FORMAT;
4799
4800 switch (mode_test)
4801 {
4802 case QImode:
4803 /* 333 format. */
4804 if (val >= 0 && val < 8 && regno < 8)
4805 return ADDRESS_LO_REG_IMM3U;
4806 break;
4807
4808 case HImode:
4809 /* 333 format. */
4810 if (val >= 0 && val < 16 && (val % 2 == 0) && regno < 8)
4811 return ADDRESS_LO_REG_IMM3U;
4812 break;
4813
4814 case SImode:
4815 case SFmode:
4816 case DFmode:
4817 /* fp imply 37 format. */
4818 if ((regno == FP_REGNUM) &&
4819 (val >= 0 && val < 512 && (val % 4 == 0)))
4820 return ADDRESS_FP_IMM7U;
4821 /* sp imply 37 format. */
4822 else if ((regno == SP_REGNUM) &&
4823 (val >= 0 && val < 512 && (val % 4 == 0)))
4824 return ADDRESS_SP_IMM7U;
4825 /* 333 format. */
4826 else if (val >= 0 && val < 32 && (val % 4 == 0) && regno < 8)
4827 return ADDRESS_LO_REG_IMM3U;
4828 break;
4829
4830 default:
4831 break;
4832 }
4833 }
4834
4835 return ADDRESS_NOT_16BIT_FORMAT;
4836 }
4837
4838 /* Output 16-bit store. */
4839 const char *
4840 nds32_output_16bit_store (rtx *operands, int byte)
4841 {
4842 char pattern[100];
4843 char size;
4844 rtx code = XEXP (operands[0], 0);
4845
4846 size = nds32_byte_to_size (byte);
4847
4848 switch (nds32_mem_format (operands[0]))
4849 {
4850 case ADDRESS_REG:
4851 operands[0] = code;
4852 output_asm_insn ("swi450\t%1, [%0]", operands);
4853 break;
4854 case ADDRESS_LO_REG_IMM3U:
4855 snprintf (pattern, sizeof (pattern), "s%ci333\t%%1, %%0", size);
4856 output_asm_insn (pattern, operands);
4857 break;
4858 case ADDRESS_POST_INC_LO_REG_IMM3U:
4859 snprintf (pattern, sizeof (pattern), "s%ci333.bi\t%%1, %%0", size);
4860 output_asm_insn (pattern, operands);
4861 break;
4862 case ADDRESS_FP_IMM7U:
4863 output_asm_insn ("swi37\t%1, %0", operands);
4864 break;
4865 case ADDRESS_SP_IMM7U:
4866 /* Get immediate value and set back to operands[1]. */
4867 operands[0] = XEXP (code, 1);
4868 output_asm_insn ("swi37.sp\t%1, [ + (%0)]", operands);
4869 break;
4870 default:
4871 break;
4872 }
4873
4874 return "";
4875 }
4876
4877 /* Output 16-bit load. */
4878 const char *
4879 nds32_output_16bit_load (rtx *operands, int byte)
4880 {
4881 char pattern[100];
4882 unsigned char size;
4883 rtx code = XEXP (operands[1], 0);
4884
4885 size = nds32_byte_to_size (byte);
4886
4887 switch (nds32_mem_format (operands[1]))
4888 {
4889 case ADDRESS_REG:
4890 operands[1] = code;
4891 output_asm_insn ("lwi450\t%0, [%1]", operands);
4892 break;
4893 case ADDRESS_LO_REG_IMM3U:
4894 snprintf (pattern, sizeof (pattern), "l%ci333\t%%0, %%1", size);
4895 output_asm_insn (pattern, operands);
4896 break;
4897 case ADDRESS_POST_INC_LO_REG_IMM3U:
4898 snprintf (pattern, sizeof (pattern), "l%ci333.bi\t%%0, %%1", size);
4899 output_asm_insn (pattern, operands);
4900 break;
4901 case ADDRESS_FP_IMM7U:
4902 output_asm_insn ("lwi37\t%0, %1", operands);
4903 break;
4904 case ADDRESS_SP_IMM7U:
4905 /* Get immediate value and set back to operands[0]. */
4906 operands[1] = XEXP (code, 1);
4907 output_asm_insn ("lwi37.sp\t%0, [ + (%1)]", operands);
4908 break;
4909 default:
4910 break;
4911 }
4912
4913 return "";
4914 }
4915
4916 /* Output 32-bit store. */
4917 const char *
4918 nds32_output_32bit_store (rtx *operands, int byte)
4919 {
4920 char pattern[100];
4921 unsigned char size;
4922 rtx code = XEXP (operands[0], 0);
4923
4924 size = nds32_byte_to_size (byte);
4925
4926 switch (GET_CODE (code))
4927 {
4928 case REG:
4929 /* (mem (reg X))
4930 => access location by using register,
4931 use "sbi / shi / swi" */
4932 snprintf (pattern, sizeof (pattern), "s%ci\t%%1, %%0", size);
4933 break;
4934
4935 case SYMBOL_REF:
4936 case CONST:
4937 /* (mem (symbol_ref X))
4938 (mem (const (...)))
4939 => access global variables,
4940 use "sbi.gp / shi.gp / swi.gp" */
4941 operands[0] = XEXP (operands[0], 0);
4942 snprintf (pattern, sizeof (pattern), "s%ci.gp\t%%1, [ + %%0]", size);
4943 break;
4944
4945 case POST_INC:
4946 /* (mem (post_inc reg))
4947 => access location by using register which will be post increment,
4948 use "sbi.bi / shi.bi / swi.bi" */
4949 snprintf (pattern, sizeof (pattern),
4950 "s%ci.bi\t%%1, %%0, %d", size, byte);
4951 break;
4952
4953 case POST_DEC:
4954 /* (mem (post_dec reg))
4955 => access location by using register which will be post decrement,
4956 use "sbi.bi / shi.bi / swi.bi" */
4957 snprintf (pattern, sizeof (pattern),
4958 "s%ci.bi\t%%1, %%0, -%d", size, byte);
4959 break;
4960
4961 case POST_MODIFY:
4962 switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
4963 {
4964 case REG:
4965 case SUBREG:
4966 /* (mem (post_modify (reg) (plus (reg) (reg))))
4967 => access location by using register which will be
4968 post modified with reg,
4969 use "sb.bi/ sh.bi / sw.bi" */
4970 snprintf (pattern, sizeof (pattern), "s%c.bi\t%%1, %%0", size);
4971 break;
4972 case CONST_INT:
4973 /* (mem (post_modify (reg) (plus (reg) (const_int))))
4974 => access location by using register which will be
4975 post modified with const_int,
4976 use "sbi.bi/ shi.bi / swi.bi" */
4977 snprintf (pattern, sizeof (pattern), "s%ci.bi\t%%1, %%0", size);
4978 break;
4979 default:
4980 abort ();
4981 }
4982 break;
4983
4984 case PLUS:
4985 switch (GET_CODE (XEXP (code, 1)))
4986 {
4987 case REG:
4988 case SUBREG:
4989 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
4990 => access location by adding two registers,
4991 use "sb / sh / sw" */
4992 snprintf (pattern, sizeof (pattern), "s%c\t%%1, %%0", size);
4993 break;
4994 case CONST_INT:
4995 /* (mem (plus reg const_int))
4996 => access location by adding one register with const_int,
4997 use "sbi / shi / swi" */
4998 snprintf (pattern, sizeof (pattern), "s%ci\t%%1, %%0", size);
4999 break;
5000 default:
5001 abort ();
5002 }
5003 break;
5004
5005 case LO_SUM:
5006 operands[2] = XEXP (code, 1);
5007 operands[0] = XEXP (code, 0);
5008 snprintf (pattern, sizeof (pattern),
5009 "s%ci\t%%1, [%%0 + lo12(%%2)]", size);
5010 break;
5011
5012 default:
5013 abort ();
5014 }
5015
5016 output_asm_insn (pattern, operands);
5017 return "";
5018 }
5019
5020 /* Output 32-bit load. */
5021 const char *
5022 nds32_output_32bit_load (rtx *operands, int byte)
5023 {
5024 char pattern[100];
5025 unsigned char size;
5026 rtx code;
5027
5028 code = XEXP (operands[1], 0);
5029
5030 size = nds32_byte_to_size (byte);
5031
5032 switch (GET_CODE (code))
5033 {
5034 case REG:
5035 /* (mem (reg X))
5036 => access location by using register,
5037 use "lbi / lhi / lwi" */
5038 snprintf (pattern, sizeof (pattern), "l%ci\t%%0, %%1", size);
5039 break;
5040
5041 case SYMBOL_REF:
5042 case CONST:
5043 /* (mem (symbol_ref X))
5044 (mem (const (...)))
5045 => access global variables,
5046 use "lbi.gp / lhi.gp / lwi.gp" */
5047 operands[1] = XEXP (operands[1], 0);
5048 snprintf (pattern, sizeof (pattern), "l%ci.gp\t%%0, [ + %%1]", size);
5049 break;
5050
5051 case POST_INC:
5052 /* (mem (post_inc reg))
5053 => access location by using register which will be post increment,
5054 use "lbi.bi / lhi.bi / lwi.bi" */
5055 snprintf (pattern, sizeof (pattern),
5056 "l%ci.bi\t%%0, %%1, %d", size, byte);
5057 break;
5058
5059 case POST_DEC:
5060 /* (mem (post_dec reg))
5061 => access location by using register which will be post decrement,
5062 use "lbi.bi / lhi.bi / lwi.bi" */
5063 snprintf (pattern, sizeof (pattern),
5064 "l%ci.bi\t%%0, %%1, -%d", size, byte);
5065 break;
5066
5067 case POST_MODIFY:
5068 switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
5069 {
5070 case REG:
5071 case SUBREG:
5072 /* (mem (post_modify (reg) (plus (reg) (reg))))
5073 => access location by using register which will be
5074 post modified with reg,
5075 use "lb.bi/ lh.bi / lw.bi" */
5076 snprintf (pattern, sizeof (pattern), "l%c.bi\t%%0, %%1", size);
5077 break;
5078 case CONST_INT:
5079 /* (mem (post_modify (reg) (plus (reg) (const_int))))
5080 => access location by using register which will be
5081 post modified with const_int,
5082 use "lbi.bi/ lhi.bi / lwi.bi" */
5083 snprintf (pattern, sizeof (pattern), "l%ci.bi\t%%0, %%1", size);
5084 break;
5085 default:
5086 abort ();
5087 }
5088 break;
5089
5090 case PLUS:
5091 switch (GET_CODE (XEXP (code, 1)))
5092 {
5093 case REG:
5094 case SUBREG:
5095 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
5096 use "lb / lh / lw" */
5097 snprintf (pattern, sizeof (pattern), "l%c\t%%0, %%1", size);
5098 break;
5099 case CONST_INT:
5100 /* (mem (plus reg const_int))
5101 => access location by adding one register with const_int,
5102 use "lbi / lhi / lwi" */
5103 snprintf (pattern, sizeof (pattern), "l%ci\t%%0, %%1", size);
5104 break;
5105 default:
5106 abort ();
5107 }
5108 break;
5109
5110 case LO_SUM:
5111 operands[2] = XEXP (code, 1);
5112 operands[1] = XEXP (code, 0);
5113 snprintf (pattern, sizeof (pattern),
5114 "l%ci\t%%0, [%%1 + lo12(%%2)]", size);
5115 break;
5116
5117 default:
5118 abort ();
5119 }
5120
5121 output_asm_insn (pattern, operands);
5122 return "";
5123 }
5124
5125 /* Output 32-bit load with signed extension. */
5126 const char *
5127 nds32_output_32bit_load_s (rtx *operands, int byte)
5128 {
5129 char pattern[100];
5130 unsigned char size;
5131 rtx code;
5132
5133 code = XEXP (operands[1], 0);
5134
5135 size = nds32_byte_to_size (byte);
5136
5137 switch (GET_CODE (code))
5138 {
5139 case REG:
5140 /* (mem (reg X))
5141 => access location by using register,
5142 use "lbsi / lhsi" */
5143 snprintf (pattern, sizeof (pattern), "l%csi\t%%0, %%1", size);
5144 break;
5145
5146 case SYMBOL_REF:
5147 case CONST:
5148 /* (mem (symbol_ref X))
5149 (mem (const (...)))
5150 => access global variables,
5151 use "lbsi.gp / lhsi.gp" */
5152 operands[1] = XEXP (operands[1], 0);
5153 snprintf (pattern, sizeof (pattern), "l%csi.gp\t%%0, [ + %%1]", size);
5154 break;
5155
5156 case POST_INC:
5157 /* (mem (post_inc reg))
5158 => access location by using register which will be post increment,
5159 use "lbsi.bi / lhsi.bi" */
5160 snprintf (pattern, sizeof (pattern),
5161 "l%csi.bi\t%%0, %%1, %d", size, byte);
5162 break;
5163
5164 case POST_DEC:
5165 /* (mem (post_dec reg))
5166 => access location by using register which will be post decrement,
5167 use "lbsi.bi / lhsi.bi" */
5168 snprintf (pattern, sizeof (pattern),
5169 "l%csi.bi\t%%0, %%1, -%d", size, byte);
5170 break;
5171
5172 case POST_MODIFY:
5173 switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
5174 {
5175 case REG:
5176 case SUBREG:
5177 /* (mem (post_modify (reg) (plus (reg) (reg))))
5178 => access location by using register which will be
5179 post modified with reg,
5180 use "lbs.bi/ lhs.bi" */
5181 snprintf (pattern, sizeof (pattern), "l%cs.bi\t%%0, %%1", size);
5182 break;
5183 case CONST_INT:
5184 /* (mem (post_modify (reg) (plus (reg) (const_int))))
5185 => access location by using register which will be
5186 post modified with const_int,
5187 use "lbsi.bi/ lhsi.bi" */
5188 snprintf (pattern, sizeof (pattern), "l%csi.bi\t%%0, %%1", size);
5189 break;
5190 default:
5191 abort ();
5192 }
5193 break;
5194
5195 case PLUS:
5196 switch (GET_CODE (XEXP (code, 1)))
5197 {
5198 case REG:
5199 case SUBREG:
5200 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
5201 use "lbs / lhs" */
5202 snprintf (pattern, sizeof (pattern), "l%cs\t%%0, %%1", size);
5203 break;
5204 case CONST_INT:
5205 /* (mem (plus reg const_int))
5206 => access location by adding one register with const_int,
5207 use "lbsi / lhsi" */
5208 snprintf (pattern, sizeof (pattern), "l%csi\t%%0, %%1", size);
5209 break;
5210 default:
5211 abort ();
5212 }
5213 break;
5214
5215 case LO_SUM:
5216 operands[2] = XEXP (code, 1);
5217 operands[1] = XEXP (code, 0);
5218 snprintf (pattern, sizeof (pattern),
5219 "l%csi\t%%0, [%%1 + lo12(%%2)]", size);
5220 break;
5221
5222 default:
5223 abort ();
5224 }
5225
5226 output_asm_insn (pattern, operands);
5227 return "";
5228 }
5229
5230 /* Function to output stack push operation.
5231 We need to deal with normal stack push multiple or stack v3push. */
5232 const char *
5233 nds32_output_stack_push (void)
5234 {
5235 /* A string pattern for output_asm_insn(). */
5236 char pattern[100];
5237 /* The operands array which will be used in output_asm_insn(). */
5238 rtx operands[3];
5239 /* Pick up callee-saved first regno and last regno for further use. */
5240 int rb_regno = cfun->machine->callee_saved_regs_first_regno;
5241 int re_regno = cfun->machine->callee_saved_regs_last_regno;
5242
5243 if (TARGET_V3PUSH)
5244 {
5245 /* For stack v3push:
5246 operands[0]: Re
5247 operands[1]: imm8u */
5248
5249 /* This variable is to check if 'push25 Re,imm8u' is available. */
5250 int sp_adjust;
5251
5252 /* Set operands[0]. */
5253 operands[0] = gen_rtx_REG (SImode, re_regno);
5254
5255 /* Check if we can generate 'push25 Re,imm8u',
5256 otherwise, generate 'push25 Re,0'. */
5257 sp_adjust = cfun->machine->local_size
5258 + cfun->machine->out_args_size
5259 + cfun->machine->callee_saved_area_padding_bytes;
5260 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
5261 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust))
5262 operands[1] = GEN_INT (sp_adjust);
5263 else
5264 operands[1] = GEN_INT (0);
5265
5266 /* Create assembly code pattern. */
5267 snprintf (pattern, sizeof (pattern), "push25\t%%0, %%1");
5268 }
5269 else
5270 {
5271 /* For normal stack push multiple:
5272 operands[0]: Rb
5273 operands[1]: Re
5274 operands[2]: En4 */
5275
5276 /* This variable is used to check if we only need to generate En4 field.
5277 As long as Rb==Re=SP_REGNUM, we set this variable to 1. */
5278 int push_en4_only_p = 0;
5279
5280 /* Set operands[0] and operands[1]. */
5281 operands[0] = gen_rtx_REG (SImode, rb_regno);
5282 operands[1] = gen_rtx_REG (SImode, re_regno);
5283
5284 /* 'smw.adm $sp,[$sp],$sp,0' means push nothing. */
5285 if (!cfun->machine->fp_size
5286 && !cfun->machine->gp_size
5287 && !cfun->machine->lp_size
5288 && REGNO (operands[0]) == SP_REGNUM
5289 && REGNO (operands[1]) == SP_REGNUM)
5290 {
5291 /* No need to generate instruction. */
5292 return "";
5293 }
5294 else
5295 {
5296 /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */
5297 if (REGNO (operands[0]) == SP_REGNUM
5298 && REGNO (operands[1]) == SP_REGNUM)
5299 push_en4_only_p = 1;
5300
5301 /* Create assembly code pattern.
5302 We need to handle the form: "Rb, Re, { $fp $gp $lp }". */
5303 snprintf (pattern, sizeof (pattern),
5304 "push.s\t%s{%s%s%s }",
5305 push_en4_only_p ? "" : "%0, %1, ",
5306 cfun->machine->fp_size ? " $fp" : "",
5307 cfun->machine->gp_size ? " $gp" : "",
5308 cfun->machine->lp_size ? " $lp" : "");
5309 }
5310 }
5311
5312 /* We use output_asm_insn() to output assembly code by ourself. */
5313 output_asm_insn (pattern, operands);
5314 return "";
5315 }
5316
5317 /* Function to output stack pop operation.
5318 We need to deal with normal stack pop multiple or stack v3pop. */
5319 const char *
5320 nds32_output_stack_pop (void)
5321 {
5322 /* A string pattern for output_asm_insn(). */
5323 char pattern[100];
5324 /* The operands array which will be used in output_asm_insn(). */
5325 rtx operands[3];
5326 /* Pick up callee-saved first regno and last regno for further use. */
5327 int rb_regno = cfun->machine->callee_saved_regs_first_regno;
5328 int re_regno = cfun->machine->callee_saved_regs_last_regno;
5329
5330 if (TARGET_V3PUSH)
5331 {
5332 /* For stack v3pop:
5333 operands[0]: Re
5334 operands[1]: imm8u */
5335
5336 /* This variable is to check if 'pop25 Re,imm8u' is available. */
5337 int sp_adjust;
5338
5339 /* Set operands[0]. */
5340 operands[0] = gen_rtx_REG (SImode, re_regno);
5341
5342 /* Check if we can generate 'pop25 Re,imm8u',
5343 otherwise, generate 'pop25 Re,0'.
5344 We have to consider alloca issue as well.
5345 If the function does call alloca(), the stack pointer is not fixed.
5346 In that case, we cannot use 'pop25 Re,imm8u' directly.
5347 We have to caculate stack pointer from frame pointer
5348 and then use 'pop25 Re,0'. */
5349 sp_adjust = cfun->machine->local_size
5350 + cfun->machine->out_args_size
5351 + cfun->machine->callee_saved_area_padding_bytes;
5352 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
5353 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)
5354 && !cfun->calls_alloca)
5355 operands[1] = GEN_INT (sp_adjust);
5356 else
5357 operands[1] = GEN_INT (0);
5358
5359 /* Create assembly code pattern. */
5360 snprintf (pattern, sizeof (pattern), "pop25\t%%0, %%1");
5361 }
5362 else
5363 {
5364 /* For normal stack pop multiple:
5365 operands[0]: Rb
5366 operands[1]: Re
5367 operands[2]: En4 */
5368
5369 /* This variable is used to check if we only need to generate En4 field.
5370 As long as Rb==Re=SP_REGNUM, we set this variable to 1. */
5371 int pop_en4_only_p = 0;
5372
5373 /* Set operands[0] and operands[1]. */
5374 operands[0] = gen_rtx_REG (SImode, rb_regno);
5375 operands[1] = gen_rtx_REG (SImode, re_regno);
5376
5377 /* 'lmw.bim $sp,[$sp],$sp,0' means pop nothing. */
5378 if (!cfun->machine->fp_size
5379 && !cfun->machine->gp_size
5380 && !cfun->machine->lp_size
5381 && REGNO (operands[0]) == SP_REGNUM
5382 && REGNO (operands[1]) == SP_REGNUM)
5383 {
5384 /* No need to generate instruction. */
5385 return "";
5386 }
5387 else
5388 {
5389 /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */
5390 if (REGNO (operands[0]) == SP_REGNUM
5391 && REGNO (operands[1]) == SP_REGNUM)
5392 pop_en4_only_p = 1;
5393
5394 /* Create assembly code pattern.
5395 We need to handle the form: "Rb, Re, { $fp $gp $lp }". */
5396 snprintf (pattern, sizeof (pattern),
5397 "pop.s\t%s{%s%s%s }",
5398 pop_en4_only_p ? "" : "%0, %1, ",
5399 cfun->machine->fp_size ? " $fp" : "",
5400 cfun->machine->gp_size ? " $gp" : "",
5401 cfun->machine->lp_size ? " $lp" : "");
5402 }
5403 }
5404
5405 /* We use output_asm_insn() to output assembly code by ourself. */
5406 output_asm_insn (pattern, operands);
5407 return "";
5408 }
5409
5410 /* Return align 2 (log base 2) if the next instruction of LABEL is 4 byte. */
5411 int
5412 nds32_target_alignment (rtx label)
5413 {
5414 rtx insn;
5415
5416 if (optimize_size)
5417 return 0;
5418
5419 insn = next_active_insn (label);
5420
5421 if (insn == 0)
5422 return 0;
5423 else if ((get_attr_length (insn) % 4) == 0)
5424 return 2;
5425 else
5426 return 0;
5427 }
5428
5429 /* ------------------------------------------------------------------------ */
5430
5431 /* PART 5: Initialize target hook structure and definitions. */
5432 \f
5433 /* Controlling the Compilation Driver. */
5434
5435 \f
5436 /* Run-time Target Specification. */
5437
5438 \f
5439 /* Defining Data Structures for Per-function Information. */
5440
5441 \f
5442 /* Storage Layout. */
5443
5444 #undef TARGET_PROMOTE_FUNCTION_MODE
5445 #define TARGET_PROMOTE_FUNCTION_MODE \
5446 default_promote_function_mode_always_promote
5447
5448 \f
5449 /* Layout of Source Language Data Types. */
5450
5451 \f
5452 /* Register Usage. */
5453
5454 /* -- Basic Characteristics of Registers. */
5455
5456 /* -- Order of Allocation of Registers. */
5457
5458 /* -- How Values Fit in Registers. */
5459
5460 /* -- Handling Leaf Functions. */
5461
5462 /* -- Registers That Form a Stack. */
5463
5464 \f
5465 /* Register Classes. */
5466
5467 #undef TARGET_CLASS_MAX_NREGS
5468 #define TARGET_CLASS_MAX_NREGS nds32_class_max_nregs
5469
5470 #undef TARGET_LRA_P
5471 #define TARGET_LRA_P hook_bool_void_true
5472
5473 #undef TARGET_REGISTER_PRIORITY
5474 #define TARGET_REGISTER_PRIORITY nds32_register_priority
5475
5476 \f
5477 /* Obsolete Macros for Defining Constraints. */
5478
5479 \f
5480 /* Stack Layout and Calling Conventions. */
5481
5482 /* -- Basic Stack Layout. */
5483
5484 /* -- Exception Handling Support. */
5485
5486 /* -- Specifying How Stack Checking is Done. */
5487
5488 /* -- Registers That Address the Stack Frame. */
5489
5490 /* -- Eliminating Frame Pointer and Arg Pointer. */
5491
5492 #undef TARGET_CAN_ELIMINATE
5493 #define TARGET_CAN_ELIMINATE nds32_can_eliminate
5494
5495 /* -- Passing Function Arguments on the Stack. */
5496
5497 /* -- Passing Arguments in Registers. */
5498
5499 #undef TARGET_FUNCTION_ARG
5500 #define TARGET_FUNCTION_ARG nds32_function_arg
5501
5502 #undef TARGET_FUNCTION_ARG_ADVANCE
5503 #define TARGET_FUNCTION_ARG_ADVANCE nds32_function_arg_advance
5504
5505 #undef TARGET_FUNCTION_ARG_BOUNDARY
5506 #define TARGET_FUNCTION_ARG_BOUNDARY nds32_function_arg_boundary
5507
5508 /* -- How Scalar Function Values Are Returned. */
5509
5510 #undef TARGET_FUNCTION_VALUE
5511 #define TARGET_FUNCTION_VALUE nds32_function_value
5512
5513 #undef TARGET_LIBCALL_VALUE
5514 #define TARGET_LIBCALL_VALUE nds32_libcall_value
5515
5516 #undef TARGET_FUNCTION_VALUE_REGNO_P
5517 #define TARGET_FUNCTION_VALUE_REGNO_P nds32_function_value_regno_p
5518
5519 /* -- How Large Values Are Returned. */
5520
5521 /* -- Caller-Saves Register Allocation. */
5522
5523 /* -- Function Entry and Exit. */
5524
5525 #undef TARGET_ASM_FUNCTION_PROLOGUE
5526 #define TARGET_ASM_FUNCTION_PROLOGUE nds32_asm_function_prologue
5527
5528 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
5529 #define TARGET_ASM_FUNCTION_END_PROLOGUE nds32_asm_function_end_prologue
5530
5531 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
5532 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE nds32_asm_function_begin_epilogue
5533
5534 #undef TARGET_ASM_FUNCTION_EPILOGUE
5535 #define TARGET_ASM_FUNCTION_EPILOGUE nds32_asm_function_epilogue
5536
5537 #undef TARGET_ASM_OUTPUT_MI_THUNK
5538 #define TARGET_ASM_OUTPUT_MI_THUNK nds32_asm_output_mi_thunk
5539
5540 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5541 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
5542
5543 /* -- Generating Code for Profiling. */
5544
5545 /* -- Permitting tail calls. */
5546
5547 #undef TARGET_WARN_FUNC_RETURN
5548 #define TARGET_WARN_FUNC_RETURN nds32_warn_func_return
5549
5550 /* Stack smashing protection. */
5551
5552 \f
5553 /* Implementing the Varargs Macros. */
5554
5555 #undef TARGET_STRICT_ARGUMENT_NAMING
5556 #define TARGET_STRICT_ARGUMENT_NAMING nds32_strict_argument_naming
5557
5558 \f
5559 /* Trampolines for Nested Functions. */
5560
5561 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
5562 #define TARGET_ASM_TRAMPOLINE_TEMPLATE nds32_asm_trampoline_template
5563
5564 #undef TARGET_TRAMPOLINE_INIT
5565 #define TARGET_TRAMPOLINE_INIT nds32_trampoline_init
5566
5567 \f
5568 /* Implicit Calls to Library Routines. */
5569
5570 \f
5571 /* Addressing Modes. */
5572
5573 #undef TARGET_LEGITIMATE_ADDRESS_P
5574 #define TARGET_LEGITIMATE_ADDRESS_P nds32_legitimate_address_p
5575
5576 \f
5577 /* Anchored Addresses. */
5578
5579 \f
5580 /* Condition Code Status. */
5581
5582 /* -- Representation of condition codes using (cc0). */
5583
5584 /* -- Representation of condition codes using registers. */
5585
5586 /* -- Macros to control conditional execution. */
5587
5588 \f
5589 /* Describing Relative Costs of Operations. */
5590
5591 #undef TARGET_REGISTER_MOVE_COST
5592 #define TARGET_REGISTER_MOVE_COST nds32_register_move_cost
5593
5594 #undef TARGET_MEMORY_MOVE_COST
5595 #define TARGET_MEMORY_MOVE_COST nds32_memory_move_cost
5596
5597 #undef TARGET_RTX_COSTS
5598 #define TARGET_RTX_COSTS nds32_rtx_costs
5599
5600 #undef TARGET_ADDRESS_COST
5601 #define TARGET_ADDRESS_COST nds32_address_cost
5602
5603 \f
5604 /* Adjusting the Instruction Scheduler. */
5605
5606 \f
5607 /* Dividing the Output into Sections (Texts, Data, . . . ). */
5608
5609 \f
5610 /* Position Independent Code. */
5611
5612 \f
5613 /* Defining the Output Assembler Language. */
5614
5615 /* -- The Overall Framework of an Assembler File. */
5616
5617 #undef TARGET_ASM_FILE_START
5618 #define TARGET_ASM_FILE_START nds32_asm_file_start
5619 #undef TARGET_ASM_FILE_END
5620 #define TARGET_ASM_FILE_END nds32_asm_file_end
5621
5622 /* -- Output of Data. */
5623
5624 #undef TARGET_ASM_ALIGNED_HI_OP
5625 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
5626
5627 #undef TARGET_ASM_ALIGNED_SI_OP
5628 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
5629
5630 /* -- Output of Uninitialized Variables. */
5631
5632 /* -- Output and Generation of Labels. */
5633
5634 #undef TARGET_ASM_GLOBALIZE_LABEL
5635 #define TARGET_ASM_GLOBALIZE_LABEL nds32_asm_globalize_label
5636
5637 /* -- How Initialization Functions Are Handled. */
5638
5639 /* -- Macros Controlling Initialization Routines. */
5640
5641 /* -- Output of Assembler Instructions. */
5642
5643 #undef TARGET_PRINT_OPERAND
5644 #define TARGET_PRINT_OPERAND nds32_print_operand
5645 #undef TARGET_PRINT_OPERAND_ADDRESS
5646 #define TARGET_PRINT_OPERAND_ADDRESS nds32_print_operand_address
5647
5648 /* -- Output of Dispatch Tables. */
5649
5650 /* -- Assembler Commands for Exception Regions. */
5651
5652 /* -- Assembler Commands for Alignment. */
5653
5654 \f
5655 /* Controlling Debugging Information Format. */
5656
5657 /* -- Macros Affecting All Debugging Formats. */
5658
5659 /* -- Specific Options for DBX Output. */
5660
5661 /* -- Open-Ended Hooks for DBX Format. */
5662
5663 /* -- File Names in DBX Format. */
5664
5665 /* -- Macros for SDB and DWARF Output. */
5666
5667 /* -- Macros for VMS Debug Format. */
5668
5669 \f
5670 /* Cross Compilation and Floating Point. */
5671
5672 \f
5673 /* Mode Switching Instructions. */
5674
5675 \f
5676 /* Defining target-specific uses of __attribute__. */
5677
5678 #undef TARGET_ATTRIBUTE_TABLE
5679 #define TARGET_ATTRIBUTE_TABLE nds32_attribute_table
5680
5681 #undef TARGET_MERGE_DECL_ATTRIBUTES
5682 #define TARGET_MERGE_DECL_ATTRIBUTES nds32_merge_decl_attributes
5683
5684 #undef TARGET_INSERT_ATTRIBUTES
5685 #define TARGET_INSERT_ATTRIBUTES nds32_insert_attributes
5686
5687 #undef TARGET_OPTION_PRAGMA_PARSE
5688 #define TARGET_OPTION_PRAGMA_PARSE nds32_option_pragma_parse
5689
5690 #undef TARGET_OPTION_OVERRIDE
5691 #define TARGET_OPTION_OVERRIDE nds32_option_override
5692
5693 \f
5694 /* Emulating TLS. */
5695
5696 \f
5697 /* Defining coprocessor specifics for MIPS targets. */
5698
5699 \f
5700 /* Parameters for Precompiled Header Validity Checking. */
5701
5702 \f
5703 /* C++ ABI parameters. */
5704
5705 \f
5706 /* Adding support for named address spaces. */
5707
5708 \f
5709 /* Miscellaneous Parameters. */
5710
5711 #undef TARGET_INIT_BUILTINS
5712 #define TARGET_INIT_BUILTINS nds32_init_builtins
5713
5714 #undef TARGET_EXPAND_BUILTIN
5715 #define TARGET_EXPAND_BUILTIN nds32_expand_builtin
5716
5717 \f
5718 /* ------------------------------------------------------------------------ */
5719
5720 /* Initialize the GCC target structure. */
5721
5722 struct gcc_target targetm = TARGET_INITIALIZER;
5723
5724 /* ------------------------------------------------------------------------ */