]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/nds32/nds32.c
t-mlibs (MULTILIB_OPTIONS): Fix typo in comment.
[thirdparty/gcc.git] / gcc / config / nds32 / nds32.c
CommitLineData
9304f876 1/* Subroutines used for code generation of Andes NDS32 cpu for GNU compiler
23a5b65a 2 Copyright (C) 2012-2014 Free Software Foundation, Inc.
9304f876
CJW
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"
d8a2d370
DN
28#include "stor-layout.h"
29#include "varasm.h"
30#include "calls.h"
9304f876
CJW
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. */
80static 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. */
86static const char * const nds32_intrinsic_register_names[] =
87{
88 "$PSW", "$IPSW", "$ITYPE", "$IPC"
89};
90
91/* Defining target-specific uses of __attribute__. */
92static 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. */
130static struct machine_function *
131nds32_init_machine_status (void)
132{
133 struct machine_function *machine;
134 machine = ggc_alloc_cleared_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. */
147static void
148nds32_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". */
356static rtx
357nds32_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". */
490static rtx
491nds32_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". */
623static rtx
624nds32_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". */
744static rtx
745nds32_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. */
865static bool
866nds32_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. */
910static void
911nds32_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. */
930static void
931nds32_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. */
937static void
938nds32_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. */
956static void
957nds32_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. */
1098static void
1099nds32_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. */
1183static void
1184nds32_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(). */
1232static void
1233nds32_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. */
1368static int
1369nds32_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. */
1436static bool
1437nds32_needs_double_word_align (enum machine_mode mode, const_tree type)
1438{
1439 unsigned int align;
1440
634bdae9
CJW
1441 /* Pick up the alignment according to the mode or type. */
1442 align = NDS32_MODE_TYPE_ALIGN (mode, type);
9304f876
CJW
1443
1444 return (align > PARM_BOUNDARY);
1445}
1446
1447/* Return true if FUNC is a naked function. */
810f736f
CJW
1448static bool
1449nds32_naked_function_p (tree func)
9304f876
CJW
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. */
1471static bool
1472nds32_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. */
1492static bool
1493nds32_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)])]'. */
1615static rtx
1616nds32_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)]))]'. */
1641static rtx
1642nds32_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. */
1669static rtx
1670nds32_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. */
1698static char
1699nds32_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. */
1716static int
1717nds32_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
1736static unsigned char
1737nds32_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
1745static int
1746nds32_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
1819static 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
1838static rtx
1839nds32_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. */
634bdae9
CJW
1857 unsigned int regno;
1858
1859 regno = NDS32_AVAILABLE_REGNUM_FOR_ARG (cum->reg_offset, mode, type);
1860 return gen_rtx_REG (mode, regno);
9304f876
CJW
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
1870static void
1871nds32_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
1887static unsigned int
1888nds32_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
1897static rtx
1898nds32_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
1913static rtx
1914nds32_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
1920static bool
1921nds32_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. */
1930static void
1931nds32_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 /* GCC build attributes list with reverse order,
1964 so we use nreverse() to make it looks like
1965 the order that user specifies. */
1966 attrs = nreverse (DECL_ATTRIBUTES (current_function_decl));
1967
1968 /* If there is no any attribute, print out "None". */
1969 if (!attrs)
1970 fprintf (file, "None");
1971
1972 /* If there are some attributes, try if we need to
1973 construct isr vector information. */
1974 func_name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
1975 nds32_construct_isr_vectors_information (attrs, func_name);
1976
1977 /* Display all attributes of this function. */
1978 while (attrs)
1979 {
1980 name = TREE_PURPOSE (attrs);
1981 fprintf (file, "%s ", IDENTIFIER_POINTER (name));
1982
1983 /* Pick up the next attribute. */
1984 attrs = TREE_CHAIN (attrs);
1985 }
1986 fputc ('\n', file);
1987}
1988
1989/* After rtl prologue has been expanded, this function is used. */
1990static void
1991nds32_asm_function_end_prologue (FILE *file)
1992{
1993 fprintf (file, "\t! END PROLOGUE\n");
1994
1995 /* If frame pointer is NOT needed and -mfp-as-gp is issued,
1996 we can generate special directive: ".omit_fp_begin"
1997 to guide linker doing fp-as-gp optimization.
1998 However, for a naked function, which means
1999 it should not have prologue/epilogue,
2000 using fp-as-gp still requires saving $fp by push/pop behavior and
2001 there is no benefit to use fp-as-gp on such small function.
2002 So we need to make sure this function is NOT naked as well. */
2003 if (!frame_pointer_needed
2004 && !cfun->machine->naked_p
2005 && cfun->machine->fp_as_gp_p)
2006 {
2007 fprintf (file, "\t! ----------------------------------------\n");
2008 fprintf (file, "\t! Guide linker to do "
2009 "link time optimization: fp-as-gp\n");
2010 fprintf (file, "\t! We add one more instruction to "
2011 "initialize $fp near to $gp location.\n");
2012 fprintf (file, "\t! If linker fails to use fp-as-gp transformation,\n");
2013 fprintf (file, "\t! this extra instruction should be "
2014 "eliminated at link stage.\n");
2015 fprintf (file, "\t.omit_fp_begin\n");
2016 fprintf (file, "\tla\t$fp,_FP_BASE_\n");
2017 fprintf (file, "\t! ----------------------------------------\n");
2018 }
2019}
2020
2021/* Before rtl epilogue has been expanded, this function is used. */
2022static void
2023nds32_asm_function_begin_epilogue (FILE *file)
2024{
2025 /* If frame pointer is NOT needed and -mfp-as-gp is issued,
2026 we can generate special directive: ".omit_fp_end"
2027 to claim fp-as-gp optimization range.
2028 However, for a naked function,
2029 which means it should not have prologue/epilogue,
2030 using fp-as-gp still requires saving $fp by push/pop behavior and
2031 there is no benefit to use fp-as-gp on such small function.
2032 So we need to make sure this function is NOT naked as well. */
2033 if (!frame_pointer_needed
2034 && !cfun->machine->naked_p
2035 && cfun->machine->fp_as_gp_p)
2036 {
2037 fprintf (file, "\t! ----------------------------------------\n");
2038 fprintf (file, "\t! Claim the range of fp-as-gp "
2039 "link time optimization\n");
2040 fprintf (file, "\t.omit_fp_end\n");
2041 fprintf (file, "\t! ----------------------------------------\n");
2042 }
2043
2044 fprintf (file, "\t! BEGIN EPILOGUE\n");
2045}
2046
2047/* The content produced from this function
2048 will be placed after epilogue body. */
2049static void
2050nds32_asm_function_epilogue (FILE *file,
2051 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
2052{
2053 fprintf (file, "\t! END EPILOGUE\n");
2054}
2055
2056static void
2057nds32_asm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
2058 HOST_WIDE_INT delta,
2059 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
2060 tree function)
2061{
2062 int this_regno;
2063
2064 /* Make sure unwind info is emitted for the thunk if needed. */
2065 final_start_function (emit_barrier (), file, 1);
2066
2067 this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)
2068 ? 1
2069 : 0);
2070
2071 if (delta != 0)
2072 {
2073 if (satisfies_constraint_Is15 (GEN_INT (delta)))
2074 {
2075 fprintf (file, "\taddi\t$r%d, $r%d, %ld\n",
2076 this_regno, this_regno, delta);
2077 }
2078 else if (satisfies_constraint_Is20 (GEN_INT (delta)))
2079 {
2080 fprintf (file, "\tmovi\t$ta, %ld\n", delta);
2081 fprintf (file, "\tadd\t$r%d, $r%d, $ta\n", this_regno, this_regno);
2082 }
2083 else
2084 {
2085 fprintf (file, "\tsethi\t$ta, hi20(%ld)\n", delta);
2086 fprintf (file, "\tori\t$ta, $ta, lo12(%ld)\n", delta);
2087 fprintf (file, "\tadd\t$r%d, $r%d, $ta\n", this_regno, this_regno);
2088 }
2089 }
2090
2091 fprintf (file, "\tb\t");
2092 assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
2093 fprintf (file, "\n");
2094
2095 final_end_function ();
2096}
2097
2098/* -- Permitting tail calls. */
2099
2100/* Determine whether we need to enable warning for function return check. */
2101static bool
2102nds32_warn_func_return (tree decl)
2103{
2104/* Naked functions are implemented entirely in assembly, including the
2105 return sequence, so suppress warnings about this. */
2106 return !nds32_naked_function_p (decl);
2107}
2108
2109\f
2110/* Implementing the Varargs Macros. */
2111
2112static bool
2113nds32_strict_argument_naming (cumulative_args_t ca ATTRIBUTE_UNUSED)
2114{
2115 /* Return true so that all the named arguments for FUNCTION_ARG have named=1.
2116 If return false, for the variadic function, all named arguments EXCEPT
2117 the last are treated as named. */
2118 return true;
2119}
2120
2121\f
2122/* Trampolines for Nested Functions. */
2123
2124static void
2125nds32_asm_trampoline_template (FILE *f)
2126{
2127 if (TARGET_REDUCED_REGS)
2128 {
2129 /* Trampoline is not supported on reduced-set registers yet. */
2130 sorry ("a nested function is not supported for reduced registers");
2131 }
2132 else
2133 {
2134 asm_fprintf (f, "\t! Trampoline code template\n");
2135 asm_fprintf (f, "\t! This code fragment will be copied "
2136 "into stack on demand\n");
2137
2138 asm_fprintf (f, "\tmfusr\t$r16,$pc\n");
2139 asm_fprintf (f, "\tlwi\t$r15,[$r16 + 20] "
2140 "! load nested function address\n");
2141 asm_fprintf (f, "\tlwi\t$r16,[$r16 + 16] "
2142 "! load chain_value\n");
2143 asm_fprintf (f, "\tjr\t$r15\n");
2144 }
2145
2146 /* Preserve space ($pc + 16) for saving chain_value,
2147 nds32_trampoline_init will fill the value in this slot. */
2148 asm_fprintf (f, "\t! space for saving chain_value\n");
2149 assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
2150
2151 /* Preserve space ($pc + 20) for saving nested function address,
2152 nds32_trampoline_init will fill the value in this slot. */
2153 asm_fprintf (f, "\t! space for saving nested function address\n");
2154 assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
2155}
2156
2157/* Emit RTL insns to initialize the variable parts of a trampoline. */
2158static void
2159nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
2160{
2161 int i;
2162
2163 /* Nested function address. */
2164 rtx fnaddr;
2165 /* The memory rtx that is going to
2166 be filled with chain_value. */
2167 rtx chain_value_mem;
2168 /* The memory rtx that is going to
2169 be filled with nested function address. */
2170 rtx nested_func_mem;
2171
2172 /* Start address of trampoline code in stack, for doing cache sync. */
2173 rtx sync_cache_addr;
2174 /* Temporary register for sync instruction. */
2175 rtx tmp_reg;
2176 /* Instruction-cache sync instruction,
2177 requesting an argument as starting address. */
2178 rtx isync_insn;
2179 /* For convenience reason of doing comparison. */
2180 int tramp_align_in_bytes;
2181
2182 /* Trampoline is not supported on reduced-set registers yet. */
2183 if (TARGET_REDUCED_REGS)
2184 sorry ("a nested function is not supported for reduced registers");
2185
2186 /* STEP 1: Copy trampoline code template into stack,
2187 fill up essential data into stack. */
2188
2189 /* Extract nested function address rtx. */
2190 fnaddr = XEXP (DECL_RTL (fndecl), 0);
2191
2192 /* m_tramp is memory rtx that is going to be filled with trampoline code.
2193 We have nds32_asm_trampoline_template() to emit template pattern. */
2194 emit_block_move (m_tramp, assemble_trampoline_template (),
2195 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
2196
2197 /* After copying trampoline code into stack,
2198 fill chain_value into stack. */
2199 chain_value_mem = adjust_address (m_tramp, SImode, 16);
2200 emit_move_insn (chain_value_mem, chain_value);
2201 /* After copying trampoline code int stack,
2202 fill nested function address into stack. */
2203 nested_func_mem = adjust_address (m_tramp, SImode, 20);
2204 emit_move_insn (nested_func_mem, fnaddr);
2205
2206 /* STEP 2: Sync instruction-cache. */
2207
2208 /* We have successfully filled trampoline code into stack.
2209 However, in order to execute code in stack correctly,
2210 we must sync instruction cache. */
2211 sync_cache_addr = XEXP (m_tramp, 0);
2212 tmp_reg = gen_reg_rtx (SImode);
2213 isync_insn = gen_unspec_volatile_isync (tmp_reg);
2214
2215 /* Because nds32_cache_block_size is in bytes,
2216 we get trampoline alignment in bytes for convenient comparison. */
2217 tramp_align_in_bytes = TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT;
2218
2219 if (tramp_align_in_bytes >= nds32_cache_block_size
2220 && (tramp_align_in_bytes % nds32_cache_block_size) == 0)
2221 {
2222 /* Under this condition, the starting address of trampoline
2223 must be aligned to the starting address of each cache block
2224 and we do not have to worry about cross-boundary issue. */
2225 for (i = 0;
2226 i < (TRAMPOLINE_SIZE + nds32_cache_block_size - 1)
2227 / nds32_cache_block_size;
2228 i++)
2229 {
2230 emit_move_insn (tmp_reg,
2231 plus_constant (Pmode, sync_cache_addr,
2232 nds32_cache_block_size * i));
2233 emit_insn (isync_insn);
2234 }
2235 }
2236 else if (TRAMPOLINE_SIZE > nds32_cache_block_size)
2237 {
2238 /* The starting address of trampoline code
2239 may not be aligned to the cache block,
2240 so the trampoline code may be across two cache block.
2241 We need to sync the last element, which is 4-byte size,
2242 of trampoline template. */
2243 for (i = 0;
2244 i < (TRAMPOLINE_SIZE + nds32_cache_block_size - 1)
2245 / nds32_cache_block_size;
2246 i++)
2247 {
2248 emit_move_insn (tmp_reg,
2249 plus_constant (Pmode, sync_cache_addr,
2250 nds32_cache_block_size * i));
2251 emit_insn (isync_insn);
2252 }
2253
2254 /* The last element of trampoline template is 4-byte size. */
2255 emit_move_insn (tmp_reg,
2256 plus_constant (Pmode, sync_cache_addr,
2257 TRAMPOLINE_SIZE - 4));
2258 emit_insn (isync_insn);
2259 }
2260 else
2261 {
2262 /* This is the simplest case.
2263 Because TRAMPOLINE_SIZE is less than or
2264 equal to nds32_cache_block_size,
2265 we can just sync start address and
2266 the last element of trampoline code. */
2267
2268 /* Sync starting address of tampoline code. */
2269 emit_move_insn (tmp_reg, sync_cache_addr);
2270 emit_insn (isync_insn);
2271 /* Sync the last element, which is 4-byte size,
2272 of trampoline template. */
2273 emit_move_insn (tmp_reg,
2274 plus_constant (Pmode, sync_cache_addr,
2275 TRAMPOLINE_SIZE - 4));
2276 emit_insn (isync_insn);
2277 }
2278
2279 /* Set instruction serialization barrier
2280 to guarantee the correct operations. */
2281 emit_insn (gen_unspec_volatile_isb ());
2282}
2283
2284\f
2285/* Addressing Modes. */
2286
2287static bool
2288nds32_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
2289{
2290 /* For (mem:DI addr) or (mem:DF addr) case,
2291 we only allow 'addr' to be [reg], [symbol_ref],
2292 [const], or [reg + const_int] pattern. */
2293 if (mode == DImode || mode == DFmode)
2294 {
2295 /* Allow [Reg + const_int] addressing mode. */
2296 if (GET_CODE (x) == PLUS)
2297 {
2298 if (nds32_address_register_rtx_p (XEXP (x, 0), strict)
2299 && nds32_legitimate_index_p (mode, XEXP (x, 1), strict)
2300 && CONST_INT_P (XEXP (x, 1)))
2301 return true;
2302
2303 else if (nds32_address_register_rtx_p (XEXP (x, 1), strict)
2304 && nds32_legitimate_index_p (mode, XEXP (x, 0), strict)
2305 && CONST_INT_P (XEXP (x, 0)))
2306 return true;
2307 }
2308
2309 /* Now check [reg], [symbol_ref], and [const]. */
2310 if (GET_CODE (x) != REG
2311 && GET_CODE (x) != SYMBOL_REF
2312 && GET_CODE (x) != CONST)
2313 return false;
2314 }
2315
2316 /* Check if 'x' is a valid address. */
2317 switch (GET_CODE (x))
2318 {
2319 case REG:
2320 /* (mem (reg A)) => [Ra] */
2321 return nds32_address_register_rtx_p (x, strict);
2322
2323 case SYMBOL_REF:
2324
2325 if (!TARGET_GP_DIRECT
2326 && (reload_completed
2327 || reload_in_progress
2328 || lra_in_progress))
2329 return false;
2330
2331 /* (mem (symbol_ref A)) => [symbol_ref] */
2332 return !currently_expanding_to_rtl;
2333
2334 case CONST:
2335
2336 if (!TARGET_GP_DIRECT
2337 && (reload_completed
2338 || reload_in_progress
2339 || lra_in_progress))
2340 return false;
2341
2342 /* (mem (const (...)))
2343 => [ + const_addr ], where const_addr = symbol_ref + const_int */
2344 if (GET_CODE (XEXP (x, 0)) == PLUS)
2345 {
2346 rtx plus_op = XEXP (x, 0);
2347
2348 rtx op0 = XEXP (plus_op, 0);
2349 rtx op1 = XEXP (plus_op, 1);
2350
2351 if (GET_CODE (op0) == SYMBOL_REF && CONST_INT_P (op1))
2352 return true;
2353 else
2354 return false;
2355 }
2356
2357 return false;
2358
2359 case POST_MODIFY:
2360 /* (mem (post_modify (reg) (plus (reg) (reg))))
2361 => [Ra], Rb */
2362 /* (mem (post_modify (reg) (plus (reg) (const_int))))
2363 => [Ra], const_int */
2364 if (GET_CODE (XEXP (x, 0)) == REG
2365 && GET_CODE (XEXP (x, 1)) == PLUS)
2366 {
2367 rtx plus_op = XEXP (x, 1);
2368
2369 rtx op0 = XEXP (plus_op, 0);
2370 rtx op1 = XEXP (plus_op, 1);
2371
2372 if (nds32_address_register_rtx_p (op0, strict)
2373 && nds32_legitimate_index_p (mode, op1, strict))
2374 return true;
2375 else
2376 return false;
2377 }
2378
2379 return false;
2380
2381 case POST_INC:
2382 case POST_DEC:
2383 /* (mem (post_inc reg)) => [Ra], 1/2/4 */
2384 /* (mem (post_dec reg)) => [Ra], -1/-2/-4 */
2385 /* The 1/2/4 or -1/-2/-4 have been displayed in nds32.md.
2386 We only need to deal with register Ra. */
2387 if (nds32_address_register_rtx_p (XEXP (x, 0), strict))
2388 return true;
2389 else
2390 return false;
2391
2392 case PLUS:
2393 /* (mem (plus reg const_int))
2394 => [Ra + imm] */
2395 /* (mem (plus reg reg))
2396 => [Ra + Rb] */
2397 /* (mem (plus (mult reg const_int) reg))
2398 => [Ra + Rb << sv] */
2399 if (nds32_address_register_rtx_p (XEXP (x, 0), strict)
2400 && nds32_legitimate_index_p (mode, XEXP (x, 1), strict))
2401 return true;
2402 else if (nds32_address_register_rtx_p (XEXP (x, 1), strict)
2403 && nds32_legitimate_index_p (mode, XEXP (x, 0), strict))
2404 return true;
2405 else
2406 return false;
2407
2408 case LO_SUM:
2409 if (!TARGET_GP_DIRECT)
2410 return true;
2411
2412 default:
2413 return false;
2414 }
2415}
2416
2417\f
2418/* Describing Relative Costs of Operations. */
2419
2420static int nds32_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2421 reg_class_t from,
2422 reg_class_t to)
2423{
2424 if (from == HIGH_REGS || to == HIGH_REGS)
2425 return 6;
2426
2427 return 2;
2428}
2429
2430static int nds32_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2431 reg_class_t rclass ATTRIBUTE_UNUSED,
2432 bool in ATTRIBUTE_UNUSED)
2433{
2434 return 8;
2435}
2436
2437/* This target hook describes the relative costs of RTL expressions.
2438 Return 'true' when all subexpressions of x have been processed.
2439 Return 'false' to sum the costs of sub-rtx, plus cost of this operation.
2440 Refer to gcc/rtlanal.c for more information. */
2441static bool
2442nds32_rtx_costs (rtx x,
2443 int code,
2444 int outer_code,
2445 int opno ATTRIBUTE_UNUSED,
2446 int *total,
2447 bool speed)
2448{
2449 /* According to 'speed', goto suitable cost model section. */
2450 if (speed)
2451 goto performance_cost;
2452 else
2453 goto size_cost;
2454
2455
2456performance_cost:
2457 /* This is section for performance cost model. */
2458
2459 /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4.
2460 We treat it as 4-cycle cost for each instruction
2461 under performance consideration. */
2462 switch (code)
2463 {
2464 case SET:
2465 /* For 'SET' rtx, we need to return false
2466 so that it can recursively calculate costs. */
2467 return false;
2468
2469 case USE:
2470 /* Used in combine.c as a marker. */
2471 *total = 0;
2472 break;
2473
2474 case MULT:
506cb361 2475 *total = COSTS_N_INSNS (1);
9304f876
CJW
2476 break;
2477
2478 case DIV:
2479 case UDIV:
2480 case MOD:
2481 case UMOD:
2482 *total = COSTS_N_INSNS (7);
2483 break;
2484
2485 default:
2486 *total = COSTS_N_INSNS (1);
2487 break;
2488 }
2489
2490 return true;
2491
2492
2493size_cost:
2494 /* This is section for size cost model. */
2495
2496 /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4.
2497 We treat it as 4-byte cost for each instruction
2498 under code size consideration. */
2499 switch (code)
2500 {
2501 case SET:
2502 /* For 'SET' rtx, we need to return false
2503 so that it can recursively calculate costs. */
2504 return false;
2505
2506 case USE:
2507 /* Used in combine.c as a marker. */
2508 *total = 0;
2509 break;
2510
2511 case CONST_INT:
2512 /* All instructions involving constant operation
2513 need to be considered for cost evaluation. */
2514 if (outer_code == SET)
2515 {
2516 /* (set X imm5s), use movi55, 2-byte cost.
2517 (set X imm20s), use movi, 4-byte cost.
2518 (set X BIG_INT), use sethi/ori, 8-byte cost. */
2519 if (satisfies_constraint_Is05 (x))
2520 *total = COSTS_N_INSNS (1) - 2;
2521 else if (satisfies_constraint_Is20 (x))
2522 *total = COSTS_N_INSNS (1);
2523 else
2524 *total = COSTS_N_INSNS (2);
2525 }
2526 else if (outer_code == PLUS || outer_code == MINUS)
2527 {
2528 /* Possible addi333/subi333 or subi45/addi45, 2-byte cost.
2529 General case, cost 1 instruction with 4-byte. */
2530 if (satisfies_constraint_Iu05 (x))
2531 *total = COSTS_N_INSNS (1) - 2;
2532 else
2533 *total = COSTS_N_INSNS (1);
2534 }
2535 else if (outer_code == ASHIFT)
2536 {
2537 /* Possible slli333, 2-byte cost.
2538 General case, cost 1 instruction with 4-byte. */
2539 if (satisfies_constraint_Iu03 (x))
2540 *total = COSTS_N_INSNS (1) - 2;
2541 else
2542 *total = COSTS_N_INSNS (1);
2543 }
2544 else if (outer_code == ASHIFTRT || outer_code == LSHIFTRT)
2545 {
2546 /* Possible srai45 or srli45, 2-byte cost.
2547 General case, cost 1 instruction with 4-byte. */
2548 if (satisfies_constraint_Iu05 (x))
2549 *total = COSTS_N_INSNS (1) - 2;
2550 else
2551 *total = COSTS_N_INSNS (1);
2552 }
2553 else
2554 {
2555 /* For other cases, simply set it 4-byte cost. */
2556 *total = COSTS_N_INSNS (1);
2557 }
2558 break;
2559
2560 case CONST_DOUBLE:
2561 /* It requires high part and low part processing, set it 8-byte cost. */
2562 *total = COSTS_N_INSNS (2);
2563 break;
2564
2565 default:
2566 /* For other cases, generally we set it 4-byte cost
2567 and stop resurively traversing. */
2568 *total = COSTS_N_INSNS (1);
2569 break;
2570 }
2571
2572 return true;
2573}
2574
2575static int nds32_address_cost (rtx address,
2576 enum machine_mode mode ATTRIBUTE_UNUSED,
2577 addr_space_t as ATTRIBUTE_UNUSED,
2578 bool speed)
2579{
2580 rtx plus0, plus1;
2581 enum rtx_code code;
2582
2583 code = GET_CODE (address);
2584
2585 /* According to 'speed', goto suitable cost model section. */
2586 if (speed)
2587 goto performance_cost;
2588 else
2589 goto size_cost;
2590
2591performance_cost:
2592 /* This is section for performance cost model. */
2593
2594 /* FALLTHRU, currently we use same cost model as size_cost. */
2595
2596size_cost:
2597 /* This is section for size cost model. */
2598
2599 switch (code)
2600 {
2601 case POST_MODIFY:
2602 case POST_INC:
2603 case POST_DEC:
2604 /* We encourage that rtx contains
2605 POST_MODIFY/POST_INC/POST_DEC behavior. */
2606 return 0;
2607
2608 case SYMBOL_REF:
2609 /* We can have gp-relative load/store for symbol_ref.
2610 Have it 4-byte cost. */
2611 return COSTS_N_INSNS (1);
2612
2613 case CONST:
2614 /* It is supposed to be the pattern (const (plus symbol_ref const_int)).
2615 Have it 4-byte cost. */
2616 return COSTS_N_INSNS (1);
2617
2618 case REG:
2619 /* Simply return 4-byte costs. */
2620 return COSTS_N_INSNS (1);
2621
2622 case PLUS:
2623 /* We do not need to check if the address is a legitimate address,
2624 because this hook is never called with an invalid address.
2625 But we better check the range of
2626 const_int value for cost, if it exists. */
2627 plus0 = XEXP (address, 0);
2628 plus1 = XEXP (address, 1);
2629
2630 if (REG_P (plus0) && CONST_INT_P (plus1))
2631 {
2632 /* If it is possible to be lwi333/swi333 form,
2633 make it 2-byte cost. */
2634 if (satisfies_constraint_Iu05 (plus1))
2635 return (COSTS_N_INSNS (1) - 2);
2636 else
2637 return COSTS_N_INSNS (1);
2638 }
2639
2640 /* For other 'plus' situation, make it cost 4-byte. */
2641 return COSTS_N_INSNS (1);
2642
2643 default:
2644 break;
2645 }
2646
2647 return COSTS_N_INSNS (4);
2648}
2649
2650\f
2651/* Defining the Output Assembler Language. */
2652
2653/* -- The Overall Framework of an Assembler File. */
2654
2655static void
2656nds32_asm_file_start (void)
2657{
2658 int i;
2659
2660 default_file_start ();
2661
2662 /* Tell assembler which ABI we are using. */
2663 fprintf (asm_out_file, "\t! ABI version\n");
2664 fprintf (asm_out_file, "\t.abi_2\n");
2665
2666 /* Tell assembler that this asm code is generated by compiler. */
2667 fprintf (asm_out_file, "\t! This asm file is generated by compiler\n");
2668 fprintf (asm_out_file, "\t.flag\tverbatim\n");
2669 /* Give assembler the size of each vector for interrupt handler. */
2670 fprintf (asm_out_file, "\t! This vector size directive is required "
2671 "for checking inconsistency on interrupt handler\n");
2672 fprintf (asm_out_file, "\t.vec_size\t%d\n", nds32_isr_vector_size);
2673
2674 /* If user enables '-mforce-fp-as-gp' or compiles programs with -Os,
2675 the compiler may produce 'la $fp,_FP_BASE_' instruction
2676 at prologue for fp-as-gp optimization.
2677 We should emit weak reference of _FP_BASE_ to avoid undefined reference
2678 in case user does not pass '--relax' option to linker. */
2679 if (TARGET_FORCE_FP_AS_GP || optimize_size)
2680 {
2681 fprintf (asm_out_file, "\t! This weak reference is required to do "
2682 "fp-as-gp link time optimization\n");
2683 fprintf (asm_out_file, "\t.weak\t_FP_BASE_\n");
2684 }
2685 /* If user enables '-mex9', we should emit relaxation directive
2686 to tell linker that this file is allowed to do ex9 optimization. */
2687 if (TARGET_EX9)
2688 {
2689 fprintf (asm_out_file, "\t! This relaxation directive is required "
2690 "to do ex9 link time optimization\n");
2691 fprintf (asm_out_file, "\t.relax\tex9\n");
2692 }
2693
2694 fprintf (asm_out_file, "\t! ------------------------------------\n");
2695
2696 if (TARGET_ISA_V2)
2697 fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V2");
2698 if (TARGET_ISA_V3)
2699 fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V3");
2700 if (TARGET_ISA_V3M)
2701 fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V3M");
2702
2703 fprintf (asm_out_file, "\t! Endian setting\t: %s\n",
2704 ((TARGET_BIG_ENDIAN) ? "big-endian"
2705 : "little-endian"));
2706
2707 fprintf (asm_out_file, "\t! ------------------------------------\n");
2708
2709 fprintf (asm_out_file, "\t! Use conditional move\t\t: %s\n",
2710 ((TARGET_CMOV) ? "Yes"
2711 : "No"));
2712 fprintf (asm_out_file, "\t! Use performance extension\t: %s\n",
2713 ((TARGET_PERF_EXT) ? "Yes"
2714 : "No"));
2715
2716 fprintf (asm_out_file, "\t! ------------------------------------\n");
2717
2718 fprintf (asm_out_file, "\t! V3PUSH instructions\t: %s\n",
2719 ((TARGET_V3PUSH) ? "Yes"
2720 : "No"));
2721 fprintf (asm_out_file, "\t! 16-bit instructions\t: %s\n",
2722 ((TARGET_16_BIT) ? "Yes"
2723 : "No"));
2724 fprintf (asm_out_file, "\t! GP base access\t: %s\n",
2725 ((TARGET_GP_DIRECT) ? "Yes"
2726 : "No"));
2727 fprintf (asm_out_file, "\t! Reduced registers set\t: %s\n",
2728 ((TARGET_REDUCED_REGS) ? "Yes"
2729 : "No"));
2730
2731 fprintf (asm_out_file, "\t! ------------------------------------\n");
2732
2733 if (optimize_size)
2734 fprintf (asm_out_file, "\t! Optimization level\t: -Os\n");
2735 else
2736 fprintf (asm_out_file, "\t! Optimization level\t: -O%d\n", optimize);
2737
2738 fprintf (asm_out_file, "\t! ------------------------------------\n");
2739
2740 fprintf (asm_out_file, "\t! Cache block size\t: %d\n",
2741 nds32_cache_block_size);
2742
2743 fprintf (asm_out_file, "\t! ------------------------------------\n");
2744
2745 /* Initialize isr vector information array before compiling functions. */
2746 for (i = 0; i < NDS32_N_ISR_VECTORS; i++)
2747 {
2748 nds32_isr_vectors[i].category = NDS32_ISR_NONE;
2749 strcpy (nds32_isr_vectors[i].func_name, "");
2750 nds32_isr_vectors[i].save_reg = NDS32_PARTIAL_SAVE;
2751 nds32_isr_vectors[i].nested_type = NDS32_NOT_NESTED;
2752 nds32_isr_vectors[i].total_n_vectors = 0;
2753 strcpy (nds32_isr_vectors[i].nmi_name, "");
2754 strcpy (nds32_isr_vectors[i].warm_name, "");
2755 }
2756}
2757
2758static void
2759nds32_asm_file_end (void)
2760{
2761 int i;
2762
2763 /* If all the vectors are NDS32_ISR_NONE, we can return immediately. */
2764 for (i = 0; i < NDS32_N_ISR_VECTORS; i++)
2765 if (nds32_isr_vectors[i].category != NDS32_ISR_NONE)
2766 break;
2767
2768 if (i == NDS32_N_ISR_VECTORS)
2769 return;
2770
2771 /* At least one vector is NOT NDS32_ISR_NONE,
2772 we should output isr vector information. */
2773 fprintf (asm_out_file, "\t! ------------------------------------\n");
2774 fprintf (asm_out_file, "\t! The isr vector information:\n");
2775 fprintf (asm_out_file, "\t! ------------------------------------\n");
2776
2777 /* Check reset handler first. Its vector number is always 0. */
2778 if (nds32_isr_vectors[0].category == NDS32_ISR_RESET)
2779 {
2780 nds32_emit_isr_reset_content ();
2781 fprintf (asm_out_file, "\t! ------------------------------------\n");
2782 }
2783
2784 /* Check other vectors, starting from vector number 1. */
2785 for (i = 1; i < NDS32_N_ISR_VECTORS; i++)
2786 {
2787 if (nds32_isr_vectors[i].category == NDS32_ISR_INTERRUPT
2788 || nds32_isr_vectors[i].category == NDS32_ISR_EXCEPTION)
2789 {
2790 /* Found one vector which is interupt or exception.
2791 Output its jmptbl and vector section content. */
2792 fprintf (asm_out_file, "\t! interrupt/exception vector %02d\n", i);
2793 fprintf (asm_out_file, "\t! ------------------------------------\n");
2794 nds32_emit_isr_jmptbl_section (i);
2795 fprintf (asm_out_file, "\t! ....................................\n");
2796 nds32_emit_isr_vector_section (i);
2797 fprintf (asm_out_file, "\t! ------------------------------------\n");
2798 }
2799 }
2800
2801 fprintf (asm_out_file, "\t! ------------------------------------\n");
2802}
2803
2804/* -- Output and Generation of Labels. */
2805
2806static void
2807nds32_asm_globalize_label (FILE *stream, const char *name)
2808{
2809 fputs ("\t.global\t", stream);
2810 assemble_name (stream, name);
2811 fputs ("\n", stream);
2812}
2813
2814/* -- Output of Assembler Instructions. */
2815
2816static void
2817nds32_print_operand (FILE *stream, rtx x, int code)
2818{
2819 int op_value;
2820
2821 switch (code)
2822 {
2823 case 0 :
2824 /* Do nothing special. */
2825 break;
2826
2827 case 'V':
2828 /* 'x' is supposed to be CONST_INT, get the value. */
2829 gcc_assert (CONST_INT_P (x));
2830 op_value = INTVAL (x);
2831
2832 /* According to the Andes architecture,
2833 the system/user register index range is 0 ~ 1023.
2834 In order to avoid conflict between user-specified-integer value
2835 and enum-specified-register value,
2836 the 'enum nds32_intrinsic_registers' value
2837 in nds32_intrinsic.h starts from 1024. */
2838 if (op_value < 1024 && op_value >= 0)
2839 {
2840 /* If user gives integer value directly (0~1023),
2841 we just print out the value. */
2842 fprintf (stream, "%d", op_value);
2843 }
2844 else if (op_value < 0
2845 || op_value >= ((int) ARRAY_SIZE (nds32_intrinsic_register_names)
2846 + 1024))
2847 {
2848 /* The enum index value for array size is out of range. */
2849 error ("intrinsic register index is out of range");
2850 }
2851 else
2852 {
2853 /* If user applies normal way with __NDS32_REG_XXX__ enum data,
2854 we can print out register name. Remember to substract 1024. */
2855 fprintf (stream, "%s",
2856 nds32_intrinsic_register_names[op_value - 1024]);
2857 }
2858
2859 /* No need to handle following process, so return immediately. */
2860 return;
2861
2862 default :
2863 /* Unknown flag. */
2864 output_operand_lossage ("invalid operand output code");
2865 break;
2866 }
2867
2868 switch (GET_CODE (x))
2869 {
2870 case LABEL_REF:
2871 case SYMBOL_REF:
2872 output_addr_const (stream, x);
2873 break;
2874
2875 case REG:
2876 /* Forbid using static chain register ($r16)
2877 on reduced-set registers configuration. */
2878 if (TARGET_REDUCED_REGS
2879 && REGNO (x) == STATIC_CHAIN_REGNUM)
2880 sorry ("a nested function is not supported for reduced registers");
2881
2882 /* Normal cases, print out register name. */
2883 fputs (reg_names[REGNO (x)], stream);
2884 break;
2885
2886 case MEM:
2887 output_address (XEXP (x, 0));
2888 break;
2889
2890 case CODE_LABEL:
2891 case CONST_INT:
2892 case CONST:
2893 output_addr_const (stream, x);
2894 break;
2895
2896 default:
2897 /* Generally, output_addr_const () is able to handle most cases.
2898 We want to see what CODE could appear,
2899 so we use gcc_unreachable() to stop it. */
2900 debug_rtx (x);
2901 gcc_unreachable ();
2902 break;
2903 }
2904}
2905
2906static void
2907nds32_print_operand_address (FILE *stream, rtx x)
2908{
2909 rtx op0, op1;
2910
2911 switch (GET_CODE (x))
2912 {
2913 case SYMBOL_REF:
2914 case CONST:
2915 /* [ + symbol_ref] */
2916 /* [ + const_addr], where const_addr = symbol_ref + const_int */
2917 fputs ("[ + ", stream);
2918 output_addr_const (stream, x);
2919 fputs ("]", stream);
2920 break;
2921
2922 case REG:
2923 /* Forbid using static chain register ($r16)
2924 on reduced-set registers configuration. */
2925 if (TARGET_REDUCED_REGS
2926 && REGNO (x) == STATIC_CHAIN_REGNUM)
2927 sorry ("a nested function is not supported for reduced registers");
2928
2929 /* [Ra] */
2930 fprintf (stream, "[%s]", reg_names[REGNO (x)]);
2931 break;
2932
2933 case PLUS:
2934 op0 = XEXP (x, 0);
2935 op1 = XEXP (x, 1);
2936
2937 /* Checking op0, forbid using static chain register ($r16)
2938 on reduced-set registers configuration. */
2939 if (TARGET_REDUCED_REGS
2940 && REG_P (op0)
2941 && REGNO (op0) == STATIC_CHAIN_REGNUM)
2942 sorry ("a nested function is not supported for reduced registers");
2943 /* Checking op1, forbid using static chain register ($r16)
2944 on reduced-set registers configuration. */
2945 if (TARGET_REDUCED_REGS
2946 && REG_P (op1)
2947 && REGNO (op1) == STATIC_CHAIN_REGNUM)
2948 sorry ("a nested function is not supported for reduced registers");
2949
2950 if (REG_P (op0) && CONST_INT_P (op1))
2951 {
2952 /* [Ra + imm] */
2953 fprintf (stream, "[%s + (%d)]",
2954 reg_names[REGNO (op0)], (int)INTVAL (op1));
2955 }
2956 else if (REG_P (op0) && REG_P (op1))
2957 {
2958 /* [Ra + Rb] */
2959 fprintf (stream, "[%s + %s]",
2960 reg_names[REGNO (op0)], reg_names[REGNO (op1)]);
2961 }
2962 else if (GET_CODE (op0) == MULT && REG_P (op1))
2963 {
2964 /* [Ra + Rb << sv]
2965 From observation, the pattern looks like:
2966 (plus:SI (mult:SI (reg:SI 58)
2967 (const_int 4 [0x4]))
2968 (reg/f:SI 57)) */
2969 int sv;
2970
2971 /* We need to set sv to output shift value. */
2972 if (INTVAL (XEXP (op0, 1)) == 1)
2973 sv = 0;
2974 else if (INTVAL (XEXP (op0, 1)) == 2)
2975 sv = 1;
2976 else if (INTVAL (XEXP (op0, 1)) == 4)
2977 sv = 2;
2978 else
2979 gcc_unreachable ();
2980
2981 fprintf (stream, "[%s + %s << %d]",
2982 reg_names[REGNO (op1)],
2983 reg_names[REGNO (XEXP (op0, 0))],
2984 sv);
2985 }
2986 else
2987 {
2988 /* The control flow is not supposed to be here. */
2989 debug_rtx (x);
2990 gcc_unreachable ();
2991 }
2992
2993 break;
2994
2995 case POST_MODIFY:
2996 /* (post_modify (regA) (plus (regA) (regB)))
2997 (post_modify (regA) (plus (regA) (const_int)))
2998 We would like to extract
2999 regA and regB (or const_int) from plus rtx. */
3000 op0 = XEXP (XEXP (x, 1), 0);
3001 op1 = XEXP (XEXP (x, 1), 1);
3002
3003 /* Checking op0, forbid using static chain register ($r16)
3004 on reduced-set registers configuration. */
3005 if (TARGET_REDUCED_REGS
3006 && REG_P (op0)
3007 && REGNO (op0) == STATIC_CHAIN_REGNUM)
3008 sorry ("a nested function is not supported for reduced registers");
3009 /* Checking op1, forbid using static chain register ($r16)
3010 on reduced-set registers configuration. */
3011 if (TARGET_REDUCED_REGS
3012 && REG_P (op1)
3013 && REGNO (op1) == STATIC_CHAIN_REGNUM)
3014 sorry ("a nested function is not supported for reduced registers");
3015
3016 if (REG_P (op0) && REG_P (op1))
3017 {
3018 /* [Ra], Rb */
3019 fprintf (stream, "[%s], %s",
3020 reg_names[REGNO (op0)], reg_names[REGNO (op1)]);
3021 }
3022 else if (REG_P (op0) && CONST_INT_P (op1))
3023 {
3024 /* [Ra], imm */
3025 fprintf (stream, "[%s], %d",
3026 reg_names[REGNO (op0)], (int)INTVAL (op1));
3027 }
3028 else
3029 {
3030 /* The control flow is not supposed to be here. */
3031 debug_rtx (x);
3032 gcc_unreachable ();
3033 }
3034
3035 break;
3036
3037 case POST_INC:
3038 case POST_DEC:
3039 op0 = XEXP (x, 0);
3040
3041 /* Checking op0, forbid using static chain register ($r16)
3042 on reduced-set registers configuration. */
3043 if (TARGET_REDUCED_REGS
3044 && REG_P (op0)
3045 && REGNO (op0) == STATIC_CHAIN_REGNUM)
3046 sorry ("a nested function is not supported for reduced registers");
3047
3048 if (REG_P (op0))
3049 {
3050 /* "[Ra], 1/2/4" or "[Ra], -1/-2/-4"
3051 The 1/2/4 or -1/-2/-4 have been displayed in nds32.md.
3052 We only need to deal with register Ra. */
3053 fprintf (stream, "[%s]", reg_names[REGNO (op0)]);
3054 }
3055 else
3056 {
3057 /* The control flow is not supposed to be here. */
3058 debug_rtx (x);
3059 gcc_unreachable ();
3060 }
3061
3062 break;
3063
3064 default :
3065 /* Generally, output_addr_const () is able to handle most cases.
3066 We want to see what CODE could appear,
3067 so we use gcc_unreachable() to stop it. */
3068 debug_rtx (x);
3069 gcc_unreachable ();
3070 break;
3071 }
3072}
3073
3074\f
3075/* Defining target-specific uses of __attribute__. */
3076
3077/* Add some checking after merging attributes. */
3078static tree
3079nds32_merge_decl_attributes (tree olddecl, tree newdecl)
3080{
3081 tree combined_attrs;
3082
3083 /* Create combined attributes. */
3084 combined_attrs = merge_attributes (DECL_ATTRIBUTES (olddecl),
3085 DECL_ATTRIBUTES (newdecl));
3086
59043e75 3087 /* Since newdecl is acutally a duplicate of olddecl,
9304f876
CJW
3088 we can take olddecl for some operations. */
3089 if (TREE_CODE (olddecl) == FUNCTION_DECL)
3090 {
3091 /* Check isr-specific attributes conflict. */
3092 nds32_check_isr_attrs_conflict (olddecl, combined_attrs);
3093 }
3094
3095 return combined_attrs;
3096}
3097
3098/* Add some checking when inserting attributes. */
3099static void
3100nds32_insert_attributes (tree decl, tree *attributes)
3101{
3102 /* For function declaration, we need to check isr-specific attributes:
3103 1. Call nds32_check_isr_attrs_conflict() to check any conflict.
3104 2. Check valid integer value for interrupt/exception.
3105 3. Check valid integer value for reset.
3106 4. Check valid function for nmi/warm. */
3107 if (TREE_CODE (decl) == FUNCTION_DECL)
3108 {
3109 tree func_attrs;
3110 tree intr, excp, reset;
3111
3112 /* Pick up function attributes. */
3113 func_attrs = *attributes;
3114
3115 /* 1. Call nds32_check_isr_attrs_conflict() to check any conflict. */
3116 nds32_check_isr_attrs_conflict (decl, func_attrs);
3117
3118 /* Now we are starting to check valid id value
3119 for interrupt/exception/reset.
3120 Note that we ONLY check its validity here.
3121 To construct isr vector information, it is still performed
3122 by nds32_construct_isr_vectors_information(). */
3123 intr = lookup_attribute ("interrupt", func_attrs);
3124 excp = lookup_attribute ("exception", func_attrs);
3125 reset = lookup_attribute ("reset", func_attrs);
3126
3127 if (intr || excp)
3128 {
3129 /* Deal with interrupt/exception. */
3130 tree id_list;
3131 unsigned int lower_bound, upper_bound;
3132
3133 /* The way to handle interrupt or exception is the same,
3134 we just need to take care of actual vector number.
3135 For interrupt(0..63), the actual vector number is (9..72).
3136 For exception(1..8), the actual vector number is (1..8). */
3137 lower_bound = (intr) ? (0) : (1);
3138 upper_bound = (intr) ? (63) : (8);
3139
3140 /* Prepare id list so that we can traverse id value. */
3141 id_list = (intr) ? (TREE_VALUE (intr)) : (TREE_VALUE (excp));
3142
3143 /* 2. Check valid integer value for interrupt/exception. */
3144 while (id_list)
3145 {
3146 tree id;
3147
3148 /* Pick up each vector id value. */
3149 id = TREE_VALUE (id_list);
3150 /* Issue error if it is not a valid integer value. */
3151 if (TREE_CODE (id) != INTEGER_CST
3152 || TREE_INT_CST_LOW (id) < lower_bound
3153 || TREE_INT_CST_LOW (id) > upper_bound)
3154 error ("invalid id value for interrupt/exception attribute");
3155
3156 /* Advance to next id. */
3157 id_list = TREE_CHAIN (id_list);
3158 }
3159 }
3160 else if (reset)
3161 {
3162 /* Deal with reset. */
3163 tree id_list;
3164 tree id;
3165 tree nmi, warm;
3166 unsigned int lower_bound;
3167 unsigned int upper_bound;
3168
3169 /* Prepare id_list and identify id value so that
3170 we can check if total number of vectors is valid. */
3171 id_list = TREE_VALUE (reset);
3172 id = TREE_VALUE (id_list);
3173
3174 /* The maximum numbers for user's interrupt is 64. */
3175 lower_bound = 0;
3176 upper_bound = 64;
3177
3178 /* 3. Check valid integer value for reset. */
3179 if (TREE_CODE (id) != INTEGER_CST
3180 || TREE_INT_CST_LOW (id) < lower_bound
3181 || TREE_INT_CST_LOW (id) > upper_bound)
3182 error ("invalid id value for reset attribute");
3183
3184 /* 4. Check valid function for nmi/warm. */
3185 nmi = lookup_attribute ("nmi", func_attrs);
3186 warm = lookup_attribute ("warm", func_attrs);
3187
3188 if (nmi != NULL_TREE)
3189 {
3190 tree nmi_func_list;
3191 tree nmi_func;
3192
3193 nmi_func_list = TREE_VALUE (nmi);
3194 nmi_func = TREE_VALUE (nmi_func_list);
3195
3196 /* Issue error if it is not a valid nmi function. */
3197 if (TREE_CODE (nmi_func) != IDENTIFIER_NODE)
3198 error ("invalid nmi function for reset attribute");
3199 }
3200
3201 if (warm != NULL_TREE)
3202 {
3203 tree warm_func_list;
3204 tree warm_func;
3205
3206 warm_func_list = TREE_VALUE (warm);
3207 warm_func = TREE_VALUE (warm_func_list);
3208
3209 /* Issue error if it is not a valid warm function. */
3210 if (TREE_CODE (warm_func) != IDENTIFIER_NODE)
3211 error ("invalid warm function for reset attribute");
3212 }
3213 }
3214 else
3215 {
3216 /* No interrupt, exception, or reset attribute is set. */
3217 return;
3218 }
3219 }
3220}
3221
3222static bool
3223nds32_option_pragma_parse (tree args ATTRIBUTE_UNUSED,
3224 tree pop_target ATTRIBUTE_UNUSED)
3225{
3226 /* Currently, we do not parse any pragma target by ourself,
3227 so just simply return false. */
3228 return false;
3229}
3230
3231static void
3232nds32_option_override (void)
3233{
3234 /* After all the command options have been parsed,
3235 we shall deal with some flags for changing compiler settings. */
3236
3237 /* At first, we check if we have to strictly
3238 set some flags based on ISA family. */
3239 if (TARGET_ISA_V2)
3240 {
3241 /* Under V2 ISA, we need to strictly disable TARGET_V3PUSH. */
3242 target_flags &= ~MASK_V3PUSH;
3243 }
3244 if (TARGET_ISA_V3)
3245 {
3246 /* Under V3 ISA, currently nothing should be strictly set. */
3247 }
3248 if (TARGET_ISA_V3M)
3249 {
3250 /* Under V3M ISA, we need to strictly enable TARGET_REDUCED_REGS. */
3251 target_flags |= MASK_REDUCED_REGS;
3252 /* Under V3M ISA, we need to strictly disable TARGET_PERF_EXT. */
3253 target_flags &= ~MASK_PERF_EXT;
3254 }
3255
3256 /* See if we are using reduced-set registers:
3257 $r0~$r5, $r6~$r10, $r15, $r28, $r29, $r30, $r31
3258 If so, we must forbid using $r11~$r14, $r16~$r27. */
3259 if (TARGET_REDUCED_REGS)
3260 {
3261 int r;
3262
3263 /* Prevent register allocator from
3264 choosing it as doing register allocation. */
3265 for (r = 11; r <= 14; r++)
3266 fixed_regs[r] = call_used_regs[r] = 1;
3267 for (r = 16; r <= 27; r++)
3268 fixed_regs[r] = call_used_regs[r] = 1;
3269 }
3270
3271 /* See if user explicitly would like to use fp-as-gp optimization.
3272 If so, we must prevent $fp from being allocated
3273 during register allocation. */
3274 if (TARGET_FORCE_FP_AS_GP)
3275 fixed_regs[FP_REGNUM] = call_used_regs[FP_REGNUM] = 1;
3276
3277 if (!TARGET_16_BIT)
3278 {
3279 /* Under no 16 bit ISA, we need to strictly disable TARGET_V3PUSH. */
3280 target_flags &= ~MASK_V3PUSH;
3281 }
3282
3283 /* Currently, we don't support PIC code generation yet. */
3284 if (flag_pic)
3285 sorry ("not support -fpic");
3286}
3287
3288\f
3289/* Miscellaneous Parameters. */
3290
3291static void
3292nds32_init_builtins (void)
3293{
3294 tree pointer_type_node = build_pointer_type (integer_type_node);
3295
3296 tree void_ftype_void = build_function_type (void_type_node,
3297 void_list_node);
3298
3299 tree void_ftype_pint = build_function_type_list (void_type_node,
3300 pointer_type_node,
3301 NULL_TREE);
3302
3303 tree int_ftype_int = build_function_type_list (integer_type_node,
3304 integer_type_node,
3305 NULL_TREE);
3306
3307 tree void_ftype_int_int = build_function_type_list (void_type_node,
3308 integer_type_node,
3309 integer_type_node,
3310 NULL_TREE);
3311
3312 /* Cache. */
3313 add_builtin_function ("__builtin_nds32_isync", void_ftype_pint,
3314 NDS32_BUILTIN_ISYNC,
3315 BUILT_IN_MD, NULL, NULL_TREE);
3316 add_builtin_function ("__builtin_nds32_isb", void_ftype_void,
3317 NDS32_BUILTIN_ISB,
3318 BUILT_IN_MD, NULL, NULL_TREE);
3319
3320 /* Register Transfer. */
3321 add_builtin_function ("__builtin_nds32_mfsr", int_ftype_int,
3322 NDS32_BUILTIN_MFSR,
3323 BUILT_IN_MD, NULL, NULL_TREE);
3324 add_builtin_function ("__builtin_nds32_mfusr", int_ftype_int,
3325 NDS32_BUILTIN_MFUSR,
3326 BUILT_IN_MD, NULL, NULL_TREE);
3327 add_builtin_function ("__builtin_nds32_mtsr", void_ftype_int_int,
3328 NDS32_BUILTIN_MTSR,
3329 BUILT_IN_MD, NULL, NULL_TREE);
3330 add_builtin_function ("__builtin_nds32_mtusr", void_ftype_int_int,
3331 NDS32_BUILTIN_MTUSR,
3332 BUILT_IN_MD, NULL, NULL_TREE);
3333
3334 /* Interrupt. */
3335 add_builtin_function ("__builtin_nds32_setgie_en", void_ftype_void,
3336 NDS32_BUILTIN_SETGIE_EN,
3337 BUILT_IN_MD, NULL, NULL_TREE);
3338 add_builtin_function ("__builtin_nds32_setgie_dis", void_ftype_void,
3339 NDS32_BUILTIN_SETGIE_DIS,
3340 BUILT_IN_MD, NULL, NULL_TREE);
3341}
3342
3343static rtx
3344nds32_expand_builtin (tree exp,
3345 rtx target,
3346 rtx subtarget ATTRIBUTE_UNUSED,
3347 enum machine_mode mode ATTRIBUTE_UNUSED,
3348 int ignore ATTRIBUTE_UNUSED)
3349{
3350 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
3351
3352 int fcode = DECL_FUNCTION_CODE (fndecl);
3353
3354 switch (fcode)
3355 {
3356 /* Cache. */
3357 case NDS32_BUILTIN_ISYNC:
3358 return nds32_expand_builtin_null_ftype_reg
3359 (CODE_FOR_unspec_volatile_isync, exp, target);
3360 case NDS32_BUILTIN_ISB:
3361 /* Since there are no result and operands for isb instruciton,
3362 we can simply emit this rtx. */
3363 emit_insn (gen_unspec_volatile_isb ());
3364 return target;
3365
3366 /* Register Transfer. */
3367 case NDS32_BUILTIN_MFSR:
3368 return nds32_expand_builtin_reg_ftype_imm
3369 (CODE_FOR_unspec_volatile_mfsr, exp, target);
3370 case NDS32_BUILTIN_MFUSR:
3371 return nds32_expand_builtin_reg_ftype_imm
3372 (CODE_FOR_unspec_volatile_mfusr, exp, target);
3373 case NDS32_BUILTIN_MTSR:
3374 return nds32_expand_builtin_null_ftype_reg_imm
3375 (CODE_FOR_unspec_volatile_mtsr, exp, target);
3376 case NDS32_BUILTIN_MTUSR:
3377 return nds32_expand_builtin_null_ftype_reg_imm
3378 (CODE_FOR_unspec_volatile_mtusr, exp, target);
3379
3380 /* Interrupt. */
3381 case NDS32_BUILTIN_SETGIE_EN:
3382 /* Since there are no result and operands for setgie.e instruciton,
3383 we can simply emit this rtx. */
3384 emit_insn (gen_unspec_volatile_setgie_en ());
3385 return target;
3386 case NDS32_BUILTIN_SETGIE_DIS:
3387 /* Since there are no result and operands for setgie.d instruciton,
3388 we can simply emit this rtx. */
3389 emit_insn (gen_unspec_volatile_setgie_dis ());
3390 return target;
3391
3392 default:
3393 gcc_unreachable ();
3394 }
3395
3396 return NULL_RTX;
3397}
3398
3399
3400/* ------------------------------------------------------------------------ */
3401
3402/* PART 4: Implemet extern function definitions,
3403 the prototype is in nds32-protos.h. */
3404\f
3405/* Defining Data Structures for Per-function Information. */
3406
3407void
3408nds32_init_expanders (void)
3409{
3410 /* Arrange to initialize and mark the machine per-function status. */
3411 init_machine_status = nds32_init_machine_status;
3412}
3413
3414\f
3415/* Register Usage. */
3416
3417/* -- How Values Fit in Registers. */
3418
3419int
3420nds32_hard_regno_nregs (int regno ATTRIBUTE_UNUSED,
3421 enum machine_mode mode)
3422{
3423 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
3424}
3425
3426int
3427nds32_hard_regno_mode_ok (int regno, enum machine_mode mode)
3428{
3429 /* Restrict double-word quantities to even register pairs. */
3430 if (HARD_REGNO_NREGS (regno, mode) == 1
3431 || !((regno) & 1))
3432 return 1;
3433
3434 return 0;
3435}
3436
3437\f
3438/* Register Classes. */
3439
3440enum reg_class
3441nds32_regno_reg_class (int regno)
3442{
3443 /* Refer to nds32.h for more register class details. */
3444
3445 if (regno >= 0 && regno <= 7)
3446 return LOW_REGS;
3447 else if (regno >= 8 && regno <= 11)
3448 return MIDDLE_REGS;
3449 else if (regno >= 12 && regno <= 14)
3450 return HIGH_REGS;
3451 else if (regno == 15)
3452 return R15_TA_REG;
3453 else if (regno >= 16 && regno <= 19)
3454 return MIDDLE_REGS;
3455 else if (regno >= 20 && regno <= 31)
3456 return HIGH_REGS;
3457 else if (regno == 32 || regno == 33)
3458 return FRAME_REGS;
3459 else
3460 return NO_REGS;
3461}
3462
3463\f
3464/* Stack Layout and Calling Conventions. */
3465
3466/* -- Basic Stack Layout. */
3467
3468rtx
3469nds32_return_addr_rtx (int count,
3470 rtx frameaddr ATTRIBUTE_UNUSED)
3471{
3472 /* There is no way to determine the return address
3473 if frameaddr is the frame that has 'count' steps
3474 up from current frame. */
3475 if (count != 0)
3476 return NULL_RTX;
3477
3478 /* If count == 0, it means we are at current frame,
3479 the return address is $r30 ($lp). */
3480 return get_hard_reg_initial_val (Pmode, LP_REGNUM);
3481}
3482
3483/* -- Eliminating Frame Pointer and Arg Pointer. */
3484
3485HOST_WIDE_INT
3486nds32_initial_elimination_offset (unsigned int from_reg, unsigned int to_reg)
3487{
3488 HOST_WIDE_INT offset;
3489
3490 /* Compute and setup stack frame size.
3491 The result will be in cfun->machine. */
3492 nds32_compute_stack_frame ();
3493
3494 /* Remember to consider
3495 cfun->machine->callee_saved_area_padding_bytes
3496 when calculating offset. */
3497 if (from_reg == ARG_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM)
3498 {
3499 offset = (cfun->machine->fp_size
3500 + cfun->machine->gp_size
3501 + cfun->machine->lp_size
3502 + cfun->machine->callee_saved_regs_size
3503 + cfun->machine->callee_saved_area_padding_bytes
3504 + cfun->machine->local_size
3505 + cfun->machine->out_args_size);
3506 }
3507 else if (from_reg == ARG_POINTER_REGNUM
3508 && to_reg == HARD_FRAME_POINTER_REGNUM)
3509 {
3510 offset = 0;
3511 }
3512 else if (from_reg == FRAME_POINTER_REGNUM
3513 && to_reg == STACK_POINTER_REGNUM)
3514 {
3515 offset = (cfun->machine->local_size + cfun->machine->out_args_size);
3516 }
3517 else if (from_reg == FRAME_POINTER_REGNUM
3518 && to_reg == HARD_FRAME_POINTER_REGNUM)
3519 {
3520 offset = (-1) * (cfun->machine->fp_size
3521 + cfun->machine->gp_size
3522 + cfun->machine->lp_size
3523 + cfun->machine->callee_saved_regs_size
3524 + cfun->machine->callee_saved_area_padding_bytes);
3525 }
3526 else
3527 {
3528 gcc_unreachable ();
3529 }
3530
3531 return offset;
3532}
3533
3534/* -- Passing Arguments in Registers. */
3535
3536void
3537nds32_init_cumulative_args (CUMULATIVE_ARGS *cum,
3538 tree fntype ATTRIBUTE_UNUSED,
3539 rtx libname ATTRIBUTE_UNUSED,
3540 tree fndecl ATTRIBUTE_UNUSED,
3541 int n_named_args ATTRIBUTE_UNUSED)
3542{
3543 /* Initial available registers
3544 (in offset, corresponding to NDS32_GPR_ARG_FIRST_REGNUM)
3545 for passing arguments. */
3546 cum->reg_offset = 0;
3547}
3548
3549/* -- Function Entry and Exit. */
3550
3551/* Function for normal multiple push prologue. */
3552void
3553nds32_expand_prologue (void)
3554{
3555 int fp_adjust;
3556 int sp_adjust;
3557 int en4_const;
3558
3559 rtx Rb, Re;
3560 rtx push_insn;
3561 rtx fp_adjust_insn, sp_adjust_insn;
3562
3563 /* Before computing everything for stack frame size,
3564 we check if it is still worth to use fp_as_gp optimization.
3565 If it is, the 'df_regs_ever_live_p (FP_REGNUM)' will be set
3566 so that $fp will be saved on stack. */
3567 cfun->machine->fp_as_gp_p = nds32_fp_as_gp_check_available ();
3568
3569 /* Compute and setup stack frame size.
3570 The result will be in cfun->machine. */
3571 nds32_compute_stack_frame ();
3572
3573 /* If the function is 'naked',
3574 we do not have to generate prologue code fragment. */
3575 if (cfun->machine->naked_p)
3576 return;
3577
3578 /* Get callee_first_regno and callee_last_regno. */
3579 Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno);
3580 Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno);
3581
3582 /* push_insn = gen_stack_push_multiple(first_regno, last_regno),
3583 the pattern 'stack_push_multiple' is implemented in nds32.md.
3584 For En4 field, we have to calculate its constant value.
3585 Refer to Andes ISA for more information. */
3586 en4_const = 0;
3587 if (cfun->machine->fp_size)
3588 en4_const += 8;
3589 if (cfun->machine->gp_size)
3590 en4_const += 4;
3591 if (cfun->machine->lp_size)
3592 en4_const += 2;
3593
3594 /* If $fp, $gp, $lp, and all callee-save registers are NOT required
3595 to be saved, we don't have to create multiple push instruction.
3596 Otherwise, a multiple push instruction is needed. */
3597 if (!(REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM && en4_const == 0))
3598 {
3599 /* Create multiple push instruction rtx. */
3600 push_insn = nds32_gen_stack_push_multiple (Rb, Re, GEN_INT (en4_const));
3601 /* Emit rtx into instructions list and receive INSN rtx form. */
3602 push_insn = emit_insn (push_insn);
3603
3604 /* The insn rtx 'push_insn' will change frame layout.
3605 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3606 generate CFI (Call Frame Information) stuff. */
3607 RTX_FRAME_RELATED_P (push_insn) = 1;
3608 }
3609
3610 /* Check frame_pointer_needed to see
3611 if we shall emit fp adjustment instruction. */
3612 if (frame_pointer_needed)
3613 {
3614 /* adjust $fp = $sp + ($fp size) + ($gp size) + ($lp size)
3615 + (4 * callee-saved-registers)
3616 Note: No need to adjust
3617 cfun->machine->callee_saved_area_padding_bytes,
3618 because, at this point, stack pointer is just
3619 at the position after push instruction. */
3620 fp_adjust = cfun->machine->fp_size
3621 + cfun->machine->gp_size
3622 + cfun->machine->lp_size
3623 + cfun->machine->callee_saved_regs_size;
3624 fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx,
3625 stack_pointer_rtx,
3626 GEN_INT (fp_adjust));
3627 /* Emit rtx into instructions list and receive INSN rtx form. */
3628 fp_adjust_insn = emit_insn (fp_adjust_insn);
3629 }
3630
3631 /* Adjust $sp = $sp - local_size - out_args_size
3632 - callee_saved_area_padding_bytes. */
3633 sp_adjust = cfun->machine->local_size
3634 + cfun->machine->out_args_size
3635 + cfun->machine->callee_saved_area_padding_bytes;
3636 /* sp_adjust value may be out of range of the addi instruction,
3637 create alternative add behavior with TA_REGNUM if necessary,
3638 using NEGATIVE value to tell that we are decreasing address. */
3639 sp_adjust = nds32_force_addi_stack_int ( (-1) * sp_adjust);
3640 if (sp_adjust)
3641 {
3642 /* Generate sp adjustment instruction if and only if sp_adjust != 0. */
3643 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
3644 stack_pointer_rtx,
3645 GEN_INT (-1 * sp_adjust));
3646 /* Emit rtx into instructions list and receive INSN rtx form. */
3647 sp_adjust_insn = emit_insn (sp_adjust_insn);
3648
3649 /* The insn rtx 'sp_adjust_insn' will change frame layout.
3650 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3651 generate CFI (Call Frame Information) stuff. */
3652 RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
3653 }
3654
3655 /* Prevent the instruction scheduler from
3656 moving instructions across the boundary. */
3657 emit_insn (gen_blockage ());
3658}
3659
3660/* Function for normal multiple pop epilogue. */
3661void
3662nds32_expand_epilogue (void)
3663{
3664 int sp_adjust;
3665 int en4_const;
3666
3667 rtx Rb, Re;
3668 rtx pop_insn;
3669 rtx sp_adjust_insn;
3670
3671 /* Compute and setup stack frame size.
3672 The result will be in cfun->machine. */
3673 nds32_compute_stack_frame ();
3674
3675 /* Prevent the instruction scheduler from
3676 moving instructions across the boundary. */
3677 emit_insn (gen_blockage ());
3678
3679 /* If the function is 'naked', we do not have to generate
3680 epilogue code fragment BUT 'ret' instruction. */
3681 if (cfun->machine->naked_p)
3682 {
3683 /* Generate return instruction by using
3684 unspec_volatile_func_return pattern.
3685 Make sure this instruction is after gen_blockage().
3686 NOTE that $lp will become 'live'
3687 after this instruction has been emitted. */
3688 emit_insn (gen_unspec_volatile_func_return ());
3689 return;
3690 }
3691
3692 if (frame_pointer_needed)
3693 {
3694 /* adjust $sp = $fp - ($fp size) - ($gp size) - ($lp size)
3695 - (4 * callee-saved-registers)
3696 Note: No need to adjust
3697 cfun->machine->callee_saved_area_padding_bytes,
3698 because we want to adjust stack pointer
3699 to the position for pop instruction. */
3700 sp_adjust = cfun->machine->fp_size
3701 + cfun->machine->gp_size
3702 + cfun->machine->lp_size
3703 + cfun->machine->callee_saved_regs_size;
3704 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
3705 hard_frame_pointer_rtx,
3706 GEN_INT (-1 * sp_adjust));
3707 /* Emit rtx into instructions list and receive INSN rtx form. */
3708 sp_adjust_insn = emit_insn (sp_adjust_insn);
3709 }
3710 else
3711 {
3712 /* If frame pointer is NOT needed,
3713 we cannot calculate the sp adjustment from frame pointer.
3714 Instead, we calculate the adjustment by local_size,
3715 out_args_size, and callee_saved_area_padding_bytes.
3716 Notice that such sp adjustment value may be out of range,
3717 so we have to deal with it as well. */
3718
3719 /* Adjust $sp = $sp + local_size + out_args_size
3720 + callee_saved_area_padding_bytes. */
3721 sp_adjust = cfun->machine->local_size
3722 + cfun->machine->out_args_size
3723 + cfun->machine->callee_saved_area_padding_bytes;
3724 /* sp_adjust value may be out of range of the addi instruction,
3725 create alternative add behavior with TA_REGNUM if necessary,
3726 using POSITIVE value to tell that we are increasing address. */
3727 sp_adjust = nds32_force_addi_stack_int (sp_adjust);
3728 if (sp_adjust)
3729 {
3730 /* Generate sp adjustment instruction
3731 if and only if sp_adjust != 0. */
3732 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
3733 stack_pointer_rtx,
3734 GEN_INT (sp_adjust));
3735 /* Emit rtx into instructions list and receive INSN rtx form. */
3736 sp_adjust_insn = emit_insn (sp_adjust_insn);
3737 }
3738 }
3739
3740 /* Get callee_first_regno and callee_last_regno. */
3741 Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno);
3742 Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno);
3743
3744 /* pop_insn = gen_stack_pop_multiple(first_regno, last_regno),
3745 the pattern 'stack_pop_multiple' is implementad in nds32.md.
3746 For En4 field, we have to calculate its constant value.
3747 Refer to Andes ISA for more information. */
3748 en4_const = 0;
3749 if (cfun->machine->fp_size)
3750 en4_const += 8;
3751 if (cfun->machine->gp_size)
3752 en4_const += 4;
3753 if (cfun->machine->lp_size)
3754 en4_const += 2;
3755
3756 /* If $fp, $gp, $lp, and all callee-save registers are NOT required
3757 to be saved, we don't have to create multiple pop instruction.
3758 Otherwise, a multiple pop instruction is needed. */
3759 if (!(REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM && en4_const == 0))
3760 {
3761 /* Create multiple pop instruction rtx. */
3762 pop_insn = nds32_gen_stack_pop_multiple (Rb, Re, GEN_INT (en4_const));
3763 /* Emit pop instruction. */
3764 emit_insn (pop_insn);
3765 }
3766
3767 /* Generate return instruction by using
3768 unspec_volatile_func_return pattern. */
3769 emit_insn (gen_unspec_volatile_func_return ());
3770}
3771
3772/* Function for v3push prologue. */
3773void
3774nds32_expand_prologue_v3push (void)
3775{
3776 int fp_adjust;
3777 int sp_adjust;
3778
3779 rtx Rb, Re;
3780 rtx push_insn;
3781 rtx fp_adjust_insn, sp_adjust_insn;
3782
3783 /* Before computing everything for stack frame size,
3784 we check if it is still worth to use fp_as_gp optimization.
3785 If it is, the 'df_regs_ever_live_p (FP_REGNUM)' will be set
3786 so that $fp will be saved on stack. */
3787 cfun->machine->fp_as_gp_p = nds32_fp_as_gp_check_available ();
3788
3789 /* Compute and setup stack frame size.
3790 The result will be in cfun->machine. */
3791 nds32_compute_stack_frame ();
3792
3793 /* If the function is 'naked',
3794 we do not have to generate prologue code fragment. */
3795 if (cfun->machine->naked_p)
3796 return;
3797
3798 /* Get callee_first_regno and callee_last_regno. */
3799 Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno);
3800 Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno);
3801
3802 /* Calculate sp_adjust first to test if 'push25 Re,imm8u' is available,
3803 where imm8u has to be 8-byte alignment. */
3804 sp_adjust = cfun->machine->local_size
3805 + cfun->machine->out_args_size
3806 + cfun->machine->callee_saved_area_padding_bytes;
3807
3808 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
3809 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust))
3810 {
3811 /* We can use 'push25 Re,imm8u'. */
3812
3813 /* push_insn = gen_stack_v3push(last_regno, sp_adjust),
3814 the pattern 'stack_v3push' is implemented in nds32.md.
3815 The (const_int 14) means v3push always push { $fp $gp $lp }. */
3816 push_insn = nds32_gen_stack_v3push (Rb, Re,
3817 GEN_INT (14), GEN_INT (sp_adjust));
3818 /* emit rtx into instructions list and receive INSN rtx form */
3819 push_insn = emit_insn (push_insn);
3820
3821 /* The insn rtx 'push_insn' will change frame layout.
3822 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3823 generate CFI (Call Frame Information) stuff. */
3824 RTX_FRAME_RELATED_P (push_insn) = 1;
3825
3826 /* Check frame_pointer_needed to see
3827 if we shall emit fp adjustment instruction. */
3828 if (frame_pointer_needed)
3829 {
3830 /* adjust $fp = $sp + 4 ($fp size)
3831 + 4 ($gp size)
3832 + 4 ($lp size)
3833 + (4 * n) (callee-saved registers)
3834 + sp_adjust ('push25 Re,imm8u')
3835 Note: Since we use 'push25 Re,imm8u',
3836 the position of stack pointer is further
3837 changed after push instruction.
3838 Hence, we need to take sp_adjust value
3839 into consideration. */
3840 fp_adjust = cfun->machine->fp_size
3841 + cfun->machine->gp_size
3842 + cfun->machine->lp_size
3843 + cfun->machine->callee_saved_regs_size
3844 + sp_adjust;
3845 fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx,
3846 stack_pointer_rtx,
3847 GEN_INT (fp_adjust));
3848 /* Emit rtx into instructions list and receive INSN rtx form. */
3849 fp_adjust_insn = emit_insn (fp_adjust_insn);
3850 }
3851 }
3852 else
3853 {
3854 /* We have to use 'push25 Re,0' and
3855 expand one more instruction to adjust $sp later. */
3856
3857 /* push_insn = gen_stack_v3push(last_regno, sp_adjust),
3858 the pattern 'stack_v3push' is implemented in nds32.md.
3859 The (const_int 14) means v3push always push { $fp $gp $lp }. */
3860 push_insn = nds32_gen_stack_v3push (Rb, Re,
3861 GEN_INT (14), GEN_INT (0));
3862 /* Emit rtx into instructions list and receive INSN rtx form. */
3863 push_insn = emit_insn (push_insn);
3864
3865 /* The insn rtx 'push_insn' will change frame layout.
3866 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3867 generate CFI (Call Frame Information) stuff. */
3868 RTX_FRAME_RELATED_P (push_insn) = 1;
3869
3870 /* Check frame_pointer_needed to see
3871 if we shall emit fp adjustment instruction. */
3872 if (frame_pointer_needed)
3873 {
3874 /* adjust $fp = $sp + 4 ($fp size)
3875 + 4 ($gp size)
3876 + 4 ($lp size)
3877 + (4 * n) (callee-saved registers)
3878 Note: Since we use 'push25 Re,0',
3879 the stack pointer is just at the position
3880 after push instruction.
3881 No need to take sp_adjust into consideration. */
3882 fp_adjust = cfun->machine->fp_size
3883 + cfun->machine->gp_size
3884 + cfun->machine->lp_size
3885 + cfun->machine->callee_saved_regs_size;
3886 fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx,
3887 stack_pointer_rtx,
3888 GEN_INT (fp_adjust));
3889 /* Emit rtx into instructions list and receive INSN rtx form. */
3890 fp_adjust_insn = emit_insn (fp_adjust_insn);
3891 }
3892
3893 /* Because we use 'push25 Re,0',
3894 we need to expand one more instruction to adjust $sp.
3895 However, sp_adjust value may be out of range of the addi instruction,
3896 create alternative add behavior with TA_REGNUM if necessary,
3897 using NEGATIVE value to tell that we are decreasing address. */
3898 sp_adjust = nds32_force_addi_stack_int ( (-1) * sp_adjust);
3899 if (sp_adjust)
3900 {
3901 /* Generate sp adjustment instruction
3902 if and only if sp_adjust != 0. */
3903 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
3904 stack_pointer_rtx,
3905 GEN_INT (-1 * sp_adjust));
3906 /* Emit rtx into instructions list and receive INSN rtx form. */
3907 sp_adjust_insn = emit_insn (sp_adjust_insn);
3908
3909 /* The insn rtx 'sp_adjust_insn' will change frame layout.
3910 We need to use RTX_FRAME_RELATED_P so that GCC is able to
3911 generate CFI (Call Frame Information) stuff. */
3912 RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
3913 }
3914 }
3915
3916 /* Prevent the instruction scheduler from
3917 moving instructions across the boundary. */
3918 emit_insn (gen_blockage ());
3919}
3920
3921/* Function for v3pop epilogue. */
3922void
3923nds32_expand_epilogue_v3pop (void)
3924{
3925 int sp_adjust;
3926
3927 rtx Rb, Re;
3928 rtx pop_insn;
3929 rtx sp_adjust_insn;
3930
3931 /* Compute and setup stack frame size.
3932 The result will be in cfun->machine. */
3933 nds32_compute_stack_frame ();
3934
3935 /* Prevent the instruction scheduler from
3936 moving instructions across the boundary. */
3937 emit_insn (gen_blockage ());
3938
3939 /* If the function is 'naked', we do not have to generate
3940 epilogue code fragment BUT 'ret' instruction. */
3941 if (cfun->machine->naked_p)
3942 {
3943 /* Generate return instruction by using
3944 unspec_volatile_func_return pattern.
3945 Make sure this instruction is after gen_blockage().
3946 NOTE that $lp will become 'live'
3947 after this instruction has been emitted. */
3948 emit_insn (gen_unspec_volatile_func_return ());
3949 return;
3950 }
3951
3952 /* Get callee_first_regno and callee_last_regno. */
3953 Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno);
3954 Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno);
3955
3956 /* Calculate sp_adjust first to test if 'pop25 Re,imm8u' is available,
3957 where imm8u has to be 8-byte alignment. */
3958 sp_adjust = cfun->machine->local_size
3959 + cfun->machine->out_args_size
3960 + cfun->machine->callee_saved_area_padding_bytes;
3961
3962 /* We have to consider alloca issue as well.
3963 If the function does call alloca(), the stack pointer is not fixed.
3964 In that case, we cannot use 'pop25 Re,imm8u' directly.
3965 We have to caculate stack pointer from frame pointer
3966 and then use 'pop25 Re,0'.
3967 Of course, the frame_pointer_needed should be nonzero
3968 if the function calls alloca(). */
3969 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
3970 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)
3971 && !cfun->calls_alloca)
3972 {
3973 /* We can use 'pop25 Re,imm8u'. */
3974
3975 /* pop_insn = gen_stack_v3pop(last_regno, sp_adjust),
3976 the pattern 'stack_v3pop' is implementad in nds32.md.
3977 The (const_int 14) means v3pop always pop { $fp $gp $lp }. */
3978 pop_insn = nds32_gen_stack_v3pop (Rb, Re,
3979 GEN_INT (14), GEN_INT (sp_adjust));
3980
3981 /* Emit pop instruction. */
3982 emit_insn (pop_insn);
3983 }
3984 else
3985 {
3986 /* We have to use 'pop25 Re,0', and prior to it,
3987 we must expand one more instruction to adjust $sp. */
3988
3989 if (frame_pointer_needed)
3990 {
3991 /* adjust $sp = $fp - 4 ($fp size)
3992 - 4 ($gp size)
3993 - 4 ($lp size)
3994 - (4 * n) (callee-saved registers)
3995 Note: No need to adjust
3996 cfun->machine->callee_saved_area_padding_bytes,
3997 because we want to adjust stack pointer
3998 to the position for pop instruction. */
3999 sp_adjust = cfun->machine->fp_size
4000 + cfun->machine->gp_size
4001 + cfun->machine->lp_size
4002 + cfun->machine->callee_saved_regs_size;
4003 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
4004 hard_frame_pointer_rtx,
4005 GEN_INT (-1 * sp_adjust));
4006 /* Emit rtx into instructions list and receive INSN rtx form. */
4007 sp_adjust_insn = emit_insn (sp_adjust_insn);
4008 }
4009 else
4010 {
4011 /* If frame pointer is NOT needed,
4012 we cannot calculate the sp adjustment from frame pointer.
4013 Instead, we calculate the adjustment by local_size,
4014 out_args_size, and callee_saved_area_padding_bytes.
4015 Notice that such sp adjustment value may be out of range,
4016 so we have to deal with it as well. */
4017
4018 /* Adjust $sp = $sp + local_size + out_args_size
4019 + callee_saved_area_padding_bytes. */
4020 sp_adjust = cfun->machine->local_size
4021 + cfun->machine->out_args_size
4022 + cfun->machine->callee_saved_area_padding_bytes;
4023 /* sp_adjust value may be out of range of the addi instruction,
4024 create alternative add behavior with TA_REGNUM if necessary,
4025 using POSITIVE value to tell that we are increasing address. */
4026 sp_adjust = nds32_force_addi_stack_int (sp_adjust);
4027 if (sp_adjust)
4028 {
4029 /* Generate sp adjustment instruction
4030 if and only if sp_adjust != 0. */
4031 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
4032 stack_pointer_rtx,
4033 GEN_INT (sp_adjust));
4034 /* Emit rtx into instructions list and receive INSN rtx form. */
4035 sp_adjust_insn = emit_insn (sp_adjust_insn);
4036 }
4037 }
4038
4039 /* pop_insn = gen_stack_v3pop(last_regno, sp_adjust),
4040 the pattern 'stack_v3pop' is implementad in nds32.md. */
4041 /* The (const_int 14) means v3pop always pop { $fp $gp $lp }. */
4042 pop_insn = nds32_gen_stack_v3pop (Rb, Re,
4043 GEN_INT (14), GEN_INT (0));
4044
4045 /* Emit pop instruction. */
4046 emit_insn (pop_insn);
4047 }
4048}
4049
4050/* ------------------------------------------------------------------------ */
4051
4052/* Function to test 333-form for load/store instructions.
4053 This is auxiliary extern function for auxiliary macro in nds32.h.
4054 Because it is a little complicated, we use function instead of macro. */
4055bool
4056nds32_ls_333_p (rtx rt, rtx ra, rtx imm, enum machine_mode mode)
4057{
4058 if (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS
4059 && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS)
4060 {
4061 if (GET_MODE_SIZE (mode) == 4)
4062 return satisfies_constraint_Iu05 (imm);
4063
4064 if (GET_MODE_SIZE (mode) == 2)
4065 return satisfies_constraint_Iu04 (imm);
4066
4067 if (GET_MODE_SIZE (mode) == 1)
4068 return satisfies_constraint_Iu03 (imm);
4069 }
4070
4071 return false;
4072}
4073
4074
4075/* Functions to expand load_multiple and store_multiple.
4076 They are auxiliary extern functions to help create rtx template.
4077 Check nds32-multiple.md file for the patterns. */
4078rtx
4079nds32_expand_load_multiple (int base_regno, int count,
4080 rtx base_addr, rtx basemem)
4081{
4082 int par_index;
4083 int offset;
4084 rtx result;
4085 rtx new_addr, mem, reg;
4086
4087 /* Create the pattern that is presented in nds32-multiple.md. */
4088
4089 result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
4090
4091 for (par_index = 0; par_index < count; par_index++)
4092 {
4093 offset = par_index * 4;
4094 /* 4-byte for loading data to each register. */
4095 new_addr = plus_constant (Pmode, base_addr, offset);
4096 mem = adjust_automodify_address_nv (basemem, SImode,
4097 new_addr, offset);
4098 reg = gen_rtx_REG (SImode, base_regno + par_index);
4099
4100 XVECEXP (result, 0, par_index) = gen_rtx_SET (VOIDmode, reg, mem);
4101 }
4102
4103 return result;
4104}
4105
4106rtx
4107nds32_expand_store_multiple (int base_regno, int count,
4108 rtx base_addr, rtx basemem)
4109{
4110 int par_index;
4111 int offset;
4112 rtx result;
4113 rtx new_addr, mem, reg;
4114
4115 /* Create the pattern that is presented in nds32-multiple.md. */
4116
4117 result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
4118
4119 for (par_index = 0; par_index < count; par_index++)
4120 {
4121 offset = par_index * 4;
4122 /* 4-byte for storing data to memory. */
4123 new_addr = plus_constant (Pmode, base_addr, offset);
4124 mem = adjust_automodify_address_nv (basemem, SImode,
4125 new_addr, offset);
4126 reg = gen_rtx_REG (SImode, base_regno + par_index);
4127
4128 XVECEXP (result, 0, par_index) = gen_rtx_SET (VOIDmode, mem, reg);
4129 }
4130
4131 return result;
4132}
4133
4134/* Function to move block memory content by
4135 using load_multiple and store_multiple.
4136 This is auxiliary extern function to help create rtx template.
4137 Check nds32-multiple.md file for the patterns. */
4138int
4139nds32_expand_movmemqi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment)
4140{
4141 HOST_WIDE_INT in_words, out_words;
4142 rtx dst_base_reg, src_base_reg;
4143 int maximum_bytes;
4144
4145 /* Because reduced-set regsiters has few registers
4146 (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31'
4147 cannot be used for register allocation),
4148 using 8 registers (32 bytes) for moving memory block
4149 may easily consume all of them.
4150 It makes register allocation/spilling hard to work.
4151 So we only allow maximum=4 registers (16 bytes) for
4152 moving memory block under reduced-set registers. */
4153 if (TARGET_REDUCED_REGS)
4154 maximum_bytes = 16;
4155 else
4156 maximum_bytes = 32;
4157
4158 /* 1. Total_bytes is integer for sure.
4159 2. Alignment is integer for sure.
4160 3. Maximum 4 or 8 registers, 4 * 4 = 16 bytes, 8 * 4 = 32 bytes.
4161 4. Requires (n * 4) block size.
4162 5. Requires 4-byte alignment. */
4163 if (GET_CODE (total_bytes) != CONST_INT
4164 || GET_CODE (alignment) != CONST_INT
4165 || INTVAL (total_bytes) > maximum_bytes
4166 || INTVAL (total_bytes) & 3
4167 || INTVAL (alignment) & 3)
4168 return 0;
4169
4170 dst_base_reg = copy_to_mode_reg (SImode, XEXP (dstmem, 0));
4171 src_base_reg = copy_to_mode_reg (SImode, XEXP (srcmem, 0));
4172
4173 out_words = in_words = INTVAL (total_bytes) / UNITS_PER_WORD;
4174
4175 emit_insn (nds32_expand_load_multiple (0, in_words, src_base_reg, srcmem));
4176 emit_insn (nds32_expand_store_multiple (0, out_words, dst_base_reg, dstmem));
4177
4178 /* Successfully create patterns, return 1. */
4179 return 1;
4180}
4181
4182/* Function to check whether the OP is a valid load/store operation.
4183 This is a helper function for the predicates:
4184 'nds32_load_multiple_operation' and 'nds32_store_multiple_operation'
4185 in predicates.md file.
4186
4187 The OP is supposed to be a parallel rtx.
4188 For each element within this parallel rtx:
4189 (set (reg) (mem addr)) is the form for load operation.
4190 (set (mem addr) (reg)) is the form for store operation.
4191 We have to extract reg and mem of every element and
4192 check if the information is valid for multiple load/store operation. */
4193bool
4194nds32_valid_multiple_load_store (rtx op, bool load_p)
4195{
4196 int count;
4197 int first_elt_regno;
4198 rtx elt;
4199
4200 /* Get the counts of elements in the parallel rtx. */
4201 count = XVECLEN (op, 0);
4202 /* Pick up the first element. */
4203 elt = XVECEXP (op, 0, 0);
4204
4205 /* Perform some quick check for the first element in the parallel rtx. */
4206 if (GET_CODE (elt) != SET
4207 || count <= 1
4208 || count > 8)
4209 return false;
4210
4211 /* Pick up regno of first element for further detail checking.
4212 Note that the form is different between load and store operation. */
4213 if (load_p)
4214 {
4215 if (GET_CODE (SET_DEST (elt)) != REG
4216 || GET_CODE (SET_SRC (elt)) != MEM)
4217 return false;
4218
4219 first_elt_regno = REGNO (SET_DEST (elt));
4220 }
4221 else
4222 {
4223 if (GET_CODE (SET_SRC (elt)) != REG
4224 || GET_CODE (SET_DEST (elt)) != MEM)
4225 return false;
4226
4227 first_elt_regno = REGNO (SET_SRC (elt));
4228 }
4229
4230 /* Perform detail check for each element.
4231 Refer to nds32-multiple.md for more information
4232 about following checking.
4233 The starting element of parallel rtx is index 0. */
4234 if (!nds32_consecutive_registers_load_store_p (op, load_p, 0,
4235 first_elt_regno,
4236 count))
4237 return false;
4238
4239 /* Pass all test, this is a valid rtx. */
4240 return true;
4241}
4242
4243/* Function to check whether the OP is a valid stack push/pop operation.
4244 For a valid stack operation, it must satisfy following conditions:
4245 1. Consecutive registers push/pop operations.
4246 2. Valid $fp/$gp/$lp push/pop operations.
4247 3. The last element must be stack adjustment rtx.
4248 See the prologue/epilogue implementation for details. */
4249bool
4250nds32_valid_stack_push_pop (rtx op, bool push_p)
4251{
4252 int index;
4253 int total_count;
4254 int rest_count;
4255 int first_regno;
4256 rtx elt;
4257 rtx elt_reg;
4258 rtx elt_mem;
4259 rtx elt_plus;
4260
4261 /* Get the counts of elements in the parallel rtx. */
4262 total_count = XVECLEN (op, 0);
4263
4264 /* Perform some quick check for that every element should be 'set'. */
4265 for (index = 0; index < total_count; index++)
4266 {
4267 elt = XVECEXP (op, 0, index);
4268 if (GET_CODE (elt) != SET)
4269 return false;
4270 }
4271
4272 /* For push operation, the parallel rtx looks like:
4273 (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
4274 (reg:SI Rb))
4275 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
4276 (reg:SI Rb+1))
4277 ...
4278 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
4279 (reg:SI Re))
4280 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
4281 (reg:SI FP_REGNUM))
4282 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
4283 (reg:SI GP_REGNUM))
4284 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
4285 (reg:SI LP_REGNUM))
4286 (set (reg:SI SP_REGNUM)
4287 (plus (reg:SI SP_REGNUM) (const_int -32)))])
4288
4289 For pop operation, the parallel rtx looks like:
4290 (parallel [(set (reg:SI Rb)
4291 (mem (reg:SI SP_REGNUM)))
4292 (set (reg:SI Rb+1)
4293 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
4294 ...
4295 (set (reg:SI Re)
4296 (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
4297 (set (reg:SI FP_REGNUM)
4298 (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
4299 (set (reg:SI GP_REGNUM)
4300 (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
4301 (set (reg:SI LP_REGNUM)
4302 (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
4303 (set (reg:SI SP_REGNUM)
4304 (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
4305
4306 /* 1. Consecutive registers push/pop operations.
4307 We need to calculate how many registers should be consecutive.
4308 The $sp adjustment rtx, $fp push rtx, $gp push rtx,
4309 and $lp push rtx are excluded. */
4310
4311 /* Exclude last $sp adjustment rtx. */
4312 rest_count = total_count - 1;
4313 /* Exclude $fp, $gp, and $lp if they are in the parallel rtx. */
4314 if (cfun->machine->fp_size)
4315 rest_count--;
4316 if (cfun->machine->gp_size)
4317 rest_count--;
4318 if (cfun->machine->lp_size)
4319 rest_count--;
4320
4321 if (rest_count > 0)
4322 {
4323 elt = XVECEXP (op, 0, 0);
4324 /* Pick up register element. */
4325 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
4326 first_regno = REGNO (elt_reg);
4327
4328 /* The 'push' operation is a kind of store operation.
4329 The 'pop' operation is a kind of load operation.
4330 Pass corresponding false/true as second argument (bool load_p).
4331 The par_index is supposed to start with index 0. */
4332 if (!nds32_consecutive_registers_load_store_p (op,
4333 !push_p ? true : false,
4334 0,
4335 first_regno,
4336 rest_count))
4337 return false;
4338 }
4339
4340 /* 2. Valid $fp/$gp/$lp push/pop operations.
4341 Remember to set start index for checking them. */
4342
4343 /* The rest_count is the start index for checking $fp/$gp/$lp. */
4344 index = rest_count;
4345 /* If index < 0, this parallel rtx is definitely
4346 not a valid stack push/pop operation. */
4347 if (index < 0)
4348 return false;
4349
4350 /* Check $fp/$gp/$lp one by one.
4351 We use 'push_p' to pick up reg rtx and mem rtx. */
4352 if (cfun->machine->fp_size)
4353 {
4354 elt = XVECEXP (op, 0, index);
4355 elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
4356 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
4357 index++;
4358
4359 if (GET_CODE (elt_mem) != MEM
4360 || GET_CODE (elt_reg) != REG
4361 || REGNO (elt_reg) != FP_REGNUM)
4362 return false;
4363 }
4364 if (cfun->machine->gp_size)
4365 {
4366 elt = XVECEXP (op, 0, index);
4367 elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
4368 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
4369 index++;
4370
4371 if (GET_CODE (elt_mem) != MEM
4372 || GET_CODE (elt_reg) != REG
4373 || REGNO (elt_reg) != GP_REGNUM)
4374 return false;
4375 }
4376 if (cfun->machine->lp_size)
4377 {
4378 elt = XVECEXP (op, 0, index);
4379 elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
4380 elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
4381 index++;
4382
4383 if (GET_CODE (elt_mem) != MEM
4384 || GET_CODE (elt_reg) != REG
4385 || REGNO (elt_reg) != LP_REGNUM)
4386 return false;
4387 }
4388
4389 /* 3. The last element must be stack adjustment rtx.
4390 Its form of rtx should be:
4391 (set (reg:SI SP_REGNUM)
4392 (plus (reg:SI SP_REGNUM) (const_int X)))
4393 The X could be positive or negative value. */
4394
4395 /* Pick up the last element. */
4396 elt = XVECEXP (op, 0, total_count - 1);
4397
4398 /* Extract its destination and source rtx. */
4399 elt_reg = SET_DEST (elt);
4400 elt_plus = SET_SRC (elt);
4401
4402 /* Check this is (set (stack_reg) (plus stack_reg const)) pattern. */
4403 if (GET_CODE (elt_reg) != REG
4404 || GET_CODE (elt_plus) != PLUS
4405 || REGNO (elt_reg) != SP_REGNUM)
4406 return false;
4407
4408 /* Pass all test, this is a valid rtx. */
4409 return true;
4410}
4411
4412/* Computing the Length of an Insn.
4413 Modifies the length assigned to instruction INSN.
4414 LEN is the initially computed length of the insn. */
4415int
4416nds32_adjust_insn_length (rtx insn, int length)
4417{
4418 rtx src, dst;
4419
4420 switch (recog_memoized (insn))
4421 {
4422 case CODE_FOR_move_df:
4423 case CODE_FOR_move_di:
4424 /* Adjust length of movd44 to 2. */
4425 src = XEXP (PATTERN (insn), 1);
4426 dst = XEXP (PATTERN (insn), 0);
4427
4428 if (REG_P (src)
4429 && REG_P (dst)
4430 && (REGNO (src) % 2) == 0
4431 && (REGNO (dst) % 2) == 0)
4432 length = 2;
4433 break;
4434
4435 default:
4436 break;
4437 }
4438
4439 return length;
4440}
4441
4442
4443/* Function to check if 'bclr' instruction can be used with IVAL. */
4444int
4445nds32_can_use_bclr_p (int ival)
4446{
4447 int one_bit_count;
4448
4449 /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit,
4450 it means the original ival has only one 0-bit,
4451 So it is ok to perform 'bclr' operation. */
4452
4453 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival));
4454
4455 /* 'bclr' is a performance extension instruction. */
4456 return (TARGET_PERF_EXT && (one_bit_count == 1));
4457}
4458
4459/* Function to check if 'bset' instruction can be used with IVAL. */
4460int
4461nds32_can_use_bset_p (int ival)
4462{
4463 int one_bit_count;
4464
4465 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
4466 it is ok to perform 'bset' operation. */
4467
4468 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
4469
4470 /* 'bset' is a performance extension instruction. */
4471 return (TARGET_PERF_EXT && (one_bit_count == 1));
4472}
4473
4474/* Function to check if 'btgl' instruction can be used with IVAL. */
4475int
4476nds32_can_use_btgl_p (int ival)
4477{
4478 int one_bit_count;
4479
4480 /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
4481 it is ok to perform 'btgl' operation. */
4482
4483 one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
4484
4485 /* 'btgl' is a performance extension instruction. */
4486 return (TARGET_PERF_EXT && (one_bit_count == 1));
4487}
4488
4489/* Function to check if 'bitci' instruction can be used with IVAL. */
4490int
4491nds32_can_use_bitci_p (int ival)
4492{
4493 /* If we are using V3 ISA, we have 'bitci' instruction.
4494 Try to see if we can present 'andi' semantic with
4495 such 'bit-clear-immediate' operation.
4496 For example, 'andi $r0,$r0,0xfffffffc' can be
4497 presented with 'bitci $r0,$r0,3'. */
4498 return (TARGET_ISA_V3
4499 && (ival < 0)
4500 && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode)));
4501}
4502
4503
4504/* Return true if is load/store with SYMBOL_REF addressing mode
4505 and memory mode is SImode. */
4506bool
4507nds32_symbol_load_store_p (rtx insn)
4508{
4509 rtx mem_src = NULL_RTX;
4510
4511 switch (get_attr_type (insn))
4512 {
4513 case TYPE_LOAD:
4514 mem_src = SET_SRC (PATTERN (insn));
4515 break;
4516 case TYPE_STORE:
4517 mem_src = SET_DEST (PATTERN (insn));
4518 break;
4519 default:
4520 break;
4521 }
4522
4523 /* Find load/store insn with addressing mode is SYMBOL_REF. */
4524 if (mem_src != NULL_RTX)
4525 {
4526 if ((GET_CODE (mem_src) == ZERO_EXTEND)
4527 || (GET_CODE (mem_src) == SIGN_EXTEND))
4528 mem_src = XEXP (mem_src, 0);
4529
4530 if ((GET_CODE (XEXP (mem_src, 0)) == SYMBOL_REF)
4531 || (GET_CODE (XEXP (mem_src, 0)) == LO_SUM))
4532 return true;
4533 }
4534
4535 return false;
4536}
4537
4538/* Function to determine whether it is worth to do fp_as_gp optimization.
4539 Return 0: It is NOT worth to do fp_as_gp optimization.
4540 Return 1: It is APPROXIMATELY worth to do fp_as_gp optimization.
4541 Note that if it is worth to do fp_as_gp optimization,
4542 we MUST set FP_REGNUM ever live in this function. */
4543int
4544nds32_fp_as_gp_check_available (void)
4545{
4546 /* If there exists ANY of following conditions,
4547 we DO NOT perform fp_as_gp optimization:
4548 1. TARGET_FORBID_FP_AS_GP is set
4549 regardless of the TARGET_FORCE_FP_AS_GP.
4550 2. User explicitly uses 'naked' attribute.
4551 3. Not optimize for size.
4552 4. Need frame pointer.
4553 5. If $fp is already required to be saved,
4554 it means $fp is already choosen by register allocator.
4555 Thus we better not to use it for fp_as_gp optimization.
4556 6. This function is a vararg function.
4557 DO NOT apply fp_as_gp optimization on this function
4558 because it may change and break stack frame.
4559 7. The epilogue is empty.
4560 This happens when the function uses exit()
4561 or its attribute is no_return.
4562 In that case, compiler will not expand epilogue
4563 so that we have no chance to output .omit_fp_end directive. */
4564 if (TARGET_FORBID_FP_AS_GP
4565 || lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))
4566 || !optimize_size
4567 || frame_pointer_needed
4568 || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM)
4569 || (cfun->stdarg == 1)
fefa31b5 4570 || (find_fallthru_edge (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == NULL))
9304f876
CJW
4571 return 0;
4572
4573 /* Now we can check the possibility of using fp_as_gp optimization. */
4574 if (TARGET_FORCE_FP_AS_GP)
4575 {
4576 /* User explicitly issues -mforce-fp-as-gp option. */
4577 df_set_regs_ever_live (FP_REGNUM, 1);
4578 return 1;
4579 }
4580 else
4581 {
4582 /* In the following we are going to evaluate whether
4583 it is worth to do fp_as_gp optimization. */
4584 int good_gain = 0;
4585 int symbol_count = 0;
4586
4587 int threshold;
4588 rtx insn;
4589
4590 /* We check if there already requires prologue.
4591 Note that $gp will be saved in prologue for PIC code generation.
4592 After that, we can set threshold by the existence of prologue.
4593 Each fp-implied instruction will gain 2-byte code size
4594 from gp-aware instruction, so we have following heuristics. */
4595 if (flag_pic
4596 || nds32_have_prologue_p ())
4597 {
4598 /* Have-prologue:
4599 Compiler already intends to generate prologue content,
4600 so the fp_as_gp optimization will only insert
4601 'la $fp,_FP_BASE_' instruction, which will be
4602 converted into 4-byte instruction at link time.
4603 The threshold is "3" symbol accesses, 2 + 2 + 2 > 4. */
4604 threshold = 3;
4605 }
4606 else
4607 {
4608 /* None-prologue:
4609 Compiler originally does not generate prologue content,
4610 so the fp_as_gp optimization will NOT ONLY insert
4611 'la $fp,_FP_BASE' instruction, but also causes
4612 push/pop instructions.
4613 If we are using v3push (push25/pop25),
4614 the threshold is "5" symbol accesses, 5*2 > 4 + 2 + 2;
4615 If we are using normal push (smw/lmw),
4616 the threshold is "5+2" symbol accesses 7*2 > 4 + 4 + 4. */
4617 threshold = 5 + (TARGET_V3PUSH ? 0 : 2);
4618 }
4619
4620 /* We would like to traverse every instruction in this function.
4621 So we need to have push_topmost_sequence()/pop_topmost_sequence()
4622 surrounding our for-loop evaluation. */
4623 push_topmost_sequence ();
4624 /* Counting the insn number which the addressing mode is symbol. */
4625 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4626 {
4627 if (single_set (insn) && nds32_symbol_load_store_p (insn))
4628 symbol_count++;
4629
4630 if (symbol_count == threshold)
4631 {
4632 good_gain = 1;
4633 break;
4634 }
4635 }
4636 pop_topmost_sequence ();
4637
4638 /* Enable fp_as_gp optimization when potential gain is good enough. */
4639 if (good_gain)
4640 {
4641 df_set_regs_ever_live (FP_REGNUM, 1);
4642 return 1;
4643 }
4644 }
4645
4646 /* By default we return 0. */
4647 return 0;
4648}
4649
4650
4651/* Function to generate PC relative jump table.
4652 Refer to nds32.md for more details.
4653
4654 The following is the sample for the case that diff value
4655 can be presented in '.short' size.
4656
4657 addi $r1, $r1, -(case_lower_bound)
4658 slti $ta, $r1, (case_number)
4659 beqz $ta, .L_skip_label
4660
4661 la $ta, .L35 ! get jump table address
4662 lh $r1, [$ta + $r1 << 1] ! load symbol diff from jump table entry
4663 addi $ta, $r1, $ta
4664 jr5 $ta
4665
4666 ! jump table entry
4667 L35:
4668 .short .L25-.L35
4669 .short .L26-.L35
4670 .short .L27-.L35
4671 .short .L28-.L35
4672 .short .L29-.L35
4673 .short .L30-.L35
4674 .short .L31-.L35
4675 .short .L32-.L35
4676 .short .L33-.L35
4677 .short .L34-.L35 */
4678const char *
4679nds32_output_casesi_pc_relative (rtx *operands)
4680{
4681 enum machine_mode mode;
4682 rtx diff_vec;
4683
d7b6661b 4684 diff_vec = PATTERN (NEXT_INSN (operands[1]));
9304f876
CJW
4685
4686 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
4687
4688 /* Step C: "t <-- operands[1]". */
4689 output_asm_insn ("la\t$ta, %l1", operands);
4690
4691 /* Get the mode of each element in the difference vector. */
4692 mode = GET_MODE (diff_vec);
4693
4694 /* Step D: "z <-- (mem (plus (operands[0] << m) t))",
4695 where m is 0, 1, or 2 to load address-diff value from table. */
4696 switch (mode)
4697 {
4698 case QImode:
4699 output_asm_insn ("lb\t%2, [$ta + %0 << 0]", operands);
4700 break;
4701 case HImode:
4702 output_asm_insn ("lh\t%2, [$ta + %0 << 1]", operands);
4703 break;
4704 case SImode:
4705 output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands);
4706 break;
4707 default:
4708 gcc_unreachable ();
4709 }
4710
4711 /* Step E: "t <-- z + t".
4712 Add table label_ref with address-diff value to
4713 obtain target case address. */
4714 output_asm_insn ("add\t$ta, %2, $ta", operands);
4715
4716 /* Step F: jump to target with register t. */
4717 if (TARGET_16_BIT)
4718 return "jr5\t$ta";
4719 else
4720 return "jr\t$ta";
4721}
4722
4723/* Function to generate normal jump table. */
4724const char *
4725nds32_output_casesi (rtx *operands)
4726{
4727 /* Step C: "t <-- operands[1]". */
4728 output_asm_insn ("la\t$ta, %l1", operands);
4729
4730 /* Step D: "z <-- (mem (plus (operands[0] << 2) t))". */
4731 output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands);
4732
4733 /* No need to perform Step E, which is only used for
4734 pc relative jump table. */
4735
4736 /* Step F: jump to target with register z. */
4737 if (TARGET_16_BIT)
4738 return "jr5\t%2";
4739 else
4740 return "jr\t%2";
4741}
4742
4743
4744/* Function to return memory format. */
4745enum nds32_16bit_address_type
4746nds32_mem_format (rtx op)
4747{
4748 enum machine_mode mode_test;
4749 int val;
4750 int regno;
4751
4752 if (!TARGET_16_BIT)
4753 return ADDRESS_NOT_16BIT_FORMAT;
4754
4755 mode_test = GET_MODE (op);
4756
4757 op = XEXP (op, 0);
4758
4759 /* 45 format. */
4760 if (GET_CODE (op) == REG && (mode_test == SImode))
4761 return ADDRESS_REG;
4762
4763 /* 333 format for QI/HImode. */
4764 if (GET_CODE (op) == REG && (REGNO (op) < R8_REGNUM))
4765 return ADDRESS_LO_REG_IMM3U;
4766
4767 /* post_inc 333 format. */
4768 if ((GET_CODE (op) == POST_INC) && (mode_test == SImode))
4769 {
4770 regno = REGNO(XEXP (op, 0));
4771
4772 if (regno < 8)
4773 return ADDRESS_POST_INC_LO_REG_IMM3U;
4774 }
4775
4776 /* post_inc 333 format. */
4777 if ((GET_CODE (op) == POST_MODIFY)
4778 && (mode_test == SImode)
4779 && (REG_P (XEXP (XEXP (op, 1), 0)))
4780 && (CONST_INT_P (XEXP (XEXP (op, 1), 1))))
4781 {
4782 regno = REGNO (XEXP (XEXP (op, 1), 0));
4783 val = INTVAL (XEXP (XEXP (op, 1), 1));
4784 if (regno < 8 && val < 32)
4785 return ADDRESS_POST_INC_LO_REG_IMM3U;
4786 }
4787
4788 if ((GET_CODE (op) == PLUS)
4789 && (GET_CODE (XEXP (op, 0)) == REG)
4790 && (GET_CODE (XEXP (op, 1)) == CONST_INT))
4791 {
4792 val = INTVAL (XEXP (op, 1));
4793
4794 regno = REGNO(XEXP (op, 0));
4795
4796 if (regno > 7
4797 && regno != SP_REGNUM
4798 && regno != FP_REGNUM)
4799 return ADDRESS_NOT_16BIT_FORMAT;
4800
4801 switch (mode_test)
4802 {
4803 case QImode:
4804 /* 333 format. */
4805 if (val >= 0 && val < 8 && regno < 8)
4806 return ADDRESS_LO_REG_IMM3U;
4807 break;
4808
4809 case HImode:
4810 /* 333 format. */
4811 if (val >= 0 && val < 16 && (val % 2 == 0) && regno < 8)
4812 return ADDRESS_LO_REG_IMM3U;
4813 break;
4814
4815 case SImode:
4816 case SFmode:
4817 case DFmode:
4818 /* fp imply 37 format. */
4819 if ((regno == FP_REGNUM) &&
4820 (val >= 0 && val < 512 && (val % 4 == 0)))
4821 return ADDRESS_FP_IMM7U;
4822 /* sp imply 37 format. */
4823 else if ((regno == SP_REGNUM) &&
4824 (val >= 0 && val < 512 && (val % 4 == 0)))
4825 return ADDRESS_SP_IMM7U;
4826 /* 333 format. */
4827 else if (val >= 0 && val < 32 && (val % 4 == 0) && regno < 8)
4828 return ADDRESS_LO_REG_IMM3U;
4829 break;
4830
4831 default:
4832 break;
4833 }
4834 }
4835
4836 return ADDRESS_NOT_16BIT_FORMAT;
4837}
4838
4839/* Output 16-bit store. */
4840const char *
4841nds32_output_16bit_store (rtx *operands, int byte)
4842{
4843 char pattern[100];
4844 char size;
4845 rtx code = XEXP (operands[0], 0);
4846
4847 size = nds32_byte_to_size (byte);
4848
4849 switch (nds32_mem_format (operands[0]))
4850 {
4851 case ADDRESS_REG:
4852 operands[0] = code;
4853 output_asm_insn ("swi450\t%1, [%0]", operands);
4854 break;
4855 case ADDRESS_LO_REG_IMM3U:
4856 snprintf (pattern, sizeof (pattern), "s%ci333\t%%1, %%0", size);
4857 output_asm_insn (pattern, operands);
4858 break;
4859 case ADDRESS_POST_INC_LO_REG_IMM3U:
4860 snprintf (pattern, sizeof (pattern), "s%ci333.bi\t%%1, %%0", size);
4861 output_asm_insn (pattern, operands);
4862 break;
4863 case ADDRESS_FP_IMM7U:
4864 output_asm_insn ("swi37\t%1, %0", operands);
4865 break;
4866 case ADDRESS_SP_IMM7U:
4867 /* Get immediate value and set back to operands[1]. */
4868 operands[0] = XEXP (code, 1);
4869 output_asm_insn ("swi37.sp\t%1, [ + (%0)]", operands);
4870 break;
4871 default:
4872 break;
4873 }
4874
4875 return "";
4876}
4877
4878/* Output 16-bit load. */
4879const char *
4880nds32_output_16bit_load (rtx *operands, int byte)
4881{
4882 char pattern[100];
4883 unsigned char size;
4884 rtx code = XEXP (operands[1], 0);
4885
4886 size = nds32_byte_to_size (byte);
4887
4888 switch (nds32_mem_format (operands[1]))
4889 {
4890 case ADDRESS_REG:
4891 operands[1] = code;
4892 output_asm_insn ("lwi450\t%0, [%1]", operands);
4893 break;
4894 case ADDRESS_LO_REG_IMM3U:
4895 snprintf (pattern, sizeof (pattern), "l%ci333\t%%0, %%1", size);
4896 output_asm_insn (pattern, operands);
4897 break;
4898 case ADDRESS_POST_INC_LO_REG_IMM3U:
4899 snprintf (pattern, sizeof (pattern), "l%ci333.bi\t%%0, %%1", size);
4900 output_asm_insn (pattern, operands);
4901 break;
4902 case ADDRESS_FP_IMM7U:
4903 output_asm_insn ("lwi37\t%0, %1", operands);
4904 break;
4905 case ADDRESS_SP_IMM7U:
4906 /* Get immediate value and set back to operands[0]. */
4907 operands[1] = XEXP (code, 1);
4908 output_asm_insn ("lwi37.sp\t%0, [ + (%1)]", operands);
4909 break;
4910 default:
4911 break;
4912 }
4913
4914 return "";
4915}
4916
4917/* Output 32-bit store. */
4918const char *
4919nds32_output_32bit_store (rtx *operands, int byte)
4920{
4921 char pattern[100];
4922 unsigned char size;
4923 rtx code = XEXP (operands[0], 0);
4924
4925 size = nds32_byte_to_size (byte);
4926
4927 switch (GET_CODE (code))
4928 {
4929 case REG:
4930 /* (mem (reg X))
4931 => access location by using register,
4932 use "sbi / shi / swi" */
4933 snprintf (pattern, sizeof (pattern), "s%ci\t%%1, %%0", size);
4934 break;
4935
4936 case SYMBOL_REF:
4937 case CONST:
4938 /* (mem (symbol_ref X))
4939 (mem (const (...)))
4940 => access global variables,
4941 use "sbi.gp / shi.gp / swi.gp" */
4942 operands[0] = XEXP (operands[0], 0);
4943 snprintf (pattern, sizeof (pattern), "s%ci.gp\t%%1, [ + %%0]", size);
4944 break;
4945
4946 case POST_INC:
4947 /* (mem (post_inc reg))
4948 => access location by using register which will be post increment,
4949 use "sbi.bi / shi.bi / swi.bi" */
4950 snprintf (pattern, sizeof (pattern),
4951 "s%ci.bi\t%%1, %%0, %d", size, byte);
4952 break;
4953
4954 case POST_DEC:
4955 /* (mem (post_dec reg))
4956 => access location by using register which will be post decrement,
4957 use "sbi.bi / shi.bi / swi.bi" */
4958 snprintf (pattern, sizeof (pattern),
4959 "s%ci.bi\t%%1, %%0, -%d", size, byte);
4960 break;
4961
4962 case POST_MODIFY:
4963 switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
4964 {
4965 case REG:
4966 case SUBREG:
4967 /* (mem (post_modify (reg) (plus (reg) (reg))))
4968 => access location by using register which will be
4969 post modified with reg,
4970 use "sb.bi/ sh.bi / sw.bi" */
4971 snprintf (pattern, sizeof (pattern), "s%c.bi\t%%1, %%0", size);
4972 break;
4973 case CONST_INT:
4974 /* (mem (post_modify (reg) (plus (reg) (const_int))))
4975 => access location by using register which will be
4976 post modified with const_int,
4977 use "sbi.bi/ shi.bi / swi.bi" */
4978 snprintf (pattern, sizeof (pattern), "s%ci.bi\t%%1, %%0", size);
4979 break;
4980 default:
4981 abort ();
4982 }
4983 break;
4984
4985 case PLUS:
4986 switch (GET_CODE (XEXP (code, 1)))
4987 {
4988 case REG:
4989 case SUBREG:
4990 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
4991 => access location by adding two registers,
4992 use "sb / sh / sw" */
4993 snprintf (pattern, sizeof (pattern), "s%c\t%%1, %%0", size);
4994 break;
4995 case CONST_INT:
4996 /* (mem (plus reg const_int))
4997 => access location by adding one register with const_int,
4998 use "sbi / shi / swi" */
4999 snprintf (pattern, sizeof (pattern), "s%ci\t%%1, %%0", size);
5000 break;
5001 default:
5002 abort ();
5003 }
5004 break;
5005
5006 case LO_SUM:
5007 operands[2] = XEXP (code, 1);
5008 operands[0] = XEXP (code, 0);
5009 snprintf (pattern, sizeof (pattern),
5010 "s%ci\t%%1, [%%0 + lo12(%%2)]", size);
5011 break;
5012
5013 default:
5014 abort ();
5015 }
5016
5017 output_asm_insn (pattern, operands);
5018 return "";
5019}
5020
5021/* Output 32-bit load. */
5022const char *
5023nds32_output_32bit_load (rtx *operands, int byte)
5024{
5025 char pattern[100];
5026 unsigned char size;
5027 rtx code;
5028
5029 code = XEXP (operands[1], 0);
5030
5031 size = nds32_byte_to_size (byte);
5032
5033 switch (GET_CODE (code))
5034 {
5035 case REG:
5036 /* (mem (reg X))
5037 => access location by using register,
5038 use "lbi / lhi / lwi" */
5039 snprintf (pattern, sizeof (pattern), "l%ci\t%%0, %%1", size);
5040 break;
5041
5042 case SYMBOL_REF:
5043 case CONST:
5044 /* (mem (symbol_ref X))
5045 (mem (const (...)))
5046 => access global variables,
5047 use "lbi.gp / lhi.gp / lwi.gp" */
5048 operands[1] = XEXP (operands[1], 0);
5049 snprintf (pattern, sizeof (pattern), "l%ci.gp\t%%0, [ + %%1]", size);
5050 break;
5051
5052 case POST_INC:
5053 /* (mem (post_inc reg))
5054 => access location by using register which will be post increment,
5055 use "lbi.bi / lhi.bi / lwi.bi" */
5056 snprintf (pattern, sizeof (pattern),
5057 "l%ci.bi\t%%0, %%1, %d", size, byte);
5058 break;
5059
5060 case POST_DEC:
5061 /* (mem (post_dec reg))
5062 => access location by using register which will be post decrement,
5063 use "lbi.bi / lhi.bi / lwi.bi" */
5064 snprintf (pattern, sizeof (pattern),
5065 "l%ci.bi\t%%0, %%1, -%d", size, byte);
5066 break;
5067
5068 case POST_MODIFY:
5069 switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
5070 {
5071 case REG:
5072 case SUBREG:
5073 /* (mem (post_modify (reg) (plus (reg) (reg))))
5074 => access location by using register which will be
5075 post modified with reg,
5076 use "lb.bi/ lh.bi / lw.bi" */
5077 snprintf (pattern, sizeof (pattern), "l%c.bi\t%%0, %%1", size);
5078 break;
5079 case CONST_INT:
5080 /* (mem (post_modify (reg) (plus (reg) (const_int))))
5081 => access location by using register which will be
5082 post modified with const_int,
5083 use "lbi.bi/ lhi.bi / lwi.bi" */
5084 snprintf (pattern, sizeof (pattern), "l%ci.bi\t%%0, %%1", size);
5085 break;
5086 default:
5087 abort ();
5088 }
5089 break;
5090
5091 case PLUS:
5092 switch (GET_CODE (XEXP (code, 1)))
5093 {
5094 case REG:
5095 case SUBREG:
5096 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
5097 use "lb / lh / lw" */
5098 snprintf (pattern, sizeof (pattern), "l%c\t%%0, %%1", size);
5099 break;
5100 case CONST_INT:
5101 /* (mem (plus reg const_int))
5102 => access location by adding one register with const_int,
5103 use "lbi / lhi / lwi" */
5104 snprintf (pattern, sizeof (pattern), "l%ci\t%%0, %%1", size);
5105 break;
5106 default:
5107 abort ();
5108 }
5109 break;
5110
5111 case LO_SUM:
5112 operands[2] = XEXP (code, 1);
5113 operands[1] = XEXP (code, 0);
5114 snprintf (pattern, sizeof (pattern),
5115 "l%ci\t%%0, [%%1 + lo12(%%2)]", size);
5116 break;
5117
5118 default:
5119 abort ();
5120 }
5121
5122 output_asm_insn (pattern, operands);
5123 return "";
5124}
5125
5126/* Output 32-bit load with signed extension. */
5127const char *
5128nds32_output_32bit_load_s (rtx *operands, int byte)
5129{
5130 char pattern[100];
5131 unsigned char size;
5132 rtx code;
5133
5134 code = XEXP (operands[1], 0);
5135
5136 size = nds32_byte_to_size (byte);
5137
5138 switch (GET_CODE (code))
5139 {
5140 case REG:
5141 /* (mem (reg X))
5142 => access location by using register,
5143 use "lbsi / lhsi" */
5144 snprintf (pattern, sizeof (pattern), "l%csi\t%%0, %%1", size);
5145 break;
5146
5147 case SYMBOL_REF:
5148 case CONST:
5149 /* (mem (symbol_ref X))
5150 (mem (const (...)))
5151 => access global variables,
5152 use "lbsi.gp / lhsi.gp" */
5153 operands[1] = XEXP (operands[1], 0);
5154 snprintf (pattern, sizeof (pattern), "l%csi.gp\t%%0, [ + %%1]", size);
5155 break;
5156
5157 case POST_INC:
5158 /* (mem (post_inc reg))
5159 => access location by using register which will be post increment,
5160 use "lbsi.bi / lhsi.bi" */
5161 snprintf (pattern, sizeof (pattern),
5162 "l%csi.bi\t%%0, %%1, %d", size, byte);
5163 break;
5164
5165 case POST_DEC:
5166 /* (mem (post_dec reg))
5167 => access location by using register which will be post decrement,
5168 use "lbsi.bi / lhsi.bi" */
5169 snprintf (pattern, sizeof (pattern),
5170 "l%csi.bi\t%%0, %%1, -%d", size, byte);
5171 break;
5172
5173 case POST_MODIFY:
5174 switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
5175 {
5176 case REG:
5177 case SUBREG:
5178 /* (mem (post_modify (reg) (plus (reg) (reg))))
5179 => access location by using register which will be
5180 post modified with reg,
5181 use "lbs.bi/ lhs.bi" */
5182 snprintf (pattern, sizeof (pattern), "l%cs.bi\t%%0, %%1", size);
5183 break;
5184 case CONST_INT:
5185 /* (mem (post_modify (reg) (plus (reg) (const_int))))
5186 => access location by using register which will be
5187 post modified with const_int,
5188 use "lbsi.bi/ lhsi.bi" */
5189 snprintf (pattern, sizeof (pattern), "l%csi.bi\t%%0, %%1", size);
5190 break;
5191 default:
5192 abort ();
5193 }
5194 break;
5195
5196 case PLUS:
5197 switch (GET_CODE (XEXP (code, 1)))
5198 {
5199 case REG:
5200 case SUBREG:
5201 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
5202 use "lbs / lhs" */
5203 snprintf (pattern, sizeof (pattern), "l%cs\t%%0, %%1", size);
5204 break;
5205 case CONST_INT:
5206 /* (mem (plus reg const_int))
5207 => access location by adding one register with const_int,
5208 use "lbsi / lhsi" */
5209 snprintf (pattern, sizeof (pattern), "l%csi\t%%0, %%1", size);
5210 break;
5211 default:
5212 abort ();
5213 }
5214 break;
5215
5216 case LO_SUM:
5217 operands[2] = XEXP (code, 1);
5218 operands[1] = XEXP (code, 0);
5219 snprintf (pattern, sizeof (pattern),
5220 "l%csi\t%%0, [%%1 + lo12(%%2)]", size);
5221 break;
5222
5223 default:
5224 abort ();
5225 }
5226
5227 output_asm_insn (pattern, operands);
5228 return "";
5229}
5230
5231/* Function to output stack push operation.
5232 We need to deal with normal stack push multiple or stack v3push. */
5233const char *
5234nds32_output_stack_push (void)
5235{
5236 /* A string pattern for output_asm_insn(). */
5237 char pattern[100];
5238 /* The operands array which will be used in output_asm_insn(). */
5239 rtx operands[3];
5240 /* Pick up callee-saved first regno and last regno for further use. */
5241 int rb_regno = cfun->machine->callee_saved_regs_first_regno;
5242 int re_regno = cfun->machine->callee_saved_regs_last_regno;
5243
5244 if (TARGET_V3PUSH)
5245 {
5246 /* For stack v3push:
5247 operands[0]: Re
5248 operands[1]: imm8u */
5249
5250 /* This variable is to check if 'push25 Re,imm8u' is available. */
5251 int sp_adjust;
5252
5253 /* Set operands[0]. */
5254 operands[0] = gen_rtx_REG (SImode, re_regno);
5255
5256 /* Check if we can generate 'push25 Re,imm8u',
5257 otherwise, generate 'push25 Re,0'. */
5258 sp_adjust = cfun->machine->local_size
5259 + cfun->machine->out_args_size
5260 + cfun->machine->callee_saved_area_padding_bytes;
5261 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
5262 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust))
5263 operands[1] = GEN_INT (sp_adjust);
5264 else
5265 operands[1] = GEN_INT (0);
5266
5267 /* Create assembly code pattern. */
5268 snprintf (pattern, sizeof (pattern), "push25\t%%0, %%1");
5269 }
5270 else
5271 {
5272 /* For normal stack push multiple:
5273 operands[0]: Rb
5274 operands[1]: Re
5275 operands[2]: En4 */
5276
5277 /* This variable is used to check if we only need to generate En4 field.
5278 As long as Rb==Re=SP_REGNUM, we set this variable to 1. */
5279 int push_en4_only_p = 0;
5280
5281 /* Set operands[0] and operands[1]. */
5282 operands[0] = gen_rtx_REG (SImode, rb_regno);
5283 operands[1] = gen_rtx_REG (SImode, re_regno);
5284
5285 /* 'smw.adm $sp,[$sp],$sp,0' means push nothing. */
5286 if (!cfun->machine->fp_size
5287 && !cfun->machine->gp_size
5288 && !cfun->machine->lp_size
5289 && REGNO (operands[0]) == SP_REGNUM
5290 && REGNO (operands[1]) == SP_REGNUM)
5291 {
5292 /* No need to generate instruction. */
5293 return "";
5294 }
5295 else
5296 {
5297 /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */
5298 if (REGNO (operands[0]) == SP_REGNUM
5299 && REGNO (operands[1]) == SP_REGNUM)
5300 push_en4_only_p = 1;
5301
5302 /* Create assembly code pattern.
5303 We need to handle the form: "Rb, Re, { $fp $gp $lp }". */
5304 snprintf (pattern, sizeof (pattern),
5305 "push.s\t%s{%s%s%s }",
5306 push_en4_only_p ? "" : "%0, %1, ",
5307 cfun->machine->fp_size ? " $fp" : "",
5308 cfun->machine->gp_size ? " $gp" : "",
5309 cfun->machine->lp_size ? " $lp" : "");
5310 }
5311 }
5312
5313 /* We use output_asm_insn() to output assembly code by ourself. */
5314 output_asm_insn (pattern, operands);
5315 return "";
5316}
5317
5318/* Function to output stack pop operation.
5319 We need to deal with normal stack pop multiple or stack v3pop. */
5320const char *
5321nds32_output_stack_pop (void)
5322{
5323 /* A string pattern for output_asm_insn(). */
5324 char pattern[100];
5325 /* The operands array which will be used in output_asm_insn(). */
5326 rtx operands[3];
5327 /* Pick up callee-saved first regno and last regno for further use. */
5328 int rb_regno = cfun->machine->callee_saved_regs_first_regno;
5329 int re_regno = cfun->machine->callee_saved_regs_last_regno;
5330
5331 if (TARGET_V3PUSH)
5332 {
5333 /* For stack v3pop:
5334 operands[0]: Re
5335 operands[1]: imm8u */
5336
5337 /* This variable is to check if 'pop25 Re,imm8u' is available. */
5338 int sp_adjust;
5339
5340 /* Set operands[0]. */
5341 operands[0] = gen_rtx_REG (SImode, re_regno);
5342
5343 /* Check if we can generate 'pop25 Re,imm8u',
5344 otherwise, generate 'pop25 Re,0'.
5345 We have to consider alloca issue as well.
5346 If the function does call alloca(), the stack pointer is not fixed.
5347 In that case, we cannot use 'pop25 Re,imm8u' directly.
5348 We have to caculate stack pointer from frame pointer
5349 and then use 'pop25 Re,0'. */
5350 sp_adjust = cfun->machine->local_size
5351 + cfun->machine->out_args_size
5352 + cfun->machine->callee_saved_area_padding_bytes;
5353 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
5354 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)
5355 && !cfun->calls_alloca)
5356 operands[1] = GEN_INT (sp_adjust);
5357 else
5358 operands[1] = GEN_INT (0);
5359
5360 /* Create assembly code pattern. */
5361 snprintf (pattern, sizeof (pattern), "pop25\t%%0, %%1");
5362 }
5363 else
5364 {
5365 /* For normal stack pop multiple:
5366 operands[0]: Rb
5367 operands[1]: Re
5368 operands[2]: En4 */
5369
5370 /* This variable is used to check if we only need to generate En4 field.
5371 As long as Rb==Re=SP_REGNUM, we set this variable to 1. */
5372 int pop_en4_only_p = 0;
5373
5374 /* Set operands[0] and operands[1]. */
5375 operands[0] = gen_rtx_REG (SImode, rb_regno);
5376 operands[1] = gen_rtx_REG (SImode, re_regno);
5377
5378 /* 'lmw.bim $sp,[$sp],$sp,0' means pop nothing. */
5379 if (!cfun->machine->fp_size
5380 && !cfun->machine->gp_size
5381 && !cfun->machine->lp_size
5382 && REGNO (operands[0]) == SP_REGNUM
5383 && REGNO (operands[1]) == SP_REGNUM)
5384 {
5385 /* No need to generate instruction. */
5386 return "";
5387 }
5388 else
5389 {
5390 /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */
5391 if (REGNO (operands[0]) == SP_REGNUM
5392 && REGNO (operands[1]) == SP_REGNUM)
5393 pop_en4_only_p = 1;
5394
5395 /* Create assembly code pattern.
5396 We need to handle the form: "Rb, Re, { $fp $gp $lp }". */
5397 snprintf (pattern, sizeof (pattern),
5398 "pop.s\t%s{%s%s%s }",
5399 pop_en4_only_p ? "" : "%0, %1, ",
5400 cfun->machine->fp_size ? " $fp" : "",
5401 cfun->machine->gp_size ? " $gp" : "",
5402 cfun->machine->lp_size ? " $lp" : "");
5403 }
5404 }
5405
5406 /* We use output_asm_insn() to output assembly code by ourself. */
5407 output_asm_insn (pattern, operands);
5408 return "";
5409}
5410
5411/* Return align 2 (log base 2) if the next instruction of LABEL is 4 byte. */
5412int
5413nds32_target_alignment (rtx label)
5414{
5415 rtx insn;
5416
5417 if (optimize_size)
5418 return 0;
5419
5420 insn = next_active_insn (label);
5421
5422 if (insn == 0)
5423 return 0;
5424 else if ((get_attr_length (insn) % 4) == 0)
5425 return 2;
5426 else
5427 return 0;
5428}
5429
5430/* ------------------------------------------------------------------------ */
5431
5432/* PART 5: Initialize target hook structure and definitions. */
5433\f
5434/* Controlling the Compilation Driver. */
5435
5436\f
5437/* Run-time Target Specification. */
5438
5439\f
5440/* Defining Data Structures for Per-function Information. */
5441
5442\f
5443/* Storage Layout. */
5444
5445#undef TARGET_PROMOTE_FUNCTION_MODE
5446#define TARGET_PROMOTE_FUNCTION_MODE \
5447 default_promote_function_mode_always_promote
5448
5449\f
5450/* Layout of Source Language Data Types. */
5451
5452\f
5453/* Register Usage. */
5454
5455/* -- Basic Characteristics of Registers. */
5456
5457/* -- Order of Allocation of Registers. */
5458
5459/* -- How Values Fit in Registers. */
5460
5461/* -- Handling Leaf Functions. */
5462
5463/* -- Registers That Form a Stack. */
5464
5465\f
5466/* Register Classes. */
5467
5468#undef TARGET_CLASS_MAX_NREGS
5469#define TARGET_CLASS_MAX_NREGS nds32_class_max_nregs
5470
5471#undef TARGET_LRA_P
5472#define TARGET_LRA_P hook_bool_void_true
5473
5474#undef TARGET_REGISTER_PRIORITY
5475#define TARGET_REGISTER_PRIORITY nds32_register_priority
5476
5477\f
5478/* Obsolete Macros for Defining Constraints. */
5479
5480\f
5481/* Stack Layout and Calling Conventions. */
5482
5483/* -- Basic Stack Layout. */
5484
5485/* -- Exception Handling Support. */
5486
5487/* -- Specifying How Stack Checking is Done. */
5488
5489/* -- Registers That Address the Stack Frame. */
5490
5491/* -- Eliminating Frame Pointer and Arg Pointer. */
5492
5493#undef TARGET_CAN_ELIMINATE
5494#define TARGET_CAN_ELIMINATE nds32_can_eliminate
5495
5496/* -- Passing Function Arguments on the Stack. */
5497
5498/* -- Passing Arguments in Registers. */
5499
5500#undef TARGET_FUNCTION_ARG
5501#define TARGET_FUNCTION_ARG nds32_function_arg
5502
5503#undef TARGET_FUNCTION_ARG_ADVANCE
5504#define TARGET_FUNCTION_ARG_ADVANCE nds32_function_arg_advance
5505
5506#undef TARGET_FUNCTION_ARG_BOUNDARY
5507#define TARGET_FUNCTION_ARG_BOUNDARY nds32_function_arg_boundary
5508
5509/* -- How Scalar Function Values Are Returned. */
5510
5511#undef TARGET_FUNCTION_VALUE
5512#define TARGET_FUNCTION_VALUE nds32_function_value
5513
5514#undef TARGET_LIBCALL_VALUE
5515#define TARGET_LIBCALL_VALUE nds32_libcall_value
5516
5517#undef TARGET_FUNCTION_VALUE_REGNO_P
5518#define TARGET_FUNCTION_VALUE_REGNO_P nds32_function_value_regno_p
5519
5520/* -- How Large Values Are Returned. */
5521
5522/* -- Caller-Saves Register Allocation. */
5523
5524/* -- Function Entry and Exit. */
5525
5526#undef TARGET_ASM_FUNCTION_PROLOGUE
5527#define TARGET_ASM_FUNCTION_PROLOGUE nds32_asm_function_prologue
5528
5529#undef TARGET_ASM_FUNCTION_END_PROLOGUE
5530#define TARGET_ASM_FUNCTION_END_PROLOGUE nds32_asm_function_end_prologue
5531
5532#undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
5533#define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE nds32_asm_function_begin_epilogue
5534
5535#undef TARGET_ASM_FUNCTION_EPILOGUE
5536#define TARGET_ASM_FUNCTION_EPILOGUE nds32_asm_function_epilogue
5537
5538#undef TARGET_ASM_OUTPUT_MI_THUNK
5539#define TARGET_ASM_OUTPUT_MI_THUNK nds32_asm_output_mi_thunk
5540
5541#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5542#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
5543
5544/* -- Generating Code for Profiling. */
5545
5546/* -- Permitting tail calls. */
5547
5548#undef TARGET_WARN_FUNC_RETURN
5549#define TARGET_WARN_FUNC_RETURN nds32_warn_func_return
5550
5551/* Stack smashing protection. */
5552
5553\f
5554/* Implementing the Varargs Macros. */
5555
5556#undef TARGET_STRICT_ARGUMENT_NAMING
5557#define TARGET_STRICT_ARGUMENT_NAMING nds32_strict_argument_naming
5558
5559\f
5560/* Trampolines for Nested Functions. */
5561
5562#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
5563#define TARGET_ASM_TRAMPOLINE_TEMPLATE nds32_asm_trampoline_template
5564
5565#undef TARGET_TRAMPOLINE_INIT
5566#define TARGET_TRAMPOLINE_INIT nds32_trampoline_init
5567
5568\f
5569/* Implicit Calls to Library Routines. */
5570
5571\f
5572/* Addressing Modes. */
5573
5574#undef TARGET_LEGITIMATE_ADDRESS_P
5575#define TARGET_LEGITIMATE_ADDRESS_P nds32_legitimate_address_p
5576
5577\f
5578/* Anchored Addresses. */
5579
5580\f
5581/* Condition Code Status. */
5582
5583/* -- Representation of condition codes using (cc0). */
5584
5585/* -- Representation of condition codes using registers. */
5586
5587/* -- Macros to control conditional execution. */
5588
5589\f
5590/* Describing Relative Costs of Operations. */
5591
5592#undef TARGET_REGISTER_MOVE_COST
5593#define TARGET_REGISTER_MOVE_COST nds32_register_move_cost
5594
5595#undef TARGET_MEMORY_MOVE_COST
5596#define TARGET_MEMORY_MOVE_COST nds32_memory_move_cost
5597
5598#undef TARGET_RTX_COSTS
5599#define TARGET_RTX_COSTS nds32_rtx_costs
5600
5601#undef TARGET_ADDRESS_COST
5602#define TARGET_ADDRESS_COST nds32_address_cost
5603
5604\f
5605/* Adjusting the Instruction Scheduler. */
5606
5607\f
5608/* Dividing the Output into Sections (Texts, Data, . . . ). */
5609
5610\f
5611/* Position Independent Code. */
5612
5613\f
5614/* Defining the Output Assembler Language. */
5615
5616/* -- The Overall Framework of an Assembler File. */
5617
5618#undef TARGET_ASM_FILE_START
5619#define TARGET_ASM_FILE_START nds32_asm_file_start
5620#undef TARGET_ASM_FILE_END
5621#define TARGET_ASM_FILE_END nds32_asm_file_end
5622
5623/* -- Output of Data. */
5624
5625#undef TARGET_ASM_ALIGNED_HI_OP
5626#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
5627
5628#undef TARGET_ASM_ALIGNED_SI_OP
5629#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
5630
5631/* -- Output of Uninitialized Variables. */
5632
5633/* -- Output and Generation of Labels. */
5634
5635#undef TARGET_ASM_GLOBALIZE_LABEL
5636#define TARGET_ASM_GLOBALIZE_LABEL nds32_asm_globalize_label
5637
5638/* -- How Initialization Functions Are Handled. */
5639
5640/* -- Macros Controlling Initialization Routines. */
5641
5642/* -- Output of Assembler Instructions. */
5643
5644#undef TARGET_PRINT_OPERAND
5645#define TARGET_PRINT_OPERAND nds32_print_operand
5646#undef TARGET_PRINT_OPERAND_ADDRESS
5647#define TARGET_PRINT_OPERAND_ADDRESS nds32_print_operand_address
5648
5649/* -- Output of Dispatch Tables. */
5650
5651/* -- Assembler Commands for Exception Regions. */
5652
5653/* -- Assembler Commands for Alignment. */
5654
5655\f
5656/* Controlling Debugging Information Format. */
5657
5658/* -- Macros Affecting All Debugging Formats. */
5659
5660/* -- Specific Options for DBX Output. */
5661
5662/* -- Open-Ended Hooks for DBX Format. */
5663
5664/* -- File Names in DBX Format. */
5665
5666/* -- Macros for SDB and DWARF Output. */
5667
5668/* -- Macros for VMS Debug Format. */
5669
5670\f
5671/* Cross Compilation and Floating Point. */
5672
5673\f
5674/* Mode Switching Instructions. */
5675
5676\f
5677/* Defining target-specific uses of __attribute__. */
5678
5679#undef TARGET_ATTRIBUTE_TABLE
5680#define TARGET_ATTRIBUTE_TABLE nds32_attribute_table
5681
5682#undef TARGET_MERGE_DECL_ATTRIBUTES
5683#define TARGET_MERGE_DECL_ATTRIBUTES nds32_merge_decl_attributes
5684
5685#undef TARGET_INSERT_ATTRIBUTES
5686#define TARGET_INSERT_ATTRIBUTES nds32_insert_attributes
5687
5688#undef TARGET_OPTION_PRAGMA_PARSE
5689#define TARGET_OPTION_PRAGMA_PARSE nds32_option_pragma_parse
5690
5691#undef TARGET_OPTION_OVERRIDE
5692#define TARGET_OPTION_OVERRIDE nds32_option_override
5693
5694\f
5695/* Emulating TLS. */
5696
5697\f
5698/* Defining coprocessor specifics for MIPS targets. */
5699
5700\f
5701/* Parameters for Precompiled Header Validity Checking. */
5702
5703\f
5704/* C++ ABI parameters. */
5705
5706\f
5707/* Adding support for named address spaces. */
5708
5709\f
5710/* Miscellaneous Parameters. */
5711
5712#undef TARGET_INIT_BUILTINS
5713#define TARGET_INIT_BUILTINS nds32_init_builtins
5714
5715#undef TARGET_EXPAND_BUILTIN
5716#define TARGET_EXPAND_BUILTIN nds32_expand_builtin
5717
5718\f
5719/* ------------------------------------------------------------------------ */
5720
5721/* Initialize the GCC target structure. */
5722
5723struct gcc_target targetm = TARGET_INITIALIZER;
5724
5725/* ------------------------------------------------------------------------ */