111
|
1 /* Subroutines used for code generation of Andes NDS32 cpu for GNU compiler
|
|
2 Copyright (C) 2012-2017 Free Software Foundation, Inc.
|
|
3 Contributed by Andes Technology Corporation.
|
|
4
|
|
5 This file is part of GCC.
|
|
6
|
|
7 GCC is free software; you can redistribute it and/or modify it
|
|
8 under the terms of the GNU General Public License as published
|
|
9 by the Free Software Foundation; either version 3, or (at your
|
|
10 option) any later version.
|
|
11
|
|
12 GCC is distributed in the hope that it will be useful, but WITHOUT
|
|
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
15 License for more details.
|
|
16
|
|
17 You should have received a copy of the GNU General Public License
|
|
18 along with GCC; see the file COPYING3. If not see
|
|
19 <http://www.gnu.org/licenses/>. */
|
|
20
|
|
21 /* ------------------------------------------------------------------------ */
|
|
22
|
|
23 #include "config.h"
|
|
24 #include "system.h"
|
|
25 #include "coretypes.h"
|
|
26 #include "backend.h"
|
|
27 #include "target.h"
|
|
28 #include "rtl.h"
|
|
29 #include "tree.h"
|
|
30 #include "stringpool.h"
|
|
31 #include "attribs.h"
|
|
32 #include "df.h"
|
|
33 #include "memmodel.h"
|
|
34 #include "tm_p.h"
|
|
35 #include "optabs.h" /* For GEN_FCN. */
|
|
36 #include "regs.h"
|
|
37 #include "emit-rtl.h"
|
|
38 #include "recog.h"
|
|
39 #include "diagnostic-core.h"
|
|
40 #include "stor-layout.h"
|
|
41 #include "varasm.h"
|
|
42 #include "calls.h"
|
|
43 #include "output.h"
|
|
44 #include "explow.h"
|
|
45 #include "expr.h"
|
|
46 #include "tm-constrs.h"
|
|
47 #include "builtins.h"
|
|
48
|
|
49 /* This file should be included last. */
|
|
50 #include "target-def.h"
|
|
51
|
|
52 /* ------------------------------------------------------------------------ */
|
|
53
|
|
54 /* This file is divided into five parts:
|
|
55
|
|
56 PART 1: Auxiliary static variable definitions and
|
|
57 target hook static variable definitions.
|
|
58
|
|
59 PART 2: Auxiliary static function definitions.
|
|
60
|
|
61 PART 3: Implement target hook stuff definitions.
|
|
62
|
|
63 PART 4: Implemet extern function definitions,
|
|
64 the prototype is in nds32-protos.h.
|
|
65
|
|
66 PART 5: Initialize target hook structure and definitions. */
|
|
67
|
|
68 /* ------------------------------------------------------------------------ */
|
|
69
|
|
70 /* PART 1: Auxiliary static variable definitions and
|
|
71 target hook static variable definitions. */
|
|
72
|
|
73 /* Define intrinsic register names.
|
|
74 Please refer to nds32_intrinsic.h file, the index is corresponding to
|
|
75 'enum nds32_intrinsic_registers' data type values.
|
|
76 NOTE that the base value starting from 1024. */
|
|
77 static const char * const nds32_intrinsic_register_names[] =
|
|
78 {
|
|
79 "$PSW", "$IPSW", "$ITYPE", "$IPC"
|
|
80 };
|
|
81
|
|
82 /* Defining target-specific uses of __attribute__. */
|
|
83 static const struct attribute_spec nds32_attribute_table[] =
|
|
84 {
|
|
85 /* Syntax: { name, min_len, max_len, decl_required, type_required,
|
|
86 function_type_required, handler, affects_type_identity } */
|
|
87
|
|
88 /* The interrupt vid: [0-63]+ (actual vector number starts from 9 to 72). */
|
|
89 { "interrupt", 1, 64, false, false, false, NULL, false },
|
|
90 /* The exception vid: [1-8]+ (actual vector number starts from 1 to 8). */
|
|
91 { "exception", 1, 8, false, false, false, NULL, false },
|
|
92 /* Argument is user's interrupt numbers. The vector number is always 0. */
|
|
93 { "reset", 1, 1, false, false, false, NULL, false },
|
|
94
|
|
95 /* The attributes describing isr nested type. */
|
|
96 { "nested", 0, 0, false, false, false, NULL, false },
|
|
97 { "not_nested", 0, 0, false, false, false, NULL, false },
|
|
98 { "nested_ready", 0, 0, false, false, false, NULL, false },
|
|
99
|
|
100 /* The attributes describing isr register save scheme. */
|
|
101 { "save_all", 0, 0, false, false, false, NULL, false },
|
|
102 { "partial_save", 0, 0, false, false, false, NULL, false },
|
|
103
|
|
104 /* The attributes used by reset attribute. */
|
|
105 { "nmi", 1, 1, false, false, false, NULL, false },
|
|
106 { "warm", 1, 1, false, false, false, NULL, false },
|
|
107
|
|
108 /* The attribute telling no prologue/epilogue. */
|
|
109 { "naked", 0, 0, false, false, false, NULL, false },
|
|
110
|
|
111 /* The last attribute spec is set to be NULL. */
|
|
112 { NULL, 0, 0, false, false, false, NULL, false }
|
|
113 };
|
|
114
|
|
115
|
|
116 /* ------------------------------------------------------------------------ */
|
|
117
|
|
118 /* PART 2: Auxiliary static function definitions. */
|
|
119
|
|
120 /* Function to save and restore machine-specific function data. */
|
|
121 static struct machine_function *
|
|
122 nds32_init_machine_status (void)
|
|
123 {
|
|
124 struct machine_function *machine;
|
|
125 machine = ggc_cleared_alloc<machine_function> ();
|
|
126
|
|
127 /* Initially assume this function needs prologue/epilogue. */
|
|
128 machine->naked_p = 0;
|
|
129
|
|
130 /* Initially assume this function does NOT use fp_as_gp optimization. */
|
|
131 machine->fp_as_gp_p = 0;
|
|
132
|
|
133 return machine;
|
|
134 }
|
|
135
|
|
136 /* Function to compute stack frame size and
|
|
137 store into cfun->machine structure. */
|
|
138 static void
|
|
139 nds32_compute_stack_frame (void)
|
|
140 {
|
|
141 int r;
|
|
142 int block_size;
|
|
143
|
|
144 /* Because nds32_compute_stack_frame() will be called from different place,
|
|
145 everytime we enter this function, we have to assume this function
|
|
146 needs prologue/epilogue. */
|
|
147 cfun->machine->naked_p = 0;
|
|
148
|
|
149 /* Get variadic arguments size to prepare pretend arguments and
|
|
150 we will push them into stack at prologue by ourself. */
|
|
151 cfun->machine->va_args_size = crtl->args.pretend_args_size;
|
|
152 if (cfun->machine->va_args_size != 0)
|
|
153 {
|
|
154 cfun->machine->va_args_first_regno
|
|
155 = NDS32_GPR_ARG_FIRST_REGNUM
|
|
156 + NDS32_MAX_GPR_REGS_FOR_ARGS
|
|
157 - (crtl->args.pretend_args_size / UNITS_PER_WORD);
|
|
158 cfun->machine->va_args_last_regno
|
|
159 = NDS32_GPR_ARG_FIRST_REGNUM + NDS32_MAX_GPR_REGS_FOR_ARGS - 1;
|
|
160 }
|
|
161 else
|
|
162 {
|
|
163 cfun->machine->va_args_first_regno = SP_REGNUM;
|
|
164 cfun->machine->va_args_last_regno = SP_REGNUM;
|
|
165 }
|
|
166
|
|
167 /* Important: We need to make sure that varargs area is 8-byte alignment. */
|
|
168 block_size = cfun->machine->va_args_size;
|
|
169 if (!NDS32_DOUBLE_WORD_ALIGN_P (block_size))
|
|
170 {
|
|
171 cfun->machine->va_args_area_padding_bytes
|
|
172 = NDS32_ROUND_UP_DOUBLE_WORD (block_size) - block_size;
|
|
173 }
|
|
174
|
|
175 /* Get local variables, incoming variables, and temporary variables size.
|
|
176 Note that we need to make sure it is 8-byte alignment because
|
|
177 there may be no padding bytes if we are using LRA. */
|
|
178 cfun->machine->local_size = NDS32_ROUND_UP_DOUBLE_WORD (get_frame_size ());
|
|
179
|
|
180 /* Get outgoing arguments size. */
|
|
181 cfun->machine->out_args_size = crtl->outgoing_args_size;
|
|
182
|
|
183 /* If $fp value is required to be saved on stack, it needs 4 bytes space.
|
|
184 Check whether $fp is ever live. */
|
|
185 cfun->machine->fp_size = (df_regs_ever_live_p (FP_REGNUM)) ? 4 : 0;
|
|
186
|
|
187 /* If $gp value is required to be saved on stack, it needs 4 bytes space.
|
|
188 Check whether we are using PIC code genration. */
|
|
189 cfun->machine->gp_size = (flag_pic) ? 4 : 0;
|
|
190
|
|
191 /* If $lp value is required to be saved on stack, it needs 4 bytes space.
|
|
192 Check whether $lp is ever live. */
|
|
193 cfun->machine->lp_size = (df_regs_ever_live_p (LP_REGNUM)) ? 4 : 0;
|
|
194
|
|
195 /* Initially there is no padding bytes. */
|
|
196 cfun->machine->callee_saved_area_gpr_padding_bytes = 0;
|
|
197
|
|
198 /* Calculate the bytes of saving callee-saved registers on stack. */
|
|
199 cfun->machine->callee_saved_gpr_regs_size = 0;
|
|
200 cfun->machine->callee_saved_first_gpr_regno = SP_REGNUM;
|
|
201 cfun->machine->callee_saved_last_gpr_regno = SP_REGNUM;
|
|
202 /* Currently, there is no need to check $r28~$r31
|
|
203 because we will save them in another way. */
|
|
204 for (r = 0; r < 28; r++)
|
|
205 {
|
|
206 if (NDS32_REQUIRED_CALLEE_SAVED_P (r))
|
|
207 {
|
|
208 /* Mark the first required callee-saved register
|
|
209 (only need to set it once).
|
|
210 If first regno == SP_REGNUM, we can tell that
|
|
211 it is the first time to be here. */
|
|
212 if (cfun->machine->callee_saved_first_gpr_regno == SP_REGNUM)
|
|
213 cfun->machine->callee_saved_first_gpr_regno = r;
|
|
214 /* Mark the last required callee-saved register. */
|
|
215 cfun->machine->callee_saved_last_gpr_regno = r;
|
|
216 }
|
|
217 }
|
|
218
|
|
219 /* Check if this function can omit prologue/epilogue code fragment.
|
|
220 If there is 'naked' attribute in this function,
|
|
221 we can set 'naked_p' flag to indicate that
|
|
222 we do not have to generate prologue/epilogue.
|
|
223 Or, if all the following conditions succeed,
|
|
224 we can set this function 'naked_p' as well:
|
|
225 condition 1: first_regno == last_regno == SP_REGNUM,
|
|
226 which means we do not have to save
|
|
227 any callee-saved registers.
|
|
228 condition 2: Both $lp and $fp are NOT live in this function,
|
|
229 which means we do not need to save them and there
|
|
230 is no outgoing size.
|
|
231 condition 3: There is no local_size, which means
|
|
232 we do not need to adjust $sp. */
|
|
233 if (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))
|
|
234 || (cfun->machine->callee_saved_first_gpr_regno == SP_REGNUM
|
|
235 && cfun->machine->callee_saved_last_gpr_regno == SP_REGNUM
|
|
236 && !df_regs_ever_live_p (FP_REGNUM)
|
|
237 && !df_regs_ever_live_p (LP_REGNUM)
|
|
238 && cfun->machine->local_size == 0))
|
|
239 {
|
|
240 /* Set this function 'naked_p' and other functions can check this flag.
|
|
241 Note that in nds32 port, the 'naked_p = 1' JUST means there is no
|
|
242 callee-saved, local size, and outgoing size.
|
|
243 The varargs space and ret instruction may still present in
|
|
244 the prologue/epilogue expanding. */
|
|
245 cfun->machine->naked_p = 1;
|
|
246
|
|
247 /* No need to save $fp, $gp, and $lp.
|
|
248 We should set these value to be zero
|
|
249 so that nds32_initial_elimination_offset() can work properly. */
|
|
250 cfun->machine->fp_size = 0;
|
|
251 cfun->machine->gp_size = 0;
|
|
252 cfun->machine->lp_size = 0;
|
|
253
|
|
254 /* If stack usage computation is required,
|
|
255 we need to provide the static stack size. */
|
|
256 if (flag_stack_usage_info)
|
|
257 current_function_static_stack_size = 0;
|
|
258
|
|
259 /* No need to do following adjustment, return immediately. */
|
|
260 return;
|
|
261 }
|
|
262
|
|
263 /* Adjustment for v3push instructions:
|
|
264 If we are using v3push (push25/pop25) instructions,
|
|
265 we need to make sure Rb is $r6 and Re is
|
|
266 located on $r6, $r8, $r10, or $r14.
|
|
267 Some results above will be discarded and recomputed.
|
|
268 Note that it is only available under V3/V3M ISA and we
|
|
269 DO NOT setup following stuff for isr or variadic function. */
|
|
270 if (TARGET_V3PUSH
|
|
271 && !nds32_isr_function_p (current_function_decl)
|
|
272 && (cfun->machine->va_args_size == 0))
|
|
273 {
|
|
274 /* Recompute:
|
|
275 cfun->machine->fp_size
|
|
276 cfun->machine->gp_size
|
|
277 cfun->machine->lp_size
|
|
278 cfun->machine->callee_saved_first_gpr_regno
|
|
279 cfun->machine->callee_saved_last_gpr_regno */
|
|
280
|
|
281 /* For v3push instructions, $fp, $gp, and $lp are always saved. */
|
|
282 cfun->machine->fp_size = 4;
|
|
283 cfun->machine->gp_size = 4;
|
|
284 cfun->machine->lp_size = 4;
|
|
285
|
|
286 /* Remember to set Rb = $r6. */
|
|
287 cfun->machine->callee_saved_first_gpr_regno = 6;
|
|
288
|
|
289 if (cfun->machine->callee_saved_last_gpr_regno <= 6)
|
|
290 {
|
|
291 /* Re = $r6 */
|
|
292 cfun->machine->callee_saved_last_gpr_regno = 6;
|
|
293 }
|
|
294 else if (cfun->machine->callee_saved_last_gpr_regno <= 8)
|
|
295 {
|
|
296 /* Re = $r8 */
|
|
297 cfun->machine->callee_saved_last_gpr_regno = 8;
|
|
298 }
|
|
299 else if (cfun->machine->callee_saved_last_gpr_regno <= 10)
|
|
300 {
|
|
301 /* Re = $r10 */
|
|
302 cfun->machine->callee_saved_last_gpr_regno = 10;
|
|
303 }
|
|
304 else if (cfun->machine->callee_saved_last_gpr_regno <= 14)
|
|
305 {
|
|
306 /* Re = $r14 */
|
|
307 cfun->machine->callee_saved_last_gpr_regno = 14;
|
|
308 }
|
|
309 else if (cfun->machine->callee_saved_last_gpr_regno == SP_REGNUM)
|
|
310 {
|
|
311 /* If last_regno is SP_REGNUM, which means
|
|
312 it is never changed, so set it to Re = $r6. */
|
|
313 cfun->machine->callee_saved_last_gpr_regno = 6;
|
|
314 }
|
|
315 else
|
|
316 {
|
|
317 /* The program flow should not go here. */
|
|
318 gcc_unreachable ();
|
|
319 }
|
|
320 }
|
|
321
|
|
322 /* We have correctly set callee_saved_first_gpr_regno
|
|
323 and callee_saved_last_gpr_regno.
|
|
324 Initially, the callee_saved_gpr_regs_size is supposed to be 0.
|
|
325 As long as callee_saved_last_gpr_regno is not SP_REGNUM,
|
|
326 we can update callee_saved_gpr_regs_size with new size. */
|
|
327 if (cfun->machine->callee_saved_last_gpr_regno != SP_REGNUM)
|
|
328 {
|
|
329 /* Compute pushed size of callee-saved registers. */
|
|
330 cfun->machine->callee_saved_gpr_regs_size
|
|
331 = 4 * (cfun->machine->callee_saved_last_gpr_regno
|
|
332 - cfun->machine->callee_saved_first_gpr_regno
|
|
333 + 1);
|
|
334 }
|
|
335
|
|
336 /* Important: We need to make sure that
|
|
337 (fp_size + gp_size + lp_size + callee_saved_gpr_regs_size)
|
|
338 is 8-byte alignment.
|
|
339 If it is not, calculate the padding bytes. */
|
|
340 block_size = cfun->machine->fp_size
|
|
341 + cfun->machine->gp_size
|
|
342 + cfun->machine->lp_size
|
|
343 + cfun->machine->callee_saved_gpr_regs_size;
|
|
344 if (!NDS32_DOUBLE_WORD_ALIGN_P (block_size))
|
|
345 {
|
|
346 cfun->machine->callee_saved_area_gpr_padding_bytes
|
|
347 = NDS32_ROUND_UP_DOUBLE_WORD (block_size) - block_size;
|
|
348 }
|
|
349
|
|
350 /* If stack usage computation is required,
|
|
351 we need to provide the static stack size. */
|
|
352 if (flag_stack_usage_info)
|
|
353 {
|
|
354 current_function_static_stack_size
|
|
355 = NDS32_ROUND_UP_DOUBLE_WORD (block_size)
|
|
356 + cfun->machine->local_size
|
|
357 + cfun->machine->out_args_size;
|
|
358 }
|
|
359 }
|
|
360
|
|
361 /* Function to create a parallel rtx pattern
|
|
362 which presents stack push multiple behavior.
|
|
363 The overall concept are:
|
|
364 "push registers to memory",
|
|
365 "adjust stack pointer". */
|
|
366 static void
|
|
367 nds32_emit_stack_push_multiple (rtx Rb, rtx Re, rtx En4, bool vaarg_p)
|
|
368 {
|
|
369 int regno;
|
|
370 int extra_count;
|
|
371 int num_use_regs;
|
|
372 int par_index;
|
|
373 int offset;
|
|
374 int save_fp, save_gp, save_lp;
|
|
375
|
|
376 rtx reg;
|
|
377 rtx mem;
|
|
378 rtx push_rtx;
|
|
379 rtx adjust_sp_rtx;
|
|
380 rtx parallel_insn;
|
|
381 rtx dwarf;
|
|
382
|
|
383 /* We need to provide a customized rtx which contains
|
|
384 necessary information for data analysis,
|
|
385 so we create a parallel rtx like this:
|
|
386 (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
|
|
387 (reg:SI Rb))
|
|
388 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
|
|
389 (reg:SI Rb+1))
|
|
390 ...
|
|
391 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
|
|
392 (reg:SI Re))
|
|
393 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
|
|
394 (reg:SI FP_REGNUM))
|
|
395 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
|
|
396 (reg:SI GP_REGNUM))
|
|
397 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
|
|
398 (reg:SI LP_REGNUM))
|
|
399 (set (reg:SI SP_REGNUM)
|
|
400 (plus (reg:SI SP_REGNUM) (const_int -32)))]) */
|
|
401
|
|
402 /* Determine whether we need to save $fp, $gp, or $lp. */
|
|
403 save_fp = INTVAL (En4) & 0x8;
|
|
404 save_gp = INTVAL (En4) & 0x4;
|
|
405 save_lp = INTVAL (En4) & 0x2;
|
|
406
|
|
407 /* Calculate the number of registers that will be pushed. */
|
|
408 extra_count = 0;
|
|
409 if (save_fp)
|
|
410 extra_count++;
|
|
411 if (save_gp)
|
|
412 extra_count++;
|
|
413 if (save_lp)
|
|
414 extra_count++;
|
|
415 /* Note that Rb and Re may be SP_REGNUM. DO NOT count it in. */
|
|
416 if (REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM)
|
|
417 num_use_regs = extra_count;
|
|
418 else
|
|
419 num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + extra_count;
|
|
420
|
|
421 /* In addition to used registers,
|
|
422 we need one more space for (set sp sp-x) rtx. */
|
|
423 parallel_insn = gen_rtx_PARALLEL (VOIDmode,
|
|
424 rtvec_alloc (num_use_regs + 1));
|
|
425 par_index = 0;
|
|
426
|
|
427 /* Initialize offset and start to create push behavior. */
|
|
428 offset = -(num_use_regs * 4);
|
|
429
|
|
430 /* Create (set mem regX) from Rb, Rb+1 up to Re. */
|
|
431 for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++)
|
|
432 {
|
|
433 /* Rb and Re may be SP_REGNUM.
|
|
434 We need to break this loop immediately. */
|
|
435 if (regno == SP_REGNUM)
|
|
436 break;
|
|
437
|
|
438 reg = gen_rtx_REG (SImode, regno);
|
|
439 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
440 stack_pointer_rtx,
|
|
441 offset));
|
|
442 push_rtx = gen_rtx_SET (mem, reg);
|
|
443 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
|
|
444 RTX_FRAME_RELATED_P (push_rtx) = 1;
|
|
445 offset = offset + 4;
|
|
446 par_index++;
|
|
447 }
|
|
448
|
|
449 /* Create (set mem fp), (set mem gp), and (set mem lp) if necessary. */
|
|
450 if (save_fp)
|
|
451 {
|
|
452 reg = gen_rtx_REG (SImode, FP_REGNUM);
|
|
453 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
454 stack_pointer_rtx,
|
|
455 offset));
|
|
456 push_rtx = gen_rtx_SET (mem, reg);
|
|
457 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
|
|
458 RTX_FRAME_RELATED_P (push_rtx) = 1;
|
|
459 offset = offset + 4;
|
|
460 par_index++;
|
|
461 }
|
|
462 if (save_gp)
|
|
463 {
|
|
464 reg = gen_rtx_REG (SImode, GP_REGNUM);
|
|
465 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
466 stack_pointer_rtx,
|
|
467 offset));
|
|
468 push_rtx = gen_rtx_SET (mem, reg);
|
|
469 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
|
|
470 RTX_FRAME_RELATED_P (push_rtx) = 1;
|
|
471 offset = offset + 4;
|
|
472 par_index++;
|
|
473 }
|
|
474 if (save_lp)
|
|
475 {
|
|
476 reg = gen_rtx_REG (SImode, LP_REGNUM);
|
|
477 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
478 stack_pointer_rtx,
|
|
479 offset));
|
|
480 push_rtx = gen_rtx_SET (mem, reg);
|
|
481 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
|
|
482 RTX_FRAME_RELATED_P (push_rtx) = 1;
|
|
483 offset = offset + 4;
|
|
484 par_index++;
|
|
485 }
|
|
486
|
|
487 /* Create (set sp sp-x). */
|
|
488
|
|
489 /* We need to re-calculate the offset value again for adjustment. */
|
|
490 offset = -(num_use_regs * 4);
|
|
491 adjust_sp_rtx
|
|
492 = gen_rtx_SET (stack_pointer_rtx,
|
|
493 plus_constant (Pmode, stack_pointer_rtx, offset));
|
|
494 XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
|
|
495 RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1;
|
|
496
|
|
497 parallel_insn = emit_insn (parallel_insn);
|
|
498
|
|
499 /* The insn rtx 'parallel_insn' will change frame layout.
|
|
500 We need to use RTX_FRAME_RELATED_P so that GCC is able to
|
|
501 generate CFI (Call Frame Information) stuff. */
|
|
502 RTX_FRAME_RELATED_P (parallel_insn) = 1;
|
|
503
|
|
504 /* Don't use GCC's logic for CFI info if we are generate a push for VAARG
|
|
505 since we will not restore those register at epilogue. */
|
|
506 if (vaarg_p)
|
|
507 {
|
|
508 dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA,
|
|
509 copy_rtx (adjust_sp_rtx), NULL_RTX);
|
|
510 REG_NOTES (parallel_insn) = dwarf;
|
|
511 }
|
|
512 }
|
|
513
|
|
514 /* Function to create a parallel rtx pattern
|
|
515 which presents stack pop multiple behavior.
|
|
516 The overall concept are:
|
|
517 "pop registers from memory",
|
|
518 "adjust stack pointer". */
|
|
519 static void
|
|
520 nds32_emit_stack_pop_multiple (rtx Rb, rtx Re, rtx En4)
|
|
521 {
|
|
522 int regno;
|
|
523 int extra_count;
|
|
524 int num_use_regs;
|
|
525 int par_index;
|
|
526 int offset;
|
|
527 int save_fp, save_gp, save_lp;
|
|
528
|
|
529 rtx reg;
|
|
530 rtx mem;
|
|
531 rtx pop_rtx;
|
|
532 rtx adjust_sp_rtx;
|
|
533 rtx parallel_insn;
|
|
534 rtx dwarf = NULL_RTX;
|
|
535
|
|
536 /* We need to provide a customized rtx which contains
|
|
537 necessary information for data analysis,
|
|
538 so we create a parallel rtx like this:
|
|
539 (parallel [(set (reg:SI Rb)
|
|
540 (mem (reg:SI SP_REGNUM)))
|
|
541 (set (reg:SI Rb+1)
|
|
542 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
|
|
543 ...
|
|
544 (set (reg:SI Re)
|
|
545 (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
|
|
546 (set (reg:SI FP_REGNUM)
|
|
547 (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
|
|
548 (set (reg:SI GP_REGNUM)
|
|
549 (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
|
|
550 (set (reg:SI LP_REGNUM)
|
|
551 (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
|
|
552 (set (reg:SI SP_REGNUM)
|
|
553 (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
|
|
554
|
|
555 /* Determine whether we need to restore $fp, $gp, or $lp. */
|
|
556 save_fp = INTVAL (En4) & 0x8;
|
|
557 save_gp = INTVAL (En4) & 0x4;
|
|
558 save_lp = INTVAL (En4) & 0x2;
|
|
559
|
|
560 /* Calculate the number of registers that will be poped. */
|
|
561 extra_count = 0;
|
|
562 if (save_fp)
|
|
563 extra_count++;
|
|
564 if (save_gp)
|
|
565 extra_count++;
|
|
566 if (save_lp)
|
|
567 extra_count++;
|
|
568 /* Note that Rb and Re may be SP_REGNUM. DO NOT count it in. */
|
|
569 if (REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM)
|
|
570 num_use_regs = extra_count;
|
|
571 else
|
|
572 num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + extra_count;
|
|
573
|
|
574 /* In addition to used registers,
|
|
575 we need one more space for (set sp sp+x) rtx. */
|
|
576 parallel_insn = gen_rtx_PARALLEL (VOIDmode,
|
|
577 rtvec_alloc (num_use_regs + 1));
|
|
578 par_index = 0;
|
|
579
|
|
580 /* Initialize offset and start to create pop behavior. */
|
|
581 offset = 0;
|
|
582
|
|
583 /* Create (set regX mem) from Rb, Rb+1 up to Re. */
|
|
584 for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++)
|
|
585 {
|
|
586 /* Rb and Re may be SP_REGNUM.
|
|
587 We need to break this loop immediately. */
|
|
588 if (regno == SP_REGNUM)
|
|
589 break;
|
|
590
|
|
591 reg = gen_rtx_REG (SImode, regno);
|
|
592 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
593 stack_pointer_rtx,
|
|
594 offset));
|
|
595 pop_rtx = gen_rtx_SET (reg, mem);
|
|
596 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
|
|
597 RTX_FRAME_RELATED_P (pop_rtx) = 1;
|
|
598 offset = offset + 4;
|
|
599 par_index++;
|
|
600
|
|
601 dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
|
|
602 }
|
|
603
|
|
604 /* Create (set fp mem), (set gp mem), and (set lp mem) if necessary. */
|
|
605 if (save_fp)
|
|
606 {
|
|
607 reg = gen_rtx_REG (SImode, FP_REGNUM);
|
|
608 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
609 stack_pointer_rtx,
|
|
610 offset));
|
|
611 pop_rtx = gen_rtx_SET (reg, mem);
|
|
612 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
|
|
613 RTX_FRAME_RELATED_P (pop_rtx) = 1;
|
|
614 offset = offset + 4;
|
|
615 par_index++;
|
|
616
|
|
617 dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
|
|
618 }
|
|
619 if (save_gp)
|
|
620 {
|
|
621 reg = gen_rtx_REG (SImode, GP_REGNUM);
|
|
622 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
623 stack_pointer_rtx,
|
|
624 offset));
|
|
625 pop_rtx = gen_rtx_SET (reg, mem);
|
|
626 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
|
|
627 RTX_FRAME_RELATED_P (pop_rtx) = 1;
|
|
628 offset = offset + 4;
|
|
629 par_index++;
|
|
630
|
|
631 dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
|
|
632 }
|
|
633 if (save_lp)
|
|
634 {
|
|
635 reg = gen_rtx_REG (SImode, LP_REGNUM);
|
|
636 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
637 stack_pointer_rtx,
|
|
638 offset));
|
|
639 pop_rtx = gen_rtx_SET (reg, mem);
|
|
640 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
|
|
641 RTX_FRAME_RELATED_P (pop_rtx) = 1;
|
|
642 offset = offset + 4;
|
|
643 par_index++;
|
|
644
|
|
645 dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
|
|
646 }
|
|
647
|
|
648 /* Create (set sp sp+x). */
|
|
649
|
|
650 /* The offset value is already in place. No need to re-calculate it. */
|
|
651 adjust_sp_rtx
|
|
652 = gen_rtx_SET (stack_pointer_rtx,
|
|
653 plus_constant (Pmode, stack_pointer_rtx, offset));
|
|
654 XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
|
|
655
|
|
656 /* Tell gcc we adjust SP in this insn. */
|
|
657 dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, copy_rtx (adjust_sp_rtx), dwarf);
|
|
658
|
|
659 parallel_insn = emit_insn (parallel_insn);
|
|
660
|
|
661 /* The insn rtx 'parallel_insn' will change frame layout.
|
|
662 We need to use RTX_FRAME_RELATED_P so that GCC is able to
|
|
663 generate CFI (Call Frame Information) stuff. */
|
|
664 RTX_FRAME_RELATED_P (parallel_insn) = 1;
|
|
665
|
|
666 /* Add CFI info by manual. */
|
|
667 REG_NOTES (parallel_insn) = dwarf;
|
|
668 }
|
|
669
|
|
670 /* Function to create a parallel rtx pattern
|
|
671 which presents stack v3push behavior.
|
|
672 The overall concept are:
|
|
673 "push registers to memory",
|
|
674 "adjust stack pointer". */
|
|
675 static void
|
|
676 nds32_emit_stack_v3push (rtx Rb,
|
|
677 rtx Re,
|
|
678 rtx En4 ATTRIBUTE_UNUSED,
|
|
679 rtx imm8u)
|
|
680 {
|
|
681 int regno;
|
|
682 int num_use_regs;
|
|
683 int par_index;
|
|
684 int offset;
|
|
685
|
|
686 rtx reg;
|
|
687 rtx mem;
|
|
688 rtx push_rtx;
|
|
689 rtx adjust_sp_rtx;
|
|
690 rtx parallel_insn;
|
|
691
|
|
692 /* We need to provide a customized rtx which contains
|
|
693 necessary information for data analysis,
|
|
694 so we create a parallel rtx like this:
|
|
695 (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
|
|
696 (reg:SI Rb))
|
|
697 (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
|
|
698 (reg:SI Rb+1))
|
|
699 ...
|
|
700 (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
|
|
701 (reg:SI Re))
|
|
702 (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
|
|
703 (reg:SI FP_REGNUM))
|
|
704 (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
|
|
705 (reg:SI GP_REGNUM))
|
|
706 (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
|
|
707 (reg:SI LP_REGNUM))
|
|
708 (set (reg:SI SP_REGNUM)
|
|
709 (plus (reg:SI SP_REGNUM) (const_int -32-imm8u)))]) */
|
|
710
|
|
711 /* Calculate the number of registers that will be pushed.
|
|
712 Since $fp, $gp, and $lp is always pushed with v3push instruction,
|
|
713 we need to count these three registers.
|
|
714 Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
|
|
715 So there is no need to worry about Rb=Re=SP_REGNUM case. */
|
|
716 num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + 3;
|
|
717
|
|
718 /* In addition to used registers,
|
|
719 we need one more space for (set sp sp-x-imm8u) rtx. */
|
|
720 parallel_insn = gen_rtx_PARALLEL (VOIDmode,
|
|
721 rtvec_alloc (num_use_regs + 1));
|
|
722 par_index = 0;
|
|
723
|
|
724 /* Initialize offset and start to create push behavior. */
|
|
725 offset = -(num_use_regs * 4);
|
|
726
|
|
727 /* Create (set mem regX) from Rb, Rb+1 up to Re.
|
|
728 Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
|
|
729 So there is no need to worry about Rb=Re=SP_REGNUM case. */
|
|
730 for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++)
|
|
731 {
|
|
732 reg = gen_rtx_REG (SImode, regno);
|
|
733 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
734 stack_pointer_rtx,
|
|
735 offset));
|
|
736 push_rtx = gen_rtx_SET (mem, reg);
|
|
737 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
|
|
738 RTX_FRAME_RELATED_P (push_rtx) = 1;
|
|
739 offset = offset + 4;
|
|
740 par_index++;
|
|
741 }
|
|
742
|
|
743 /* Create (set mem fp). */
|
|
744 reg = gen_rtx_REG (SImode, FP_REGNUM);
|
|
745 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
746 stack_pointer_rtx,
|
|
747 offset));
|
|
748 push_rtx = gen_rtx_SET (mem, reg);
|
|
749 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
|
|
750 RTX_FRAME_RELATED_P (push_rtx) = 1;
|
|
751 offset = offset + 4;
|
|
752 par_index++;
|
|
753 /* Create (set mem gp). */
|
|
754 reg = gen_rtx_REG (SImode, GP_REGNUM);
|
|
755 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
756 stack_pointer_rtx,
|
|
757 offset));
|
|
758 push_rtx = gen_rtx_SET (mem, reg);
|
|
759 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
|
|
760 RTX_FRAME_RELATED_P (push_rtx) = 1;
|
|
761 offset = offset + 4;
|
|
762 par_index++;
|
|
763 /* Create (set mem lp). */
|
|
764 reg = gen_rtx_REG (SImode, LP_REGNUM);
|
|
765 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
766 stack_pointer_rtx,
|
|
767 offset));
|
|
768 push_rtx = gen_rtx_SET (mem, reg);
|
|
769 XVECEXP (parallel_insn, 0, par_index) = push_rtx;
|
|
770 RTX_FRAME_RELATED_P (push_rtx) = 1;
|
|
771 offset = offset + 4;
|
|
772 par_index++;
|
|
773
|
|
774 /* Create (set sp sp-x-imm8u). */
|
|
775
|
|
776 /* We need to re-calculate the offset value again for adjustment. */
|
|
777 offset = -(num_use_regs * 4);
|
|
778 adjust_sp_rtx
|
|
779 = gen_rtx_SET (stack_pointer_rtx,
|
|
780 plus_constant (Pmode,
|
|
781 stack_pointer_rtx,
|
|
782 offset - INTVAL (imm8u)));
|
|
783 XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
|
|
784 RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1;
|
|
785
|
|
786 parallel_insn = emit_insn (parallel_insn);
|
|
787
|
|
788 /* The insn rtx 'parallel_insn' will change frame layout.
|
|
789 We need to use RTX_FRAME_RELATED_P so that GCC is able to
|
|
790 generate CFI (Call Frame Information) stuff. */
|
|
791 RTX_FRAME_RELATED_P (parallel_insn) = 1;
|
|
792 }
|
|
793
|
|
794 /* Function to create a parallel rtx pattern
|
|
795 which presents stack v3pop behavior.
|
|
796 The overall concept are:
|
|
797 "pop registers from memory",
|
|
798 "adjust stack pointer". */
|
|
799 static void
|
|
800 nds32_emit_stack_v3pop (rtx Rb,
|
|
801 rtx Re,
|
|
802 rtx En4 ATTRIBUTE_UNUSED,
|
|
803 rtx imm8u)
|
|
804 {
|
|
805 int regno;
|
|
806 int num_use_regs;
|
|
807 int par_index;
|
|
808 int offset;
|
|
809
|
|
810 rtx reg;
|
|
811 rtx mem;
|
|
812 rtx pop_rtx;
|
|
813 rtx adjust_sp_rtx;
|
|
814 rtx parallel_insn;
|
|
815 rtx dwarf = NULL_RTX;
|
|
816
|
|
817 /* We need to provide a customized rtx which contains
|
|
818 necessary information for data analysis,
|
|
819 so we create a parallel rtx like this:
|
|
820 (parallel [(set (reg:SI Rb)
|
|
821 (mem (reg:SI SP_REGNUM)))
|
|
822 (set (reg:SI Rb+1)
|
|
823 (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
|
|
824 ...
|
|
825 (set (reg:SI Re)
|
|
826 (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
|
|
827 (set (reg:SI FP_REGNUM)
|
|
828 (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
|
|
829 (set (reg:SI GP_REGNUM)
|
|
830 (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
|
|
831 (set (reg:SI LP_REGNUM)
|
|
832 (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
|
|
833 (set (reg:SI SP_REGNUM)
|
|
834 (plus (reg:SI SP_REGNUM) (const_int 32+imm8u)))]) */
|
|
835
|
|
836 /* Calculate the number of registers that will be poped.
|
|
837 Since $fp, $gp, and $lp is always poped with v3pop instruction,
|
|
838 we need to count these three registers.
|
|
839 Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
|
|
840 So there is no need to worry about Rb=Re=SP_REGNUM case. */
|
|
841 num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + 3;
|
|
842
|
|
843 /* In addition to used registers,
|
|
844 we need one more space for (set sp sp+x+imm8u) rtx. */
|
|
845 parallel_insn = gen_rtx_PARALLEL (VOIDmode,
|
|
846 rtvec_alloc (num_use_regs + 1));
|
|
847 par_index = 0;
|
|
848
|
|
849 /* Initialize offset and start to create pop behavior. */
|
|
850 offset = 0;
|
|
851
|
|
852 /* Create (set regX mem) from Rb, Rb+1 up to Re.
|
|
853 Under v3pop, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
|
|
854 So there is no need to worry about Rb=Re=SP_REGNUM case. */
|
|
855 for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++)
|
|
856 {
|
|
857 reg = gen_rtx_REG (SImode, regno);
|
|
858 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
859 stack_pointer_rtx,
|
|
860 offset));
|
|
861 pop_rtx = gen_rtx_SET (reg, mem);
|
|
862 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
|
|
863 RTX_FRAME_RELATED_P (pop_rtx) = 1;
|
|
864 offset = offset + 4;
|
|
865 par_index++;
|
|
866
|
|
867 dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
|
|
868 }
|
|
869
|
|
870 /* Create (set fp mem). */
|
|
871 reg = gen_rtx_REG (SImode, FP_REGNUM);
|
|
872 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
873 stack_pointer_rtx,
|
|
874 offset));
|
|
875 pop_rtx = gen_rtx_SET (reg, mem);
|
|
876 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
|
|
877 RTX_FRAME_RELATED_P (pop_rtx) = 1;
|
|
878 offset = offset + 4;
|
|
879 par_index++;
|
|
880 dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
|
|
881
|
|
882 /* Create (set gp mem). */
|
|
883 reg = gen_rtx_REG (SImode, GP_REGNUM);
|
|
884 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
885 stack_pointer_rtx,
|
|
886 offset));
|
|
887 pop_rtx = gen_rtx_SET (reg, mem);
|
|
888 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
|
|
889 RTX_FRAME_RELATED_P (pop_rtx) = 1;
|
|
890 offset = offset + 4;
|
|
891 par_index++;
|
|
892 dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
|
|
893
|
|
894 /* Create (set lp mem ). */
|
|
895 reg = gen_rtx_REG (SImode, LP_REGNUM);
|
|
896 mem = gen_frame_mem (SImode, plus_constant (Pmode,
|
|
897 stack_pointer_rtx,
|
|
898 offset));
|
|
899 pop_rtx = gen_rtx_SET (reg, mem);
|
|
900 XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
|
|
901 RTX_FRAME_RELATED_P (pop_rtx) = 1;
|
|
902 offset = offset + 4;
|
|
903 par_index++;
|
|
904 dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
|
|
905
|
|
906 /* Create (set sp sp+x+imm8u). */
|
|
907
|
|
908 /* The offset value is already in place. No need to re-calculate it. */
|
|
909 adjust_sp_rtx
|
|
910 = gen_rtx_SET (stack_pointer_rtx,
|
|
911 plus_constant (Pmode,
|
|
912 stack_pointer_rtx,
|
|
913 offset + INTVAL (imm8u)));
|
|
914 XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
|
|
915
|
|
916 /* Tell gcc we adjust SP in this insn. */
|
|
917 dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, copy_rtx (adjust_sp_rtx), dwarf);
|
|
918
|
|
919 parallel_insn = emit_insn (parallel_insn);
|
|
920
|
|
921 /* The insn rtx 'parallel_insn' will change frame layout.
|
|
922 We need to use RTX_FRAME_RELATED_P so that GCC is able to
|
|
923 generate CFI (Call Frame Information) stuff. */
|
|
924 RTX_FRAME_RELATED_P (parallel_insn) = 1;
|
|
925
|
|
926 /* Add CFI info by manual. */
|
|
927 REG_NOTES (parallel_insn) = dwarf;
|
|
928 }
|
|
929
|
|
930 /* Function that may creates more instructions
|
|
931 for large value on adjusting stack pointer.
|
|
932
|
|
933 In nds32 target, 'addi' can be used for stack pointer
|
|
934 adjustment in prologue/epilogue stage.
|
|
935 However, sometimes there are too many local variables so that
|
|
936 the adjustment value is not able to be fit in the 'addi' instruction.
|
|
937 One solution is to move value into a register
|
|
938 and then use 'add' instruction.
|
|
939 In practice, we use TA_REGNUM ($r15) to accomplish this purpose.
|
|
940 Also, we need to return zero for sp adjustment so that
|
|
941 proglogue/epilogue knows there is no need to create 'addi' instruction. */
|
|
942 static int
|
|
943 nds32_force_addi_stack_int (int full_value)
|
|
944 {
|
|
945 int adjust_value;
|
|
946
|
|
947 rtx tmp_reg;
|
|
948 rtx sp_adjust_insn;
|
|
949
|
|
950 if (!satisfies_constraint_Is15 (GEN_INT (full_value)))
|
|
951 {
|
|
952 /* The value is not able to fit in single addi instruction.
|
|
953 Create more instructions of moving value into a register
|
|
954 and then add stack pointer with it. */
|
|
955
|
|
956 /* $r15 is going to be temporary register to hold the value. */
|
|
957 tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
|
|
958
|
|
959 /* Create one more instruction to move value
|
|
960 into the temporary register. */
|
|
961 emit_move_insn (tmp_reg, GEN_INT (full_value));
|
|
962
|
|
963 /* Create new 'add' rtx. */
|
|
964 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
|
|
965 stack_pointer_rtx,
|
|
966 tmp_reg);
|
|
967 /* Emit rtx into insn list and receive its transformed insn rtx. */
|
|
968 sp_adjust_insn = emit_insn (sp_adjust_insn);
|
|
969
|
|
970 /* At prologue, we need to tell GCC that this is frame related insn,
|
|
971 so that we can consider this instruction to output debug information.
|
|
972 If full_value is NEGATIVE, it means this function
|
|
973 is invoked by expand_prologue. */
|
|
974 if (full_value < 0)
|
|
975 {
|
|
976 /* Because (tmp_reg <- full_value) may be split into two
|
|
977 rtl patterns, we can not set its RTX_FRAME_RELATED_P.
|
|
978 We need to construct another (sp <- sp + full_value)
|
|
979 and then insert it into sp_adjust_insn's reg note to
|
|
980 represent a frame related expression.
|
|
981 GCC knows how to refer it and output debug information. */
|
|
982
|
|
983 rtx plus_rtx;
|
|
984 rtx set_rtx;
|
|
985
|
|
986 plus_rtx = plus_constant (Pmode, stack_pointer_rtx, full_value);
|
|
987 set_rtx = gen_rtx_SET (stack_pointer_rtx, plus_rtx);
|
|
988 add_reg_note (sp_adjust_insn, REG_FRAME_RELATED_EXPR, set_rtx);
|
|
989
|
|
990 RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
|
|
991 }
|
|
992
|
|
993 /* We have used alternative way to adjust stack pointer value.
|
|
994 Return zero so that prologue/epilogue
|
|
995 will not generate other instructions. */
|
|
996 return 0;
|
|
997 }
|
|
998 else
|
|
999 {
|
|
1000 /* The value is able to fit in addi instruction.
|
|
1001 However, remember to make it to be positive value
|
|
1002 because we want to return 'adjustment' result. */
|
|
1003 adjust_value = (full_value < 0) ? (-full_value) : (full_value);
|
|
1004
|
|
1005 return adjust_value;
|
|
1006 }
|
|
1007 }
|
|
1008
|
|
1009 /* Return true if MODE/TYPE need double word alignment. */
|
|
1010 static bool
|
|
1011 nds32_needs_double_word_align (machine_mode mode, const_tree type)
|
|
1012 {
|
|
1013 unsigned int align;
|
|
1014
|
|
1015 /* Pick up the alignment according to the mode or type. */
|
|
1016 align = NDS32_MODE_TYPE_ALIGN (mode, type);
|
|
1017
|
|
1018 return (align > PARM_BOUNDARY);
|
|
1019 }
|
|
1020
|
|
1021 /* Return true if FUNC is a naked function. */
|
|
1022 static bool
|
|
1023 nds32_naked_function_p (tree func)
|
|
1024 {
|
|
1025 tree t;
|
|
1026
|
|
1027 if (TREE_CODE (func) != FUNCTION_DECL)
|
|
1028 abort ();
|
|
1029
|
|
1030 t = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
|
|
1031
|
|
1032 return (t != NULL_TREE);
|
|
1033 }
|
|
1034
|
|
1035 /* Function that check if 'X' is a valid address register.
|
|
1036 The variable 'STRICT' is very important to
|
|
1037 make decision for register number.
|
|
1038
|
|
1039 STRICT : true
|
|
1040 => We are in reload pass or after reload pass.
|
|
1041 The register number should be strictly limited in general registers.
|
|
1042
|
|
1043 STRICT : false
|
|
1044 => Before reload pass, we are free to use any register number. */
|
|
1045 static bool
|
|
1046 nds32_address_register_rtx_p (rtx x, bool strict)
|
|
1047 {
|
|
1048 int regno;
|
|
1049
|
|
1050 if (GET_CODE (x) != REG)
|
|
1051 return false;
|
|
1052
|
|
1053 regno = REGNO (x);
|
|
1054
|
|
1055 if (strict)
|
|
1056 return REGNO_OK_FOR_BASE_P (regno);
|
|
1057 else
|
|
1058 return true;
|
|
1059 }
|
|
1060
|
|
1061 /* Function that check if 'INDEX' is valid to be a index rtx for address.
|
|
1062
|
|
1063 OUTER_MODE : Machine mode of outer address rtx.
|
|
1064 INDEX : Check if this rtx is valid to be a index for address.
|
|
1065 STRICT : If it is true, we are in reload pass or after reload pass. */
|
|
1066 static bool
|
|
1067 nds32_legitimate_index_p (machine_mode outer_mode,
|
|
1068 rtx index,
|
|
1069 bool strict)
|
|
1070 {
|
|
1071 int regno;
|
|
1072 rtx op0;
|
|
1073 rtx op1;
|
|
1074
|
|
1075 switch (GET_CODE (index))
|
|
1076 {
|
|
1077 case REG:
|
|
1078 regno = REGNO (index);
|
|
1079 /* If we are in reload pass or after reload pass,
|
|
1080 we need to limit it to general register. */
|
|
1081 if (strict)
|
|
1082 return REGNO_OK_FOR_INDEX_P (regno);
|
|
1083 else
|
|
1084 return true;
|
|
1085
|
|
1086 case CONST_INT:
|
|
1087 /* The alignment of the integer value is determined by 'outer_mode'. */
|
|
1088 if (GET_MODE_SIZE (outer_mode) == 1)
|
|
1089 {
|
|
1090 /* Further check if the value is legal for the 'outer_mode'. */
|
|
1091 if (!satisfies_constraint_Is15 (index))
|
|
1092 return false;
|
|
1093
|
|
1094 /* Pass all test, the value is valid, return true. */
|
|
1095 return true;
|
|
1096 }
|
|
1097 if (GET_MODE_SIZE (outer_mode) == 2
|
|
1098 && NDS32_HALF_WORD_ALIGN_P (INTVAL (index)))
|
|
1099 {
|
|
1100 /* Further check if the value is legal for the 'outer_mode'. */
|
|
1101 if (!satisfies_constraint_Is16 (index))
|
|
1102 return false;
|
|
1103
|
|
1104 /* Pass all test, the value is valid, return true. */
|
|
1105 return true;
|
|
1106 }
|
|
1107 if (GET_MODE_SIZE (outer_mode) == 4
|
|
1108 && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index)))
|
|
1109 {
|
|
1110 /* Further check if the value is legal for the 'outer_mode'. */
|
|
1111 if (!satisfies_constraint_Is17 (index))
|
|
1112 return false;
|
|
1113
|
|
1114 /* Pass all test, the value is valid, return true. */
|
|
1115 return true;
|
|
1116 }
|
|
1117 if (GET_MODE_SIZE (outer_mode) == 8
|
|
1118 && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index)))
|
|
1119 {
|
|
1120 /* Further check if the value is legal for the 'outer_mode'. */
|
|
1121 if (!satisfies_constraint_Is17 (gen_int_mode (INTVAL (index) + 4,
|
|
1122 SImode)))
|
|
1123 return false;
|
|
1124
|
|
1125 /* Pass all test, the value is valid, return true. */
|
|
1126 return true;
|
|
1127 }
|
|
1128
|
|
1129 return false;
|
|
1130
|
|
1131 case MULT:
|
|
1132 op0 = XEXP (index, 0);
|
|
1133 op1 = XEXP (index, 1);
|
|
1134
|
|
1135 if (REG_P (op0) && CONST_INT_P (op1))
|
|
1136 {
|
|
1137 int multiplier;
|
|
1138 multiplier = INTVAL (op1);
|
|
1139
|
|
1140 /* We only allow (mult reg const_int_1)
|
|
1141 or (mult reg const_int_2) or (mult reg const_int_4). */
|
|
1142 if (multiplier != 1 && multiplier != 2 && multiplier != 4)
|
|
1143 return false;
|
|
1144
|
|
1145 regno = REGNO (op0);
|
|
1146 /* Limit it in general registers if we are
|
|
1147 in reload pass or after reload pass. */
|
|
1148 if(strict)
|
|
1149 return REGNO_OK_FOR_INDEX_P (regno);
|
|
1150 else
|
|
1151 return true;
|
|
1152 }
|
|
1153
|
|
1154 return false;
|
|
1155
|
|
1156 case ASHIFT:
|
|
1157 op0 = XEXP (index, 0);
|
|
1158 op1 = XEXP (index, 1);
|
|
1159
|
|
1160 if (REG_P (op0) && CONST_INT_P (op1))
|
|
1161 {
|
|
1162 int sv;
|
|
1163 /* op1 is already the sv value for use to do left shift. */
|
|
1164 sv = INTVAL (op1);
|
|
1165
|
|
1166 /* We only allow (ashift reg const_int_0)
|
|
1167 or (ashift reg const_int_1) or (ashift reg const_int_2). */
|
|
1168 if (sv != 0 && sv != 1 && sv !=2)
|
|
1169 return false;
|
|
1170
|
|
1171 regno = REGNO (op0);
|
|
1172 /* Limit it in general registers if we are
|
|
1173 in reload pass or after reload pass. */
|
|
1174 if(strict)
|
|
1175 return REGNO_OK_FOR_INDEX_P (regno);
|
|
1176 else
|
|
1177 return true;
|
|
1178 }
|
|
1179
|
|
1180 return false;
|
|
1181
|
|
1182 default:
|
|
1183 return false;
|
|
1184 }
|
|
1185 }
|
|
1186
|
|
1187 /* ------------------------------------------------------------------------ */
|
|
1188
|
|
1189 /* PART 3: Implement target hook stuff definitions. */
|
|
1190
|
|
1191 /* Register Classes. */
|
|
1192
|
|
1193 static unsigned char
|
|
1194 nds32_class_max_nregs (reg_class_t rclass ATTRIBUTE_UNUSED,
|
|
1195 machine_mode mode)
|
|
1196 {
|
|
1197 /* Return the maximum number of consecutive registers
|
|
1198 needed to represent "mode" in a register of "rclass". */
|
|
1199 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
|
|
1200 }
|
|
1201
|
|
1202 static int
|
|
1203 nds32_register_priority (int hard_regno)
|
|
1204 {
|
|
1205 /* Encourage to use r0-r7 for LRA when optimize for size. */
|
|
1206 if (optimize_size && hard_regno < 8)
|
|
1207 return 4;
|
|
1208 return 3;
|
|
1209 }
|
|
1210
|
|
1211
|
|
1212 /* Stack Layout and Calling Conventions. */
|
|
1213
|
|
1214 /* There are three kinds of pointer concepts using in GCC compiler:
|
|
1215
|
|
1216 frame pointer: A pointer to the first location of local variables.
|
|
1217 stack pointer: A pointer to the top of a stack frame.
|
|
1218 argument pointer: A pointer to the incoming arguments.
|
|
1219
|
|
1220 In nds32 target calling convention, we are using 8-byte alignment.
|
|
1221 Besides, we would like to have each stack frame of a function includes:
|
|
1222
|
|
1223 [Block A]
|
|
1224 1. previous hard frame pointer
|
|
1225 2. return address
|
|
1226 3. callee-saved registers
|
|
1227 4. <padding bytes> (we will calculte in nds32_compute_stack_frame()
|
|
1228 and save it at
|
|
1229 cfun->machine->callee_saved_area_padding_bytes)
|
|
1230
|
|
1231 [Block B]
|
|
1232 1. local variables
|
|
1233 2. spilling location
|
|
1234 3. <padding bytes> (it will be calculated by GCC itself)
|
|
1235 4. incoming arguments
|
|
1236 5. <padding bytes> (it will be calculated by GCC itself)
|
|
1237
|
|
1238 [Block C]
|
|
1239 1. <padding bytes> (it will be calculated by GCC itself)
|
|
1240 2. outgoing arguments
|
|
1241
|
|
1242 We 'wrap' these blocks together with
|
|
1243 hard frame pointer ($r28) and stack pointer ($r31).
|
|
1244 By applying the basic frame/stack/argument pointers concept,
|
|
1245 the layout of a stack frame shoule be like this:
|
|
1246
|
|
1247 | |
|
|
1248 old stack pointer -> ----
|
|
1249 | | \
|
|
1250 | | saved arguments for
|
|
1251 | | vararg functions
|
|
1252 | | /
|
|
1253 hard frame pointer -> --
|
|
1254 & argument pointer | | \
|
|
1255 | | previous hardware frame pointer
|
|
1256 | | return address
|
|
1257 | | callee-saved registers
|
|
1258 | | /
|
|
1259 frame pointer -> --
|
|
1260 | | \
|
|
1261 | | local variables
|
|
1262 | | and incoming arguments
|
|
1263 | | /
|
|
1264 --
|
|
1265 | | \
|
|
1266 | | outgoing
|
|
1267 | | arguments
|
|
1268 | | /
|
|
1269 stack pointer -> ----
|
|
1270
|
|
1271 $SFP and $AP are used to represent frame pointer and arguments pointer,
|
|
1272 which will be both eliminated as hard frame pointer. */
|
|
1273
|
|
1274 /* -- Eliminating Frame Pointer and Arg Pointer. */
|
|
1275
|
|
1276 static bool
|
|
1277 nds32_can_eliminate (const int from_reg, const int to_reg)
|
|
1278 {
|
|
1279 if (from_reg == ARG_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM)
|
|
1280 return true;
|
|
1281
|
|
1282 if (from_reg == ARG_POINTER_REGNUM && to_reg == HARD_FRAME_POINTER_REGNUM)
|
|
1283 return true;
|
|
1284
|
|
1285 if (from_reg == FRAME_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM)
|
|
1286 return true;
|
|
1287
|
|
1288 if (from_reg == FRAME_POINTER_REGNUM && to_reg == HARD_FRAME_POINTER_REGNUM)
|
|
1289 return true;
|
|
1290
|
|
1291 return false;
|
|
1292 }
|
|
1293
|
|
1294 /* -- Passing Arguments in Registers. */
|
|
1295
|
|
1296 static rtx
|
|
1297 nds32_function_arg (cumulative_args_t ca, machine_mode mode,
|
|
1298 const_tree type, bool named)
|
|
1299 {
|
|
1300 unsigned int regno;
|
|
1301 CUMULATIVE_ARGS *cum = get_cumulative_args (ca);
|
|
1302
|
|
1303 /* The last time this hook is called,
|
|
1304 it is called with MODE == VOIDmode. */
|
|
1305 if (mode == VOIDmode)
|
|
1306 return NULL_RTX;
|
|
1307
|
|
1308 /* For nameless arguments, we need to take care it individually. */
|
|
1309 if (!named)
|
|
1310 {
|
|
1311 /* If we are under hard float abi, we have arguments passed on the
|
|
1312 stack and all situation can be handled by GCC itself. */
|
|
1313 if (TARGET_HARD_FLOAT)
|
|
1314 return NULL_RTX;
|
|
1315
|
|
1316 if (NDS32_ARG_PARTIAL_IN_GPR_REG_P (cum->gpr_offset, mode, type))
|
|
1317 {
|
|
1318 /* If we still have enough registers to pass argument, pick up
|
|
1319 next available register number. */
|
|
1320 regno
|
|
1321 = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type);
|
|
1322 return gen_rtx_REG (mode, regno);
|
|
1323 }
|
|
1324
|
|
1325 /* No register available, return NULL_RTX.
|
|
1326 The compiler will use stack to pass argument instead. */
|
|
1327 return NULL_RTX;
|
|
1328 }
|
|
1329
|
|
1330 /* The following is to handle named argument.
|
|
1331 Note that the strategies of TARGET_HARD_FLOAT and !TARGET_HARD_FLOAT
|
|
1332 are different. */
|
|
1333 if (TARGET_HARD_FLOAT)
|
|
1334 {
|
|
1335 /* Currently we have not implemented hard float yet. */
|
|
1336 gcc_unreachable ();
|
|
1337 }
|
|
1338 else
|
|
1339 {
|
|
1340 /* For !TARGET_HARD_FLOAT calling convention, we always use GPR to pass
|
|
1341 argument. Since we allow to pass argument partially in registers,
|
|
1342 we can just return it if there are still registers available. */
|
|
1343 if (NDS32_ARG_PARTIAL_IN_GPR_REG_P (cum->gpr_offset, mode, type))
|
|
1344 {
|
|
1345 /* Pick up the next available register number. */
|
|
1346 regno
|
|
1347 = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type);
|
|
1348 return gen_rtx_REG (mode, regno);
|
|
1349 }
|
|
1350
|
|
1351 }
|
|
1352
|
|
1353 /* No register available, return NULL_RTX.
|
|
1354 The compiler will use stack to pass argument instead. */
|
|
1355 return NULL_RTX;
|
|
1356 }
|
|
1357
|
|
1358 static bool
|
|
1359 nds32_must_pass_in_stack (machine_mode mode, const_tree type)
|
|
1360 {
|
|
1361 /* Return true if a type must be passed in memory.
|
|
1362 If it is NOT using hard float abi, small aggregates can be
|
|
1363 passed in a register even we are calling a variadic function.
|
|
1364 So there is no need to take padding into consideration. */
|
|
1365 if (TARGET_HARD_FLOAT)
|
|
1366 return must_pass_in_stack_var_size_or_pad (mode, type);
|
|
1367 else
|
|
1368 return must_pass_in_stack_var_size (mode, type);
|
|
1369 }
|
|
1370
|
|
1371 static int
|
|
1372 nds32_arg_partial_bytes (cumulative_args_t ca, machine_mode mode,
|
|
1373 tree type, bool named ATTRIBUTE_UNUSED)
|
|
1374 {
|
|
1375 /* Returns the number of bytes at the beginning of an argument that
|
|
1376 must be put in registers. The value must be zero for arguments that are
|
|
1377 passed entirely in registers or that are entirely pushed on the stack.
|
|
1378 Besides, TARGET_FUNCTION_ARG for these arguments should return the
|
|
1379 first register to be used by the caller for this argument. */
|
|
1380 unsigned int needed_reg_count;
|
|
1381 unsigned int remaining_reg_count;
|
|
1382 CUMULATIVE_ARGS *cum;
|
|
1383
|
|
1384 cum = get_cumulative_args (ca);
|
|
1385
|
|
1386 /* Under hard float abi, we better have argument entirely passed in
|
|
1387 registers or pushed on the stack so that we can reduce the complexity
|
|
1388 of dealing with cum->gpr_offset and cum->fpr_offset. */
|
|
1389 if (TARGET_HARD_FLOAT)
|
|
1390 return 0;
|
|
1391
|
|
1392 /* If we have already runned out of argument registers, return zero
|
|
1393 so that the argument will be entirely pushed on the stack. */
|
|
1394 if (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
|
|
1395 >= NDS32_GPR_ARG_FIRST_REGNUM + NDS32_MAX_GPR_REGS_FOR_ARGS)
|
|
1396 return 0;
|
|
1397
|
|
1398 /* Calculate how many registers do we need for this argument. */
|
|
1399 needed_reg_count = NDS32_NEED_N_REGS_FOR_ARG (mode, type);
|
|
1400
|
|
1401 /* Calculate how many argument registers have left for passing argument.
|
|
1402 Note that we should count it from next available register number. */
|
|
1403 remaining_reg_count
|
|
1404 = NDS32_MAX_GPR_REGS_FOR_ARGS
|
|
1405 - (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
|
|
1406 - NDS32_GPR_ARG_FIRST_REGNUM);
|
|
1407
|
|
1408 /* Note that we have to return the nubmer of bytes, not registers count. */
|
|
1409 if (needed_reg_count > remaining_reg_count)
|
|
1410 return remaining_reg_count * UNITS_PER_WORD;
|
|
1411
|
|
1412 return 0;
|
|
1413 }
|
|
1414
|
|
1415 static void
|
|
1416 nds32_function_arg_advance (cumulative_args_t ca, machine_mode mode,
|
|
1417 const_tree type, bool named)
|
|
1418 {
|
|
1419 machine_mode sub_mode;
|
|
1420 CUMULATIVE_ARGS *cum = get_cumulative_args (ca);
|
|
1421
|
|
1422 if (named)
|
|
1423 {
|
|
1424 /* We need to further check TYPE and MODE so that we can determine
|
|
1425 which kind of register we shall advance. */
|
|
1426 if (type && TREE_CODE (type) == COMPLEX_TYPE)
|
|
1427 sub_mode = TYPE_MODE (TREE_TYPE (type));
|
|
1428 else
|
|
1429 sub_mode = mode;
|
|
1430
|
|
1431 /* Under hard float abi, we may advance FPR registers. */
|
|
1432 if (TARGET_HARD_FLOAT && GET_MODE_CLASS (sub_mode) == MODE_FLOAT)
|
|
1433 {
|
|
1434 /* Currently we have not implemented hard float yet. */
|
|
1435 gcc_unreachable ();
|
|
1436 }
|
|
1437 else
|
|
1438 {
|
|
1439 cum->gpr_offset
|
|
1440 = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
|
|
1441 - NDS32_GPR_ARG_FIRST_REGNUM
|
|
1442 + NDS32_NEED_N_REGS_FOR_ARG (mode, type);
|
|
1443 }
|
|
1444 }
|
|
1445 else
|
|
1446 {
|
|
1447 /* If this nameless argument is NOT under TARGET_HARD_FLOAT,
|
|
1448 we can advance next register as well so that caller is
|
|
1449 able to pass arguments in registers and callee must be
|
|
1450 in charge of pushing all of them into stack. */
|
|
1451 if (!TARGET_HARD_FLOAT)
|
|
1452 {
|
|
1453 cum->gpr_offset
|
|
1454 = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
|
|
1455 - NDS32_GPR_ARG_FIRST_REGNUM
|
|
1456 + NDS32_NEED_N_REGS_FOR_ARG (mode, type);
|
|
1457 }
|
|
1458 }
|
|
1459 }
|
|
1460
|
|
1461 static unsigned int
|
|
1462 nds32_function_arg_boundary (machine_mode mode, const_tree type)
|
|
1463 {
|
|
1464 return (nds32_needs_double_word_align (mode, type)
|
|
1465 ? NDS32_DOUBLE_WORD_ALIGNMENT
|
|
1466 : PARM_BOUNDARY);
|
|
1467 }
|
|
1468
|
|
1469 /* -- How Scalar Function Values Are Returned. */
|
|
1470
|
|
1471 static rtx
|
|
1472 nds32_function_value (const_tree ret_type,
|
|
1473 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
|
|
1474 bool outgoing ATTRIBUTE_UNUSED)
|
|
1475 {
|
|
1476 machine_mode mode;
|
|
1477 int unsignedp;
|
|
1478
|
|
1479 mode = TYPE_MODE (ret_type);
|
|
1480 unsignedp = TYPE_UNSIGNED (ret_type);
|
|
1481
|
|
1482 mode = promote_mode (ret_type, mode, &unsignedp);
|
|
1483
|
|
1484 return gen_rtx_REG (mode, NDS32_GPR_RET_FIRST_REGNUM);
|
|
1485 }
|
|
1486
|
|
1487 static rtx
|
|
1488 nds32_libcall_value (machine_mode mode,
|
|
1489 const_rtx fun ATTRIBUTE_UNUSED)
|
|
1490 {
|
|
1491 return gen_rtx_REG (mode, NDS32_GPR_RET_FIRST_REGNUM);
|
|
1492 }
|
|
1493
|
|
1494 static bool
|
|
1495 nds32_function_value_regno_p (const unsigned int regno)
|
|
1496 {
|
|
1497 return (regno == NDS32_GPR_RET_FIRST_REGNUM);
|
|
1498 }
|
|
1499
|
|
1500 /* -- Function Entry and Exit. */
|
|
1501
|
|
1502 /* The content produced from this function
|
|
1503 will be placed before prologue body. */
|
|
1504 static void
|
|
1505 nds32_asm_function_prologue (FILE *file)
|
|
1506 {
|
|
1507 int r;
|
|
1508 const char *func_name;
|
|
1509 tree attrs;
|
|
1510 tree name;
|
|
1511
|
|
1512 /* All stack frame information is supposed to be
|
|
1513 already computed when expanding prologue.
|
|
1514 The result is in cfun->machine.
|
|
1515 DO NOT call nds32_compute_stack_frame() here
|
|
1516 because it may corrupt the essential information. */
|
|
1517
|
|
1518 fprintf (file, "\t! BEGIN PROLOGUE\n");
|
|
1519 fprintf (file, "\t! fp needed: %d\n", frame_pointer_needed);
|
|
1520 fprintf (file, "\t! pretend_args: %d\n", cfun->machine->va_args_size);
|
|
1521 fprintf (file, "\t! local_size: %d\n", cfun->machine->local_size);
|
|
1522 fprintf (file, "\t! out_args_size: %d\n", cfun->machine->out_args_size);
|
|
1523
|
|
1524 /* Use df_regs_ever_live_p() to detect if the register
|
|
1525 is ever used in the current function. */
|
|
1526 fprintf (file, "\t! registers ever_live: ");
|
|
1527 for (r = 0; r < 32; r++)
|
|
1528 {
|
|
1529 if (df_regs_ever_live_p (r))
|
|
1530 fprintf (file, "%s, ", reg_names[r]);
|
|
1531 }
|
|
1532 fputc ('\n', file);
|
|
1533
|
|
1534 /* Display the attributes of this function. */
|
|
1535 fprintf (file, "\t! function attributes: ");
|
|
1536 /* Get the attributes tree list.
|
|
1537 Note that GCC builds attributes list with reverse order. */
|
|
1538 attrs = DECL_ATTRIBUTES (current_function_decl);
|
|
1539
|
|
1540 /* If there is no any attribute, print out "None". */
|
|
1541 if (!attrs)
|
|
1542 fprintf (file, "None");
|
|
1543
|
|
1544 /* If there are some attributes, try if we need to
|
|
1545 construct isr vector information. */
|
|
1546 func_name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
|
|
1547 nds32_construct_isr_vectors_information (attrs, func_name);
|
|
1548
|
|
1549 /* Display all attributes of this function. */
|
|
1550 while (attrs)
|
|
1551 {
|
|
1552 name = TREE_PURPOSE (attrs);
|
|
1553 fprintf (file, "%s ", IDENTIFIER_POINTER (name));
|
|
1554
|
|
1555 /* Pick up the next attribute. */
|
|
1556 attrs = TREE_CHAIN (attrs);
|
|
1557 }
|
|
1558 fputc ('\n', file);
|
|
1559 }
|
|
1560
|
|
1561 /* After rtl prologue has been expanded, this function is used. */
|
|
1562 static void
|
|
1563 nds32_asm_function_end_prologue (FILE *file)
|
|
1564 {
|
|
1565 fprintf (file, "\t! END PROLOGUE\n");
|
|
1566
|
|
1567 /* If frame pointer is NOT needed and -mfp-as-gp is issued,
|
|
1568 we can generate special directive: ".omit_fp_begin"
|
|
1569 to guide linker doing fp-as-gp optimization.
|
|
1570 However, for a naked function, which means
|
|
1571 it should not have prologue/epilogue,
|
|
1572 using fp-as-gp still requires saving $fp by push/pop behavior and
|
|
1573 there is no benefit to use fp-as-gp on such small function.
|
|
1574 So we need to make sure this function is NOT naked as well. */
|
|
1575 if (!frame_pointer_needed
|
|
1576 && !cfun->machine->naked_p
|
|
1577 && cfun->machine->fp_as_gp_p)
|
|
1578 {
|
|
1579 fprintf (file, "\t! ----------------------------------------\n");
|
|
1580 fprintf (file, "\t! Guide linker to do "
|
|
1581 "link time optimization: fp-as-gp\n");
|
|
1582 fprintf (file, "\t! We add one more instruction to "
|
|
1583 "initialize $fp near to $gp location.\n");
|
|
1584 fprintf (file, "\t! If linker fails to use fp-as-gp transformation,\n");
|
|
1585 fprintf (file, "\t! this extra instruction should be "
|
|
1586 "eliminated at link stage.\n");
|
|
1587 fprintf (file, "\t.omit_fp_begin\n");
|
|
1588 fprintf (file, "\tla\t$fp,_FP_BASE_\n");
|
|
1589 fprintf (file, "\t! ----------------------------------------\n");
|
|
1590 }
|
|
1591 }
|
|
1592
|
|
1593 /* Before rtl epilogue has been expanded, this function is used. */
|
|
1594 static void
|
|
1595 nds32_asm_function_begin_epilogue (FILE *file)
|
|
1596 {
|
|
1597 /* If frame pointer is NOT needed and -mfp-as-gp is issued,
|
|
1598 we can generate special directive: ".omit_fp_end"
|
|
1599 to claim fp-as-gp optimization range.
|
|
1600 However, for a naked function,
|
|
1601 which means it should not have prologue/epilogue,
|
|
1602 using fp-as-gp still requires saving $fp by push/pop behavior and
|
|
1603 there is no benefit to use fp-as-gp on such small function.
|
|
1604 So we need to make sure this function is NOT naked as well. */
|
|
1605 if (!frame_pointer_needed
|
|
1606 && !cfun->machine->naked_p
|
|
1607 && cfun->machine->fp_as_gp_p)
|
|
1608 {
|
|
1609 fprintf (file, "\t! ----------------------------------------\n");
|
|
1610 fprintf (file, "\t! Claim the range of fp-as-gp "
|
|
1611 "link time optimization\n");
|
|
1612 fprintf (file, "\t.omit_fp_end\n");
|
|
1613 fprintf (file, "\t! ----------------------------------------\n");
|
|
1614 }
|
|
1615
|
|
1616 fprintf (file, "\t! BEGIN EPILOGUE\n");
|
|
1617 }
|
|
1618
|
|
1619 /* The content produced from this function
|
|
1620 will be placed after epilogue body. */
|
|
1621 static void
|
|
1622 nds32_asm_function_epilogue (FILE *file)
|
|
1623 {
|
|
1624 fprintf (file, "\t! END EPILOGUE\n");
|
|
1625 }
|
|
1626
|
|
1627 static void
|
|
1628 nds32_asm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
|
|
1629 HOST_WIDE_INT delta,
|
|
1630 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
|
|
1631 tree function)
|
|
1632 {
|
|
1633 int this_regno;
|
|
1634
|
|
1635 /* Make sure unwind info is emitted for the thunk if needed. */
|
|
1636 final_start_function (emit_barrier (), file, 1);
|
|
1637
|
|
1638 this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)
|
|
1639 ? 1
|
|
1640 : 0);
|
|
1641
|
|
1642 if (delta != 0)
|
|
1643 {
|
|
1644 if (satisfies_constraint_Is15 (GEN_INT (delta)))
|
|
1645 {
|
|
1646 fprintf (file, "\taddi\t$r%d, $r%d, %ld\n",
|
|
1647 this_regno, this_regno, delta);
|
|
1648 }
|
|
1649 else if (satisfies_constraint_Is20 (GEN_INT (delta)))
|
|
1650 {
|
|
1651 fprintf (file, "\tmovi\t$ta, %ld\n", delta);
|
|
1652 fprintf (file, "\tadd\t$r%d, $r%d, $ta\n", this_regno, this_regno);
|
|
1653 }
|
|
1654 else
|
|
1655 {
|
|
1656 fprintf (file, "\tsethi\t$ta, hi20(%ld)\n", delta);
|
|
1657 fprintf (file, "\tori\t$ta, $ta, lo12(%ld)\n", delta);
|
|
1658 fprintf (file, "\tadd\t$r%d, $r%d, $ta\n", this_regno, this_regno);
|
|
1659 }
|
|
1660 }
|
|
1661
|
|
1662 fprintf (file, "\tb\t");
|
|
1663 assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
|
|
1664 fprintf (file, "\n");
|
|
1665
|
|
1666 final_end_function ();
|
|
1667 }
|
|
1668
|
|
1669 /* -- Permitting tail calls. */
|
|
1670
|
|
1671 /* Determine whether we need to enable warning for function return check. */
|
|
1672 static bool
|
|
1673 nds32_warn_func_return (tree decl)
|
|
1674 {
|
|
1675 /* Naked functions are implemented entirely in assembly, including the
|
|
1676 return sequence, so suppress warnings about this. */
|
|
1677 return !nds32_naked_function_p (decl);
|
|
1678 }
|
|
1679
|
|
1680
|
|
1681 /* Implementing the Varargs Macros. */
|
|
1682
|
|
1683 static void
|
|
1684 nds32_setup_incoming_varargs (cumulative_args_t ca,
|
|
1685 machine_mode mode,
|
|
1686 tree type,
|
|
1687 int *pretend_args_size,
|
|
1688 int second_time ATTRIBUTE_UNUSED)
|
|
1689 {
|
|
1690 unsigned int total_args_regs;
|
|
1691 unsigned int num_of_used_regs;
|
|
1692 unsigned int remaining_reg_count;
|
|
1693 CUMULATIVE_ARGS *cum;
|
|
1694
|
|
1695 /* If we are under hard float abi, we do not need to set *pretend_args_size.
|
|
1696 So that all nameless arguments are pushed by caller and all situation
|
|
1697 can be handled by GCC itself. */
|
|
1698 if (TARGET_HARD_FLOAT)
|
|
1699 return;
|
|
1700
|
|
1701 /* We are using NDS32_MAX_GPR_REGS_FOR_ARGS registers,
|
|
1702 counting from NDS32_GPR_ARG_FIRST_REGNUM, for saving incoming arguments.
|
|
1703 However, for nameless(anonymous) arguments, we should push them on the
|
|
1704 stack so that all the nameless arguments appear to have been passed
|
|
1705 consecutively in the memory for accessing. Hence, we need to check and
|
|
1706 exclude the registers that are used for named arguments. */
|
|
1707
|
|
1708 cum = get_cumulative_args (ca);
|
|
1709
|
|
1710 /* The MODE and TYPE describe the last argument.
|
|
1711 We need those information to determine the remaining registers
|
|
1712 for varargs. */
|
|
1713 total_args_regs
|
|
1714 = NDS32_MAX_GPR_REGS_FOR_ARGS + NDS32_GPR_ARG_FIRST_REGNUM;
|
|
1715 num_of_used_regs
|
|
1716 = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type)
|
|
1717 + NDS32_NEED_N_REGS_FOR_ARG (mode, type);
|
|
1718
|
|
1719 remaining_reg_count = total_args_regs - num_of_used_regs;
|
|
1720 *pretend_args_size = remaining_reg_count * UNITS_PER_WORD;
|
|
1721
|
|
1722 return;
|
|
1723 }
|
|
1724
|
|
1725 static bool
|
|
1726 nds32_strict_argument_naming (cumulative_args_t ca ATTRIBUTE_UNUSED)
|
|
1727 {
|
|
1728 /* If this hook returns true, the named argument of FUNCTION_ARG is always
|
|
1729 true for named arguments, and false for unnamed arguments. */
|
|
1730 return true;
|
|
1731 }
|
|
1732
|
|
1733
|
|
1734 /* Trampolines for Nested Functions. */
|
|
1735
|
|
1736 static void
|
|
1737 nds32_asm_trampoline_template (FILE *f)
|
|
1738 {
|
|
1739 if (TARGET_REDUCED_REGS)
|
|
1740 {
|
|
1741 /* Trampoline is not supported on reduced-set registers yet. */
|
|
1742 sorry ("a nested function is not supported for reduced registers");
|
|
1743 }
|
|
1744 else
|
|
1745 {
|
|
1746 asm_fprintf (f, "\t! Trampoline code template\n");
|
|
1747 asm_fprintf (f, "\t! This code fragment will be copied "
|
|
1748 "into stack on demand\n");
|
|
1749
|
|
1750 asm_fprintf (f, "\tmfusr\t$r16,$pc\n");
|
|
1751 asm_fprintf (f, "\tlwi\t$r15,[$r16 + 20] "
|
|
1752 "! load nested function address\n");
|
|
1753 asm_fprintf (f, "\tlwi\t$r16,[$r16 + 16] "
|
|
1754 "! load chain_value\n");
|
|
1755 asm_fprintf (f, "\tjr\t$r15\n");
|
|
1756 }
|
|
1757
|
|
1758 /* Preserve space ($pc + 16) for saving chain_value,
|
|
1759 nds32_trampoline_init will fill the value in this slot. */
|
|
1760 asm_fprintf (f, "\t! space for saving chain_value\n");
|
|
1761 assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
|
|
1762
|
|
1763 /* Preserve space ($pc + 20) for saving nested function address,
|
|
1764 nds32_trampoline_init will fill the value in this slot. */
|
|
1765 asm_fprintf (f, "\t! space for saving nested function address\n");
|
|
1766 assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
|
|
1767 }
|
|
1768
|
|
1769 /* Emit RTL insns to initialize the variable parts of a trampoline. */
|
|
1770 static void
|
|
1771 nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
|
|
1772 {
|
|
1773 int i;
|
|
1774
|
|
1775 /* Nested function address. */
|
|
1776 rtx fnaddr;
|
|
1777 /* The memory rtx that is going to
|
|
1778 be filled with chain_value. */
|
|
1779 rtx chain_value_mem;
|
|
1780 /* The memory rtx that is going to
|
|
1781 be filled with nested function address. */
|
|
1782 rtx nested_func_mem;
|
|
1783
|
|
1784 /* Start address of trampoline code in stack, for doing cache sync. */
|
|
1785 rtx sync_cache_addr;
|
|
1786 /* Temporary register for sync instruction. */
|
|
1787 rtx tmp_reg;
|
|
1788 /* Instruction-cache sync instruction,
|
|
1789 requesting an argument as starting address. */
|
|
1790 rtx isync_insn;
|
|
1791 /* For convenience reason of doing comparison. */
|
|
1792 int tramp_align_in_bytes;
|
|
1793
|
|
1794 /* Trampoline is not supported on reduced-set registers yet. */
|
|
1795 if (TARGET_REDUCED_REGS)
|
|
1796 sorry ("a nested function is not supported for reduced registers");
|
|
1797
|
|
1798 /* STEP 1: Copy trampoline code template into stack,
|
|
1799 fill up essential data into stack. */
|
|
1800
|
|
1801 /* Extract nested function address rtx. */
|
|
1802 fnaddr = XEXP (DECL_RTL (fndecl), 0);
|
|
1803
|
|
1804 /* m_tramp is memory rtx that is going to be filled with trampoline code.
|
|
1805 We have nds32_asm_trampoline_template() to emit template pattern. */
|
|
1806 emit_block_move (m_tramp, assemble_trampoline_template (),
|
|
1807 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
|
|
1808
|
|
1809 /* After copying trampoline code into stack,
|
|
1810 fill chain_value into stack. */
|
|
1811 chain_value_mem = adjust_address (m_tramp, SImode, 16);
|
|
1812 emit_move_insn (chain_value_mem, chain_value);
|
|
1813 /* After copying trampoline code int stack,
|
|
1814 fill nested function address into stack. */
|
|
1815 nested_func_mem = adjust_address (m_tramp, SImode, 20);
|
|
1816 emit_move_insn (nested_func_mem, fnaddr);
|
|
1817
|
|
1818 /* STEP 2: Sync instruction-cache. */
|
|
1819
|
|
1820 /* We have successfully filled trampoline code into stack.
|
|
1821 However, in order to execute code in stack correctly,
|
|
1822 we must sync instruction cache. */
|
|
1823 sync_cache_addr = XEXP (m_tramp, 0);
|
|
1824 tmp_reg = gen_reg_rtx (SImode);
|
|
1825 isync_insn = gen_unspec_volatile_isync (tmp_reg);
|
|
1826
|
|
1827 /* Because nds32_cache_block_size is in bytes,
|
|
1828 we get trampoline alignment in bytes for convenient comparison. */
|
|
1829 tramp_align_in_bytes = TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT;
|
|
1830
|
|
1831 if (tramp_align_in_bytes >= nds32_cache_block_size
|
|
1832 && (tramp_align_in_bytes % nds32_cache_block_size) == 0)
|
|
1833 {
|
|
1834 /* Under this condition, the starting address of trampoline
|
|
1835 must be aligned to the starting address of each cache block
|
|
1836 and we do not have to worry about cross-boundary issue. */
|
|
1837 for (i = 0;
|
|
1838 i < (TRAMPOLINE_SIZE + nds32_cache_block_size - 1)
|
|
1839 / nds32_cache_block_size;
|
|
1840 i++)
|
|
1841 {
|
|
1842 emit_move_insn (tmp_reg,
|
|
1843 plus_constant (Pmode, sync_cache_addr,
|
|
1844 nds32_cache_block_size * i));
|
|
1845 emit_insn (isync_insn);
|
|
1846 }
|
|
1847 }
|
|
1848 else if (TRAMPOLINE_SIZE > nds32_cache_block_size)
|
|
1849 {
|
|
1850 /* The starting address of trampoline code
|
|
1851 may not be aligned to the cache block,
|
|
1852 so the trampoline code may be across two cache block.
|
|
1853 We need to sync the last element, which is 4-byte size,
|
|
1854 of trampoline template. */
|
|
1855 for (i = 0;
|
|
1856 i < (TRAMPOLINE_SIZE + nds32_cache_block_size - 1)
|
|
1857 / nds32_cache_block_size;
|
|
1858 i++)
|
|
1859 {
|
|
1860 emit_move_insn (tmp_reg,
|
|
1861 plus_constant (Pmode, sync_cache_addr,
|
|
1862 nds32_cache_block_size * i));
|
|
1863 emit_insn (isync_insn);
|
|
1864 }
|
|
1865
|
|
1866 /* The last element of trampoline template is 4-byte size. */
|
|
1867 emit_move_insn (tmp_reg,
|
|
1868 plus_constant (Pmode, sync_cache_addr,
|
|
1869 TRAMPOLINE_SIZE - 4));
|
|
1870 emit_insn (isync_insn);
|
|
1871 }
|
|
1872 else
|
|
1873 {
|
|
1874 /* This is the simplest case.
|
|
1875 Because TRAMPOLINE_SIZE is less than or
|
|
1876 equal to nds32_cache_block_size,
|
|
1877 we can just sync start address and
|
|
1878 the last element of trampoline code. */
|
|
1879
|
|
1880 /* Sync starting address of tampoline code. */
|
|
1881 emit_move_insn (tmp_reg, sync_cache_addr);
|
|
1882 emit_insn (isync_insn);
|
|
1883 /* Sync the last element, which is 4-byte size,
|
|
1884 of trampoline template. */
|
|
1885 emit_move_insn (tmp_reg,
|
|
1886 plus_constant (Pmode, sync_cache_addr,
|
|
1887 TRAMPOLINE_SIZE - 4));
|
|
1888 emit_insn (isync_insn);
|
|
1889 }
|
|
1890
|
|
1891 /* Set instruction serialization barrier
|
|
1892 to guarantee the correct operations. */
|
|
1893 emit_insn (gen_unspec_volatile_isb ());
|
|
1894 }
|
|
1895
|
|
1896
|
|
1897 /* Addressing Modes. */
|
|
1898
|
|
1899 static bool
|
|
1900 nds32_legitimate_address_p (machine_mode mode, rtx x, bool strict)
|
|
1901 {
|
|
1902 /* For (mem:DI addr) or (mem:DF addr) case,
|
|
1903 we only allow 'addr' to be [reg], [symbol_ref],
|
|
1904 [const], or [reg + const_int] pattern. */
|
|
1905 if (mode == DImode || mode == DFmode)
|
|
1906 {
|
|
1907 /* Allow [Reg + const_int] addressing mode. */
|
|
1908 if (GET_CODE (x) == PLUS)
|
|
1909 {
|
|
1910 if (nds32_address_register_rtx_p (XEXP (x, 0), strict)
|
|
1911 && nds32_legitimate_index_p (mode, XEXP (x, 1), strict)
|
|
1912 && CONST_INT_P (XEXP (x, 1)))
|
|
1913 return true;
|
|
1914 else if (nds32_address_register_rtx_p (XEXP (x, 1), strict)
|
|
1915 && nds32_legitimate_index_p (mode, XEXP (x, 0), strict)
|
|
1916 && CONST_INT_P (XEXP (x, 0)))
|
|
1917 return true;
|
|
1918 }
|
|
1919
|
|
1920 /* Now check [reg], [symbol_ref], and [const]. */
|
|
1921 if (GET_CODE (x) != REG
|
|
1922 && GET_CODE (x) != SYMBOL_REF
|
|
1923 && GET_CODE (x) != CONST)
|
|
1924 return false;
|
|
1925 }
|
|
1926
|
|
1927 /* Check if 'x' is a valid address. */
|
|
1928 switch (GET_CODE (x))
|
|
1929 {
|
|
1930 case REG:
|
|
1931 /* (mem (reg A)) => [Ra] */
|
|
1932 return nds32_address_register_rtx_p (x, strict);
|
|
1933
|
|
1934 case SYMBOL_REF:
|
|
1935 /* (mem (symbol_ref A)) => [symbol_ref] */
|
|
1936 /* If -mcmodel=large, the 'symbol_ref' is not a valid address
|
|
1937 during or after LRA/reload phase. */
|
|
1938 if (TARGET_CMODEL_LARGE
|
|
1939 && (reload_completed
|
|
1940 || reload_in_progress
|
|
1941 || lra_in_progress))
|
|
1942 return false;
|
|
1943 /* If -mcmodel=medium and the symbol references to rodata section,
|
|
1944 the 'symbol_ref' is not a valid address during or after
|
|
1945 LRA/reload phase. */
|
|
1946 if (TARGET_CMODEL_MEDIUM
|
|
1947 && NDS32_SYMBOL_REF_RODATA_P (x)
|
|
1948 && (reload_completed
|
|
1949 || reload_in_progress
|
|
1950 || lra_in_progress))
|
|
1951 return false;
|
|
1952
|
|
1953 return true;
|
|
1954
|
|
1955 case CONST:
|
|
1956 /* (mem (const (...)))
|
|
1957 => [ + const_addr ], where const_addr = symbol_ref + const_int */
|
|
1958 if (GET_CODE (XEXP (x, 0)) == PLUS)
|
|
1959 {
|
|
1960 rtx plus_op = XEXP (x, 0);
|
|
1961
|
|
1962 rtx op0 = XEXP (plus_op, 0);
|
|
1963 rtx op1 = XEXP (plus_op, 1);
|
|
1964
|
|
1965 if (GET_CODE (op0) == SYMBOL_REF && CONST_INT_P (op1))
|
|
1966 {
|
|
1967 /* Now we see the [ + const_addr ] pattern, but we need
|
|
1968 some further checking. */
|
|
1969 /* If -mcmodel=large, the 'const_addr' is not a valid address
|
|
1970 during or after LRA/reload phase. */
|
|
1971 if (TARGET_CMODEL_LARGE
|
|
1972 && (reload_completed
|
|
1973 || reload_in_progress
|
|
1974 || lra_in_progress))
|
|
1975 return false;
|
|
1976 /* If -mcmodel=medium and the symbol references to rodata section,
|
|
1977 the 'const_addr' is not a valid address during or after
|
|
1978 LRA/reload phase. */
|
|
1979 if (TARGET_CMODEL_MEDIUM
|
|
1980 && NDS32_SYMBOL_REF_RODATA_P (op0)
|
|
1981 && (reload_completed
|
|
1982 || reload_in_progress
|
|
1983 || lra_in_progress))
|
|
1984 return false;
|
|
1985
|
|
1986 /* At this point we can make sure 'const_addr' is a
|
|
1987 valid address. */
|
|
1988 return true;
|
|
1989 }
|
|
1990 }
|
|
1991
|
|
1992 return false;
|
|
1993
|
|
1994 case POST_MODIFY:
|
|
1995 /* (mem (post_modify (reg) (plus (reg) (reg))))
|
|
1996 => [Ra], Rb */
|
|
1997 /* (mem (post_modify (reg) (plus (reg) (const_int))))
|
|
1998 => [Ra], const_int */
|
|
1999 if (GET_CODE (XEXP (x, 0)) == REG
|
|
2000 && GET_CODE (XEXP (x, 1)) == PLUS)
|
|
2001 {
|
|
2002 rtx plus_op = XEXP (x, 1);
|
|
2003
|
|
2004 rtx op0 = XEXP (plus_op, 0);
|
|
2005 rtx op1 = XEXP (plus_op, 1);
|
|
2006
|
|
2007 if (nds32_address_register_rtx_p (op0, strict)
|
|
2008 && nds32_legitimate_index_p (mode, op1, strict))
|
|
2009 return true;
|
|
2010 else
|
|
2011 return false;
|
|
2012 }
|
|
2013
|
|
2014 return false;
|
|
2015
|
|
2016 case POST_INC:
|
|
2017 case POST_DEC:
|
|
2018 /* (mem (post_inc reg)) => [Ra], 1/2/4 */
|
|
2019 /* (mem (post_dec reg)) => [Ra], -1/-2/-4 */
|
|
2020 /* The 1/2/4 or -1/-2/-4 have been displayed in nds32.md.
|
|
2021 We only need to deal with register Ra. */
|
|
2022 if (nds32_address_register_rtx_p (XEXP (x, 0), strict))
|
|
2023 return true;
|
|
2024 else
|
|
2025 return false;
|
|
2026
|
|
2027 case PLUS:
|
|
2028 /* (mem (plus reg const_int))
|
|
2029 => [Ra + imm] */
|
|
2030 /* (mem (plus reg reg))
|
|
2031 => [Ra + Rb] */
|
|
2032 /* (mem (plus (mult reg const_int) reg))
|
|
2033 => [Ra + Rb << sv] */
|
|
2034 if (nds32_address_register_rtx_p (XEXP (x, 0), strict)
|
|
2035 && nds32_legitimate_index_p (mode, XEXP (x, 1), strict))
|
|
2036 return true;
|
|
2037 else if (nds32_address_register_rtx_p (XEXP (x, 1), strict)
|
|
2038 && nds32_legitimate_index_p (mode, XEXP (x, 0), strict))
|
|
2039 return true;
|
|
2040 else
|
|
2041 return false;
|
|
2042
|
|
2043 case LO_SUM:
|
|
2044 /* (mem (lo_sum (reg) (symbol_ref))) */
|
|
2045 /* (mem (lo_sum (reg) (const))) */
|
|
2046 gcc_assert (REG_P (XEXP (x, 0)));
|
|
2047 if (GET_CODE (XEXP (x, 1)) == SYMBOL_REF
|
|
2048 || GET_CODE (XEXP (x, 1)) == CONST)
|
|
2049 return nds32_legitimate_address_p (mode, XEXP (x, 1), strict);
|
|
2050 else
|
|
2051 return false;
|
|
2052
|
|
2053 default:
|
|
2054 return false;
|
|
2055 }
|
|
2056 }
|
|
2057
|
|
2058
|
|
2059 /* Describing Relative Costs of Operations. */
|
|
2060
|
|
2061 static int
|
|
2062 nds32_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
|
|
2063 reg_class_t from,
|
|
2064 reg_class_t to)
|
|
2065 {
|
|
2066 if (from == HIGH_REGS || to == HIGH_REGS)
|
|
2067 return 6;
|
|
2068
|
|
2069 return 2;
|
|
2070 }
|
|
2071
|
|
2072 static int
|
|
2073 nds32_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
|
|
2074 reg_class_t rclass ATTRIBUTE_UNUSED,
|
|
2075 bool in ATTRIBUTE_UNUSED)
|
|
2076 {
|
|
2077 return 8;
|
|
2078 }
|
|
2079
|
|
2080 /* This target hook describes the relative costs of RTL expressions.
|
|
2081 Return 'true' when all subexpressions of x have been processed.
|
|
2082 Return 'false' to sum the costs of sub-rtx, plus cost of this operation.
|
|
2083 Refer to gcc/rtlanal.c for more information. */
|
|
2084 static bool
|
|
2085 nds32_rtx_costs (rtx x,
|
|
2086 machine_mode mode,
|
|
2087 int outer_code,
|
|
2088 int opno,
|
|
2089 int *total,
|
|
2090 bool speed)
|
|
2091 {
|
|
2092 return nds32_rtx_costs_impl (x, mode, outer_code, opno, total, speed);
|
|
2093 }
|
|
2094
|
|
2095 static int
|
|
2096 nds32_address_cost (rtx address,
|
|
2097 machine_mode mode,
|
|
2098 addr_space_t as,
|
|
2099 bool speed)
|
|
2100 {
|
|
2101 return nds32_address_cost_impl (address, mode, as, speed);
|
|
2102 }
|
|
2103
|
|
2104
|
|
2105 /* Dividing the Output into Sections (Texts, Data, . . . ). */
|
|
2106
|
|
2107 /* If references to a symbol or a constant must be treated differently
|
|
2108 depending on something about the variable or function named by the symbol
|
|
2109 (such as what section it is in), we use this hook to store flags
|
|
2110 in symbol_ref rtx. */
|
|
2111 static void
|
|
2112 nds32_encode_section_info (tree decl, rtx rtl, int new_decl_p)
|
|
2113 {
|
|
2114 default_encode_section_info (decl, rtl, new_decl_p);
|
|
2115
|
|
2116 /* For the memory rtx, if it references to rodata section, we can store
|
|
2117 NDS32_SYMBOL_FLAG_RODATA flag into symbol_ref rtx so that the
|
|
2118 nds32_legitimate_address_p() can determine how to treat such symbol_ref
|
|
2119 based on -mcmodel=X and this information. */
|
|
2120 if (MEM_P (rtl) && MEM_READONLY_P (rtl))
|
|
2121 {
|
|
2122 rtx addr = XEXP (rtl, 0);
|
|
2123
|
|
2124 if (GET_CODE (addr) == SYMBOL_REF)
|
|
2125 {
|
|
2126 /* For (mem (symbol_ref X)) case. */
|
|
2127 SYMBOL_REF_FLAGS (addr) |= NDS32_SYMBOL_FLAG_RODATA;
|
|
2128 }
|
|
2129 else if (GET_CODE (addr) == CONST
|
|
2130 && GET_CODE (XEXP (addr, 0)) == PLUS)
|
|
2131 {
|
|
2132 /* For (mem (const (plus (symbol_ref X) (const_int N)))) case. */
|
|
2133 rtx plus_op = XEXP (addr, 0);
|
|
2134 rtx op0 = XEXP (plus_op, 0);
|
|
2135 rtx op1 = XEXP (plus_op, 1);
|
|
2136
|
|
2137 if (GET_CODE (op0) == SYMBOL_REF && CONST_INT_P (op1))
|
|
2138 SYMBOL_REF_FLAGS (op0) |= NDS32_SYMBOL_FLAG_RODATA;
|
|
2139 }
|
|
2140 }
|
|
2141 }
|
|
2142
|
|
2143
|
|
2144 /* Defining the Output Assembler Language. */
|
|
2145
|
|
2146 /* -- The Overall Framework of an Assembler File. */
|
|
2147
|
|
2148 static void
|
|
2149 nds32_asm_file_start (void)
|
|
2150 {
|
|
2151 default_file_start ();
|
|
2152
|
|
2153 /* Tell assembler which ABI we are using. */
|
|
2154 fprintf (asm_out_file, "\t! ABI version\n");
|
|
2155 fprintf (asm_out_file, "\t.abi_2\n");
|
|
2156
|
|
2157 /* Tell assembler that this asm code is generated by compiler. */
|
|
2158 fprintf (asm_out_file, "\t! This asm file is generated by compiler\n");
|
|
2159 fprintf (asm_out_file, "\t.flag\tverbatim\n");
|
|
2160 /* Give assembler the size of each vector for interrupt handler. */
|
|
2161 fprintf (asm_out_file, "\t! This vector size directive is required "
|
|
2162 "for checking inconsistency on interrupt handler\n");
|
|
2163 fprintf (asm_out_file, "\t.vec_size\t%d\n", nds32_isr_vector_size);
|
|
2164
|
|
2165 fprintf (asm_out_file, "\t! ------------------------------------\n");
|
|
2166
|
|
2167 if (TARGET_ISA_V2)
|
|
2168 fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V2");
|
|
2169 if (TARGET_ISA_V3)
|
|
2170 fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V3");
|
|
2171 if (TARGET_ISA_V3M)
|
|
2172 fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V3M");
|
|
2173
|
|
2174 if (TARGET_CMODEL_SMALL)
|
|
2175 fprintf (asm_out_file, "\t! Code model\t\t: %s\n", "SMALL");
|
|
2176 if (TARGET_CMODEL_MEDIUM)
|
|
2177 fprintf (asm_out_file, "\t! Code model\t\t: %s\n", "MEDIUM");
|
|
2178 if (TARGET_CMODEL_LARGE)
|
|
2179 fprintf (asm_out_file, "\t! Code model\t\t: %s\n", "LARGE");
|
|
2180
|
|
2181 fprintf (asm_out_file, "\t! Endian setting\t: %s\n",
|
|
2182 ((TARGET_BIG_ENDIAN) ? "big-endian"
|
|
2183 : "little-endian"));
|
|
2184
|
|
2185 fprintf (asm_out_file, "\t! ------------------------------------\n");
|
|
2186
|
|
2187 fprintf (asm_out_file, "\t! Use conditional move\t\t: %s\n",
|
|
2188 ((TARGET_CMOV) ? "Yes"
|
|
2189 : "No"));
|
|
2190 fprintf (asm_out_file, "\t! Use performance extension\t: %s\n",
|
|
2191 ((TARGET_PERF_EXT) ? "Yes"
|
|
2192 : "No"));
|
|
2193
|
|
2194 fprintf (asm_out_file, "\t! ------------------------------------\n");
|
|
2195
|
|
2196 fprintf (asm_out_file, "\t! V3PUSH instructions\t: %s\n",
|
|
2197 ((TARGET_V3PUSH) ? "Yes"
|
|
2198 : "No"));
|
|
2199 fprintf (asm_out_file, "\t! 16-bit instructions\t: %s\n",
|
|
2200 ((TARGET_16_BIT) ? "Yes"
|
|
2201 : "No"));
|
|
2202 fprintf (asm_out_file, "\t! Reduced registers set\t: %s\n",
|
|
2203 ((TARGET_REDUCED_REGS) ? "Yes"
|
|
2204 : "No"));
|
|
2205
|
|
2206 fprintf (asm_out_file, "\t! ------------------------------------\n");
|
|
2207
|
|
2208 if (optimize_size)
|
|
2209 fprintf (asm_out_file, "\t! Optimization level\t: -Os\n");
|
|
2210 else
|
|
2211 fprintf (asm_out_file, "\t! Optimization level\t: -O%d\n", optimize);
|
|
2212
|
|
2213 fprintf (asm_out_file, "\t! ------------------------------------\n");
|
|
2214
|
|
2215 fprintf (asm_out_file, "\t! Cache block size\t: %d\n",
|
|
2216 nds32_cache_block_size);
|
|
2217
|
|
2218 fprintf (asm_out_file, "\t! ------------------------------------\n");
|
|
2219
|
|
2220 nds32_asm_file_start_for_isr ();
|
|
2221 }
|
|
2222
|
|
2223 static void
|
|
2224 nds32_asm_file_end (void)
|
|
2225 {
|
|
2226 nds32_asm_file_end_for_isr ();
|
|
2227
|
|
2228 fprintf (asm_out_file, "\t! ------------------------------------\n");
|
|
2229 }
|
|
2230
|
|
2231 /* -- Output and Generation of Labels. */
|
|
2232
|
|
2233 static void
|
|
2234 nds32_asm_globalize_label (FILE *stream, const char *name)
|
|
2235 {
|
|
2236 fputs ("\t.global\t", stream);
|
|
2237 assemble_name (stream, name);
|
|
2238 fputs ("\n", stream);
|
|
2239 }
|
|
2240
|
|
2241 /* -- Output of Assembler Instructions. */
|
|
2242
|
|
2243 static void
|
|
2244 nds32_print_operand (FILE *stream, rtx x, int code)
|
|
2245 {
|
|
2246 int op_value;
|
|
2247
|
|
2248 switch (code)
|
|
2249 {
|
|
2250 case 0 :
|
|
2251 /* Do nothing special. */
|
|
2252 break;
|
|
2253
|
|
2254 case 'V':
|
|
2255 /* 'x' is supposed to be CONST_INT, get the value. */
|
|
2256 gcc_assert (CONST_INT_P (x));
|
|
2257 op_value = INTVAL (x);
|
|
2258
|
|
2259 /* According to the Andes architecture,
|
|
2260 the system/user register index range is 0 ~ 1023.
|
|
2261 In order to avoid conflict between user-specified-integer value
|
|
2262 and enum-specified-register value,
|
|
2263 the 'enum nds32_intrinsic_registers' value
|
|
2264 in nds32_intrinsic.h starts from 1024. */
|
|
2265 if (op_value < 1024 && op_value >= 0)
|
|
2266 {
|
|
2267 /* If user gives integer value directly (0~1023),
|
|
2268 we just print out the value. */
|
|
2269 fprintf (stream, "%d", op_value);
|
|
2270 }
|
|
2271 else if (op_value < 0
|
|
2272 || op_value >= ((int) ARRAY_SIZE (nds32_intrinsic_register_names)
|
|
2273 + 1024))
|
|
2274 {
|
|
2275 /* The enum index value for array size is out of range. */
|
|
2276 error ("intrinsic register index is out of range");
|
|
2277 }
|
|
2278 else
|
|
2279 {
|
|
2280 /* If user applies normal way with __NDS32_REG_XXX__ enum data,
|
|
2281 we can print out register name. Remember to substract 1024. */
|
|
2282 fprintf (stream, "%s",
|
|
2283 nds32_intrinsic_register_names[op_value - 1024]);
|
|
2284 }
|
|
2285
|
|
2286 /* No need to handle following process, so return immediately. */
|
|
2287 return;
|
|
2288
|
|
2289 default :
|
|
2290 /* Unknown flag. */
|
|
2291 output_operand_lossage ("invalid operand output code");
|
|
2292 break;
|
|
2293 }
|
|
2294
|
|
2295 switch (GET_CODE (x))
|
|
2296 {
|
|
2297 case LABEL_REF:
|
|
2298 case SYMBOL_REF:
|
|
2299 output_addr_const (stream, x);
|
|
2300 break;
|
|
2301
|
|
2302 case REG:
|
|
2303 /* Forbid using static chain register ($r16)
|
|
2304 on reduced-set registers configuration. */
|
|
2305 if (TARGET_REDUCED_REGS
|
|
2306 && REGNO (x) == STATIC_CHAIN_REGNUM)
|
|
2307 sorry ("a nested function is not supported for reduced registers");
|
|
2308
|
|
2309 /* Normal cases, print out register name. */
|
|
2310 fputs (reg_names[REGNO (x)], stream);
|
|
2311 break;
|
|
2312
|
|
2313 case MEM:
|
|
2314 output_address (GET_MODE (x), XEXP (x, 0));
|
|
2315 break;
|
|
2316
|
|
2317 case CODE_LABEL:
|
|
2318 case CONST_INT:
|
|
2319 case CONST:
|
|
2320 output_addr_const (stream, x);
|
|
2321 break;
|
|
2322
|
|
2323 default:
|
|
2324 /* Generally, output_addr_const () is able to handle most cases.
|
|
2325 We want to see what CODE could appear,
|
|
2326 so we use gcc_unreachable() to stop it. */
|
|
2327 debug_rtx (x);
|
|
2328 gcc_unreachable ();
|
|
2329 break;
|
|
2330 }
|
|
2331 }
|
|
2332
|
|
2333 static void
|
|
2334 nds32_print_operand_address (FILE *stream, machine_mode /*mode*/, rtx x)
|
|
2335 {
|
|
2336 rtx op0, op1;
|
|
2337
|
|
2338 switch (GET_CODE (x))
|
|
2339 {
|
|
2340 case SYMBOL_REF:
|
|
2341 case CONST:
|
|
2342 /* [ + symbol_ref] */
|
|
2343 /* [ + const_addr], where const_addr = symbol_ref + const_int */
|
|
2344 fputs ("[ + ", stream);
|
|
2345 output_addr_const (stream, x);
|
|
2346 fputs ("]", stream);
|
|
2347 break;
|
|
2348
|
|
2349 case REG:
|
|
2350 /* Forbid using static chain register ($r16)
|
|
2351 on reduced-set registers configuration. */
|
|
2352 if (TARGET_REDUCED_REGS
|
|
2353 && REGNO (x) == STATIC_CHAIN_REGNUM)
|
|
2354 sorry ("a nested function is not supported for reduced registers");
|
|
2355
|
|
2356 /* [Ra] */
|
|
2357 fprintf (stream, "[%s]", reg_names[REGNO (x)]);
|
|
2358 break;
|
|
2359
|
|
2360 case PLUS:
|
|
2361 op0 = XEXP (x, 0);
|
|
2362 op1 = XEXP (x, 1);
|
|
2363
|
|
2364 /* Checking op0, forbid using static chain register ($r16)
|
|
2365 on reduced-set registers configuration. */
|
|
2366 if (TARGET_REDUCED_REGS
|
|
2367 && REG_P (op0)
|
|
2368 && REGNO (op0) == STATIC_CHAIN_REGNUM)
|
|
2369 sorry ("a nested function is not supported for reduced registers");
|
|
2370 /* Checking op1, forbid using static chain register ($r16)
|
|
2371 on reduced-set registers configuration. */
|
|
2372 if (TARGET_REDUCED_REGS
|
|
2373 && REG_P (op1)
|
|
2374 && REGNO (op1) == STATIC_CHAIN_REGNUM)
|
|
2375 sorry ("a nested function is not supported for reduced registers");
|
|
2376
|
|
2377 if (REG_P (op0) && CONST_INT_P (op1))
|
|
2378 {
|
|
2379 /* [Ra + imm] */
|
|
2380 fprintf (stream, "[%s + (%d)]",
|
|
2381 reg_names[REGNO (op0)], (int)INTVAL (op1));
|
|
2382 }
|
|
2383 else if (REG_P (op0) && REG_P (op1))
|
|
2384 {
|
|
2385 /* [Ra + Rb] */
|
|
2386 fprintf (stream, "[%s + %s]",
|
|
2387 reg_names[REGNO (op0)], reg_names[REGNO (op1)]);
|
|
2388 }
|
|
2389 else if (GET_CODE (op0) == MULT && REG_P (op1))
|
|
2390 {
|
|
2391 /* [Ra + Rb << sv]
|
|
2392 From observation, the pattern looks like:
|
|
2393 (plus:SI (mult:SI (reg:SI 58)
|
|
2394 (const_int 4 [0x4]))
|
|
2395 (reg/f:SI 57)) */
|
|
2396 int sv;
|
|
2397
|
|
2398 /* We need to set sv to output shift value. */
|
|
2399 if (INTVAL (XEXP (op0, 1)) == 1)
|
|
2400 sv = 0;
|
|
2401 else if (INTVAL (XEXP (op0, 1)) == 2)
|
|
2402 sv = 1;
|
|
2403 else if (INTVAL (XEXP (op0, 1)) == 4)
|
|
2404 sv = 2;
|
|
2405 else
|
|
2406 gcc_unreachable ();
|
|
2407
|
|
2408 fprintf (stream, "[%s + %s << %d]",
|
|
2409 reg_names[REGNO (op1)],
|
|
2410 reg_names[REGNO (XEXP (op0, 0))],
|
|
2411 sv);
|
|
2412 }
|
|
2413 else
|
|
2414 {
|
|
2415 /* The control flow is not supposed to be here. */
|
|
2416 debug_rtx (x);
|
|
2417 gcc_unreachable ();
|
|
2418 }
|
|
2419
|
|
2420 break;
|
|
2421
|
|
2422 case POST_MODIFY:
|
|
2423 /* (post_modify (regA) (plus (regA) (regB)))
|
|
2424 (post_modify (regA) (plus (regA) (const_int)))
|
|
2425 We would like to extract
|
|
2426 regA and regB (or const_int) from plus rtx. */
|
|
2427 op0 = XEXP (XEXP (x, 1), 0);
|
|
2428 op1 = XEXP (XEXP (x, 1), 1);
|
|
2429
|
|
2430 /* Checking op0, forbid using static chain register ($r16)
|
|
2431 on reduced-set registers configuration. */
|
|
2432 if (TARGET_REDUCED_REGS
|
|
2433 && REG_P (op0)
|
|
2434 && REGNO (op0) == STATIC_CHAIN_REGNUM)
|
|
2435 sorry ("a nested function is not supported for reduced registers");
|
|
2436 /* Checking op1, forbid using static chain register ($r16)
|
|
2437 on reduced-set registers configuration. */
|
|
2438 if (TARGET_REDUCED_REGS
|
|
2439 && REG_P (op1)
|
|
2440 && REGNO (op1) == STATIC_CHAIN_REGNUM)
|
|
2441 sorry ("a nested function is not supported for reduced registers");
|
|
2442
|
|
2443 if (REG_P (op0) && REG_P (op1))
|
|
2444 {
|
|
2445 /* [Ra], Rb */
|
|
2446 fprintf (stream, "[%s], %s",
|
|
2447 reg_names[REGNO (op0)], reg_names[REGNO (op1)]);
|
|
2448 }
|
|
2449 else if (REG_P (op0) && CONST_INT_P (op1))
|
|
2450 {
|
|
2451 /* [Ra], imm */
|
|
2452 fprintf (stream, "[%s], %d",
|
|
2453 reg_names[REGNO (op0)], (int)INTVAL (op1));
|
|
2454 }
|
|
2455 else
|
|
2456 {
|
|
2457 /* The control flow is not supposed to be here. */
|
|
2458 debug_rtx (x);
|
|
2459 gcc_unreachable ();
|
|
2460 }
|
|
2461
|
|
2462 break;
|
|
2463
|
|
2464 case POST_INC:
|
|
2465 case POST_DEC:
|
|
2466 op0 = XEXP (x, 0);
|
|
2467
|
|
2468 /* Checking op0, forbid using static chain register ($r16)
|
|
2469 on reduced-set registers configuration. */
|
|
2470 if (TARGET_REDUCED_REGS
|
|
2471 && REG_P (op0)
|
|
2472 && REGNO (op0) == STATIC_CHAIN_REGNUM)
|
|
2473 sorry ("a nested function is not supported for reduced registers");
|
|
2474
|
|
2475 if (REG_P (op0))
|
|
2476 {
|
|
2477 /* "[Ra], 1/2/4" or "[Ra], -1/-2/-4"
|
|
2478 The 1/2/4 or -1/-2/-4 have been displayed in nds32.md.
|
|
2479 We only need to deal with register Ra. */
|
|
2480 fprintf (stream, "[%s]", reg_names[REGNO (op0)]);
|
|
2481 }
|
|
2482 else
|
|
2483 {
|
|
2484 /* The control flow is not supposed to be here. */
|
|
2485 debug_rtx (x);
|
|
2486 gcc_unreachable ();
|
|
2487 }
|
|
2488
|
|
2489 break;
|
|
2490
|
|
2491 default :
|
|
2492 /* Generally, output_addr_const () is able to handle most cases.
|
|
2493 We want to see what CODE could appear,
|
|
2494 so we use gcc_unreachable() to stop it. */
|
|
2495 debug_rtx (x);
|
|
2496 gcc_unreachable ();
|
|
2497 break;
|
|
2498 }
|
|
2499 }
|
|
2500
|
|
2501
|
|
2502 /* Defining target-specific uses of __attribute__. */
|
|
2503
|
|
2504 /* Add some checking after merging attributes. */
|
|
2505 static tree
|
|
2506 nds32_merge_decl_attributes (tree olddecl, tree newdecl)
|
|
2507 {
|
|
2508 tree combined_attrs;
|
|
2509
|
|
2510 /* Create combined attributes. */
|
|
2511 combined_attrs = merge_attributes (DECL_ATTRIBUTES (olddecl),
|
|
2512 DECL_ATTRIBUTES (newdecl));
|
|
2513
|
|
2514 /* Since newdecl is acutally a duplicate of olddecl,
|
|
2515 we can take olddecl for some operations. */
|
|
2516 if (TREE_CODE (olddecl) == FUNCTION_DECL)
|
|
2517 {
|
|
2518 /* Check isr-specific attributes conflict. */
|
|
2519 nds32_check_isr_attrs_conflict (olddecl, combined_attrs);
|
|
2520 }
|
|
2521
|
|
2522 return combined_attrs;
|
|
2523 }
|
|
2524
|
|
2525 /* Add some checking when inserting attributes. */
|
|
2526 static void
|
|
2527 nds32_insert_attributes (tree decl, tree *attributes)
|
|
2528 {
|
|
2529 /* For function declaration, we need to check isr-specific attributes:
|
|
2530 1. Call nds32_check_isr_attrs_conflict() to check any conflict.
|
|
2531 2. Check valid integer value for interrupt/exception.
|
|
2532 3. Check valid integer value for reset.
|
|
2533 4. Check valid function for nmi/warm. */
|
|
2534 if (TREE_CODE (decl) == FUNCTION_DECL)
|
|
2535 {
|
|
2536 tree func_attrs;
|
|
2537 tree intr, excp, reset;
|
|
2538
|
|
2539 /* Pick up function attributes. */
|
|
2540 func_attrs = *attributes;
|
|
2541
|
|
2542 /* 1. Call nds32_check_isr_attrs_conflict() to check any conflict. */
|
|
2543 nds32_check_isr_attrs_conflict (decl, func_attrs);
|
|
2544
|
|
2545 /* Now we are starting to check valid id value
|
|
2546 for interrupt/exception/reset.
|
|
2547 Note that we ONLY check its validity here.
|
|
2548 To construct isr vector information, it is still performed
|
|
2549 by nds32_construct_isr_vectors_information(). */
|
|
2550 intr = lookup_attribute ("interrupt", func_attrs);
|
|
2551 excp = lookup_attribute ("exception", func_attrs);
|
|
2552 reset = lookup_attribute ("reset", func_attrs);
|
|
2553
|
|
2554 if (intr || excp)
|
|
2555 {
|
|
2556 /* Deal with interrupt/exception. */
|
|
2557 tree id_list;
|
|
2558 unsigned int lower_bound, upper_bound;
|
|
2559
|
|
2560 /* The way to handle interrupt or exception is the same,
|
|
2561 we just need to take care of actual vector number.
|
|
2562 For interrupt(0..63), the actual vector number is (9..72).
|
|
2563 For exception(1..8), the actual vector number is (1..8). */
|
|
2564 lower_bound = (intr) ? (0) : (1);
|
|
2565 upper_bound = (intr) ? (63) : (8);
|
|
2566
|
|
2567 /* Prepare id list so that we can traverse id value. */
|
|
2568 id_list = (intr) ? (TREE_VALUE (intr)) : (TREE_VALUE (excp));
|
|
2569
|
|
2570 /* 2. Check valid integer value for interrupt/exception. */
|
|
2571 while (id_list)
|
|
2572 {
|
|
2573 tree id;
|
|
2574
|
|
2575 /* Pick up each vector id value. */
|
|
2576 id = TREE_VALUE (id_list);
|
|
2577 /* Issue error if it is not a valid integer value. */
|
|
2578 if (TREE_CODE (id) != INTEGER_CST
|
|
2579 || wi::ltu_p (wi::to_wide (id), lower_bound)
|
|
2580 || wi::gtu_p (wi::to_wide (id), upper_bound))
|
|
2581 error ("invalid id value for interrupt/exception attribute");
|
|
2582
|
|
2583 /* Advance to next id. */
|
|
2584 id_list = TREE_CHAIN (id_list);
|
|
2585 }
|
|
2586 }
|
|
2587 else if (reset)
|
|
2588 {
|
|
2589 /* Deal with reset. */
|
|
2590 tree id_list;
|
|
2591 tree id;
|
|
2592 tree nmi, warm;
|
|
2593 unsigned int lower_bound;
|
|
2594 unsigned int upper_bound;
|
|
2595
|
|
2596 /* Prepare id_list and identify id value so that
|
|
2597 we can check if total number of vectors is valid. */
|
|
2598 id_list = TREE_VALUE (reset);
|
|
2599 id = TREE_VALUE (id_list);
|
|
2600
|
|
2601 /* The maximum numbers for user's interrupt is 64. */
|
|
2602 lower_bound = 0;
|
|
2603 upper_bound = 64;
|
|
2604
|
|
2605 /* 3. Check valid integer value for reset. */
|
|
2606 if (TREE_CODE (id) != INTEGER_CST
|
|
2607 || wi::ltu_p (wi::to_wide (id), lower_bound)
|
|
2608 || wi::gtu_p (wi::to_wide (id), upper_bound))
|
|
2609 error ("invalid id value for reset attribute");
|
|
2610
|
|
2611 /* 4. Check valid function for nmi/warm. */
|
|
2612 nmi = lookup_attribute ("nmi", func_attrs);
|
|
2613 warm = lookup_attribute ("warm", func_attrs);
|
|
2614
|
|
2615 if (nmi != NULL_TREE)
|
|
2616 {
|
|
2617 tree nmi_func_list;
|
|
2618 tree nmi_func;
|
|
2619
|
|
2620 nmi_func_list = TREE_VALUE (nmi);
|
|
2621 nmi_func = TREE_VALUE (nmi_func_list);
|
|
2622
|
|
2623 /* Issue error if it is not a valid nmi function. */
|
|
2624 if (TREE_CODE (nmi_func) != IDENTIFIER_NODE)
|
|
2625 error ("invalid nmi function for reset attribute");
|
|
2626 }
|
|
2627
|
|
2628 if (warm != NULL_TREE)
|
|
2629 {
|
|
2630 tree warm_func_list;
|
|
2631 tree warm_func;
|
|
2632
|
|
2633 warm_func_list = TREE_VALUE (warm);
|
|
2634 warm_func = TREE_VALUE (warm_func_list);
|
|
2635
|
|
2636 /* Issue error if it is not a valid warm function. */
|
|
2637 if (TREE_CODE (warm_func) != IDENTIFIER_NODE)
|
|
2638 error ("invalid warm function for reset attribute");
|
|
2639 }
|
|
2640 }
|
|
2641 else
|
|
2642 {
|
|
2643 /* No interrupt, exception, or reset attribute is set. */
|
|
2644 return;
|
|
2645 }
|
|
2646 }
|
|
2647 }
|
|
2648
|
|
2649 static bool
|
|
2650 nds32_option_pragma_parse (tree args ATTRIBUTE_UNUSED,
|
|
2651 tree pop_target ATTRIBUTE_UNUSED)
|
|
2652 {
|
|
2653 /* Currently, we do not parse any pragma target by ourself,
|
|
2654 so just simply return false. */
|
|
2655 return false;
|
|
2656 }
|
|
2657
|
|
2658 static void
|
|
2659 nds32_option_override (void)
|
|
2660 {
|
|
2661 /* After all the command options have been parsed,
|
|
2662 we shall deal with some flags for changing compiler settings. */
|
|
2663
|
|
2664 /* At first, we check if we have to strictly
|
|
2665 set some flags based on ISA family. */
|
|
2666 if (TARGET_ISA_V2)
|
|
2667 {
|
|
2668 /* Under V2 ISA, we need to strictly disable TARGET_V3PUSH. */
|
|
2669 target_flags &= ~MASK_V3PUSH;
|
|
2670 }
|
|
2671 if (TARGET_ISA_V3)
|
|
2672 {
|
|
2673 /* Under V3 ISA, currently nothing should be strictly set. */
|
|
2674 }
|
|
2675 if (TARGET_ISA_V3M)
|
|
2676 {
|
|
2677 /* Under V3M ISA, we need to strictly enable TARGET_REDUCED_REGS. */
|
|
2678 target_flags |= MASK_REDUCED_REGS;
|
|
2679 /* Under V3M ISA, we need to strictly disable TARGET_PERF_EXT. */
|
|
2680 target_flags &= ~MASK_PERF_EXT;
|
|
2681 }
|
|
2682
|
|
2683 /* See if we are using reduced-set registers:
|
|
2684 $r0~$r5, $r6~$r10, $r15, $r28, $r29, $r30, $r31
|
|
2685 If so, we must forbid using $r11~$r14, $r16~$r27. */
|
|
2686 if (TARGET_REDUCED_REGS)
|
|
2687 {
|
|
2688 int r;
|
|
2689
|
|
2690 /* Prevent register allocator from
|
|
2691 choosing it as doing register allocation. */
|
|
2692 for (r = 11; r <= 14; r++)
|
|
2693 fixed_regs[r] = call_used_regs[r] = 1;
|
|
2694 for (r = 16; r <= 27; r++)
|
|
2695 fixed_regs[r] = call_used_regs[r] = 1;
|
|
2696 }
|
|
2697
|
|
2698 if (!TARGET_16_BIT)
|
|
2699 {
|
|
2700 /* Under no 16 bit ISA, we need to strictly disable TARGET_V3PUSH. */
|
|
2701 target_flags &= ~MASK_V3PUSH;
|
|
2702 }
|
|
2703
|
|
2704 /* Currently, we don't support PIC code generation yet. */
|
|
2705 if (flag_pic)
|
|
2706 sorry ("position-independent code not supported");
|
|
2707 }
|
|
2708
|
|
2709
|
|
2710 /* Miscellaneous Parameters. */
|
|
2711
|
|
2712 static void
|
|
2713 nds32_init_builtins (void)
|
|
2714 {
|
|
2715 nds32_init_builtins_impl ();
|
|
2716 }
|
|
2717
|
|
2718 static rtx
|
|
2719 nds32_expand_builtin (tree exp,
|
|
2720 rtx target,
|
|
2721 rtx subtarget,
|
|
2722 machine_mode mode,
|
|
2723 int ignore)
|
|
2724 {
|
|
2725 return nds32_expand_builtin_impl (exp, target, subtarget, mode, ignore);
|
|
2726 }
|
|
2727
|
|
2728
|
|
2729 /* ------------------------------------------------------------------------ */
|
|
2730
|
|
2731 /* PART 4: Implemet extern function definitions,
|
|
2732 the prototype is in nds32-protos.h. */
|
|
2733
|
|
2734 /* Defining Data Structures for Per-function Information. */
|
|
2735
|
|
2736 void
|
|
2737 nds32_init_expanders (void)
|
|
2738 {
|
|
2739 /* Arrange to initialize and mark the machine per-function status. */
|
|
2740 init_machine_status = nds32_init_machine_status;
|
|
2741 }
|
|
2742
|
|
2743
|
|
2744 /* Register Usage. */
|
|
2745
|
|
2746 /* -- How Values Fit in Registers. */
|
|
2747
|
|
2748 /* Implement TARGET_HARD_REGNO_MODE_OK. */
|
|
2749
|
|
2750 static bool
|
|
2751 nds32_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
|
|
2752 {
|
|
2753 /* Restrict double-word quantities to even register pairs. */
|
|
2754 if (targetm.hard_regno_nregs (regno, mode) == 1
|
|
2755 || !((regno) & 1))
|
|
2756 return true;
|
|
2757
|
|
2758 return false;
|
|
2759 }
|
|
2760
|
|
2761 #undef TARGET_HARD_REGNO_MODE_OK
|
|
2762 #define TARGET_HARD_REGNO_MODE_OK nds32_hard_regno_mode_ok
|
|
2763
|
|
2764 /* Implement TARGET_MODES_TIEABLE_P. We can use general registers to
|
|
2765 tie QI/HI/SI modes together. */
|
|
2766
|
|
2767 static bool
|
|
2768 nds32_modes_tieable_p (machine_mode mode1, machine_mode mode2)
|
|
2769 {
|
|
2770 return (GET_MODE_CLASS (mode1) == MODE_INT
|
|
2771 && GET_MODE_CLASS (mode2) == MODE_INT
|
|
2772 && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
|
|
2773 && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD);
|
|
2774 }
|
|
2775
|
|
2776 #undef TARGET_MODES_TIEABLE_P
|
|
2777 #define TARGET_MODES_TIEABLE_P nds32_modes_tieable_p
|
|
2778
|
|
2779 /* Register Classes. */
|
|
2780
|
|
2781 enum reg_class
|
|
2782 nds32_regno_reg_class (int regno)
|
|
2783 {
|
|
2784 /* Refer to nds32.h for more register class details. */
|
|
2785
|
|
2786 if (regno >= 0 && regno <= 7)
|
|
2787 return LOW_REGS;
|
|
2788 else if (regno >= 8 && regno <= 11)
|
|
2789 return MIDDLE_REGS;
|
|
2790 else if (regno >= 12 && regno <= 14)
|
|
2791 return HIGH_REGS;
|
|
2792 else if (regno == 15)
|
|
2793 return R15_TA_REG;
|
|
2794 else if (regno >= 16 && regno <= 19)
|
|
2795 return MIDDLE_REGS;
|
|
2796 else if (regno >= 20 && regno <= 31)
|
|
2797 return HIGH_REGS;
|
|
2798 else if (regno == 32 || regno == 33)
|
|
2799 return FRAME_REGS;
|
|
2800 else
|
|
2801 return NO_REGS;
|
|
2802 }
|
|
2803
|
|
2804
|
|
2805 /* Stack Layout and Calling Conventions. */
|
|
2806
|
|
2807 /* -- Basic Stack Layout. */
|
|
2808
|
|
2809 rtx
|
|
2810 nds32_return_addr_rtx (int count,
|
|
2811 rtx frameaddr ATTRIBUTE_UNUSED)
|
|
2812 {
|
|
2813 /* There is no way to determine the return address
|
|
2814 if frameaddr is the frame that has 'count' steps
|
|
2815 up from current frame. */
|
|
2816 if (count != 0)
|
|
2817 return NULL_RTX;
|
|
2818
|
|
2819 /* If count == 0, it means we are at current frame,
|
|
2820 the return address is $r30 ($lp). */
|
|
2821 return get_hard_reg_initial_val (Pmode, LP_REGNUM);
|
|
2822 }
|
|
2823
|
|
2824 /* -- Eliminating Frame Pointer and Arg Pointer. */
|
|
2825
|
|
2826 HOST_WIDE_INT
|
|
2827 nds32_initial_elimination_offset (unsigned int from_reg, unsigned int to_reg)
|
|
2828 {
|
|
2829 HOST_WIDE_INT offset;
|
|
2830
|
|
2831 /* Compute and setup stack frame size.
|
|
2832 The result will be in cfun->machine. */
|
|
2833 nds32_compute_stack_frame ();
|
|
2834
|
|
2835 /* Remember to consider
|
|
2836 cfun->machine->callee_saved_area_gpr_padding_bytes
|
|
2837 when calculating offset. */
|
|
2838 if (from_reg == ARG_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM)
|
|
2839 {
|
|
2840 offset = (cfun->machine->fp_size
|
|
2841 + cfun->machine->gp_size
|
|
2842 + cfun->machine->lp_size
|
|
2843 + cfun->machine->callee_saved_gpr_regs_size
|
|
2844 + cfun->machine->callee_saved_area_gpr_padding_bytes
|
|
2845 + cfun->machine->local_size
|
|
2846 + cfun->machine->out_args_size);
|
|
2847 }
|
|
2848 else if (from_reg == ARG_POINTER_REGNUM
|
|
2849 && to_reg == HARD_FRAME_POINTER_REGNUM)
|
|
2850 {
|
|
2851 offset = 0;
|
|
2852 }
|
|
2853 else if (from_reg == FRAME_POINTER_REGNUM
|
|
2854 && to_reg == STACK_POINTER_REGNUM)
|
|
2855 {
|
|
2856 offset = (cfun->machine->local_size + cfun->machine->out_args_size);
|
|
2857 }
|
|
2858 else if (from_reg == FRAME_POINTER_REGNUM
|
|
2859 && to_reg == HARD_FRAME_POINTER_REGNUM)
|
|
2860 {
|
|
2861 offset = (-1) * (cfun->machine->fp_size
|
|
2862 + cfun->machine->gp_size
|
|
2863 + cfun->machine->lp_size
|
|
2864 + cfun->machine->callee_saved_gpr_regs_size
|
|
2865 + cfun->machine->callee_saved_area_gpr_padding_bytes);
|
|
2866 }
|
|
2867 else
|
|
2868 {
|
|
2869 gcc_unreachable ();
|
|
2870 }
|
|
2871
|
|
2872 return offset;
|
|
2873 }
|
|
2874
|
|
2875 /* -- Passing Arguments in Registers. */
|
|
2876
|
|
2877 void
|
|
2878 nds32_init_cumulative_args (CUMULATIVE_ARGS *cum,
|
|
2879 tree fntype ATTRIBUTE_UNUSED,
|
|
2880 rtx libname ATTRIBUTE_UNUSED,
|
|
2881 tree fndecl ATTRIBUTE_UNUSED,
|
|
2882 int n_named_args ATTRIBUTE_UNUSED)
|
|
2883 {
|
|
2884 /* Initial available registers
|
|
2885 (in offset, corresponding to NDS32_GPR_ARG_FIRST_REGNUM)
|
|
2886 for passing arguments. */
|
|
2887 cum->gpr_offset = 0;
|
|
2888 }
|
|
2889
|
|
2890 /* -- Function Entry and Exit. */
|
|
2891
|
|
2892 /* Function for normal multiple push prologue. */
|
|
2893 void
|
|
2894 nds32_expand_prologue (void)
|
|
2895 {
|
|
2896 int fp_adjust;
|
|
2897 int sp_adjust;
|
|
2898 int en4_const;
|
|
2899
|
|
2900 rtx Rb, Re;
|
|
2901 rtx fp_adjust_insn, sp_adjust_insn;
|
|
2902
|
|
2903 /* Compute and setup stack frame size.
|
|
2904 The result will be in cfun->machine. */
|
|
2905 nds32_compute_stack_frame ();
|
|
2906
|
|
2907 /* If this is a variadic function, first we need to push argument
|
|
2908 registers that hold the unnamed argument value. */
|
|
2909 if (cfun->machine->va_args_size != 0)
|
|
2910 {
|
|
2911 Rb = gen_rtx_REG (SImode, cfun->machine->va_args_first_regno);
|
|
2912 Re = gen_rtx_REG (SImode, cfun->machine->va_args_last_regno);
|
|
2913 /* No need to push $fp, $gp, or $lp, so use GEN_INT(0). */
|
|
2914 nds32_emit_stack_push_multiple (Rb, Re, GEN_INT (0), true);
|
|
2915
|
|
2916 /* We may also need to adjust stack pointer for padding bytes
|
|
2917 because varargs may cause $sp not 8-byte aligned. */
|
|
2918 if (cfun->machine->va_args_area_padding_bytes)
|
|
2919 {
|
|
2920 /* Generate sp adjustment instruction. */
|
|
2921 sp_adjust = cfun->machine->va_args_area_padding_bytes;
|
|
2922 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
|
|
2923 stack_pointer_rtx,
|
|
2924 GEN_INT (-1 * sp_adjust));
|
|
2925
|
|
2926 /* Emit rtx into instructions list and receive INSN rtx form. */
|
|
2927 sp_adjust_insn = emit_insn (sp_adjust_insn);
|
|
2928
|
|
2929 /* The insn rtx 'sp_adjust_insn' will change frame layout.
|
|
2930 We need to use RTX_FRAME_RELATED_P so that GCC is able to
|
|
2931 generate CFI (Call Frame Information) stuff. */
|
|
2932 RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
|
|
2933 }
|
|
2934 }
|
|
2935
|
|
2936 /* If the function is 'naked',
|
|
2937 we do not have to generate prologue code fragment. */
|
|
2938 if (cfun->machine->naked_p)
|
|
2939 return;
|
|
2940
|
|
2941 /* Get callee_first_regno and callee_last_regno. */
|
|
2942 Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_first_gpr_regno);
|
|
2943 Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_last_gpr_regno);
|
|
2944
|
|
2945 /* nds32_emit_stack_push_multiple(first_regno, last_regno),
|
|
2946 the pattern 'stack_push_multiple' is implemented in nds32.md.
|
|
2947 For En4 field, we have to calculate its constant value.
|
|
2948 Refer to Andes ISA for more information. */
|
|
2949 en4_const = 0;
|
|
2950 if (cfun->machine->fp_size)
|
|
2951 en4_const += 8;
|
|
2952 if (cfun->machine->gp_size)
|
|
2953 en4_const += 4;
|
|
2954 if (cfun->machine->lp_size)
|
|
2955 en4_const += 2;
|
|
2956
|
|
2957 /* If $fp, $gp, $lp, and all callee-save registers are NOT required
|
|
2958 to be saved, we don't have to create multiple push instruction.
|
|
2959 Otherwise, a multiple push instruction is needed. */
|
|
2960 if (!(REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM && en4_const == 0))
|
|
2961 {
|
|
2962 /* Create multiple push instruction rtx. */
|
|
2963 nds32_emit_stack_push_multiple (Rb, Re, GEN_INT (en4_const), false);
|
|
2964 }
|
|
2965
|
|
2966 /* Check frame_pointer_needed to see
|
|
2967 if we shall emit fp adjustment instruction. */
|
|
2968 if (frame_pointer_needed)
|
|
2969 {
|
|
2970 /* adjust $fp = $sp + ($fp size) + ($gp size) + ($lp size)
|
|
2971 + (4 * callee-saved-registers)
|
|
2972 Note: No need to adjust
|
|
2973 cfun->machine->callee_saved_area_gpr_padding_bytes,
|
|
2974 because, at this point, stack pointer is just
|
|
2975 at the position after push instruction. */
|
|
2976 fp_adjust = cfun->machine->fp_size
|
|
2977 + cfun->machine->gp_size
|
|
2978 + cfun->machine->lp_size
|
|
2979 + cfun->machine->callee_saved_gpr_regs_size;
|
|
2980 fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx,
|
|
2981 stack_pointer_rtx,
|
|
2982 GEN_INT (fp_adjust));
|
|
2983 /* Emit rtx into instructions list and receive INSN rtx form. */
|
|
2984 fp_adjust_insn = emit_insn (fp_adjust_insn);
|
|
2985
|
|
2986 /* The insn rtx 'fp_adjust_insn' will change frame layout. */
|
|
2987 RTX_FRAME_RELATED_P (fp_adjust_insn) = 1;
|
|
2988 }
|
|
2989
|
|
2990 /* Adjust $sp = $sp - local_size - out_args_size
|
|
2991 - callee_saved_area_gpr_padding_bytes. */
|
|
2992 sp_adjust = cfun->machine->local_size
|
|
2993 + cfun->machine->out_args_size
|
|
2994 + cfun->machine->callee_saved_area_gpr_padding_bytes;
|
|
2995 /* sp_adjust value may be out of range of the addi instruction,
|
|
2996 create alternative add behavior with TA_REGNUM if necessary,
|
|
2997 using NEGATIVE value to tell that we are decreasing address. */
|
|
2998 sp_adjust = nds32_force_addi_stack_int ( (-1) * sp_adjust);
|
|
2999 if (sp_adjust)
|
|
3000 {
|
|
3001 /* Generate sp adjustment instruction if and only if sp_adjust != 0. */
|
|
3002 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
|
|
3003 stack_pointer_rtx,
|
|
3004 GEN_INT (-1 * sp_adjust));
|
|
3005 /* Emit rtx into instructions list and receive INSN rtx form. */
|
|
3006 sp_adjust_insn = emit_insn (sp_adjust_insn);
|
|
3007
|
|
3008 /* The insn rtx 'sp_adjust_insn' will change frame layout.
|
|
3009 We need to use RTX_FRAME_RELATED_P so that GCC is able to
|
|
3010 generate CFI (Call Frame Information) stuff. */
|
|
3011 RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
|
|
3012 }
|
|
3013
|
|
3014 /* Prevent the instruction scheduler from
|
|
3015 moving instructions across the boundary. */
|
|
3016 emit_insn (gen_blockage ());
|
|
3017 }
|
|
3018
|
|
3019 /* Function for normal multiple pop epilogue. */
|
|
3020 void
|
|
3021 nds32_expand_epilogue (bool sibcall_p)
|
|
3022 {
|
|
3023 int sp_adjust;
|
|
3024 int en4_const;
|
|
3025
|
|
3026 rtx Rb, Re;
|
|
3027 rtx sp_adjust_insn;
|
|
3028
|
|
3029 /* Compute and setup stack frame size.
|
|
3030 The result will be in cfun->machine. */
|
|
3031 nds32_compute_stack_frame ();
|
|
3032
|
|
3033 /* Prevent the instruction scheduler from
|
|
3034 moving instructions across the boundary. */
|
|
3035 emit_insn (gen_blockage ());
|
|
3036
|
|
3037 /* If the function is 'naked', we do not have to generate
|
|
3038 epilogue code fragment BUT 'ret' instruction.
|
|
3039 However, if this function is also a variadic function,
|
|
3040 we need to create adjust stack pointer before 'ret' instruction. */
|
|
3041 if (cfun->machine->naked_p)
|
|
3042 {
|
|
3043 /* If this is a variadic function, we do not have to restore argument
|
|
3044 registers but need to adjust stack pointer back to previous stack
|
|
3045 frame location before return. */
|
|
3046 if (cfun->machine->va_args_size != 0)
|
|
3047 {
|
|
3048 /* Generate sp adjustment instruction.
|
|
3049 We need to consider padding bytes here. */
|
|
3050 sp_adjust = cfun->machine->va_args_size
|
|
3051 + cfun->machine->va_args_area_padding_bytes;
|
|
3052 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
|
|
3053 stack_pointer_rtx,
|
|
3054 GEN_INT (sp_adjust));
|
|
3055 /* Emit rtx into instructions list and receive INSN rtx form. */
|
|
3056 sp_adjust_insn = emit_insn (sp_adjust_insn);
|
|
3057
|
|
3058 /* The insn rtx 'sp_adjust_insn' will change frame layout.
|
|
3059 We need to use RTX_FRAME_RELATED_P so that GCC is able to
|
|
3060 generate CFI (Call Frame Information) stuff. */
|
|
3061 RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
|
|
3062 }
|
|
3063
|
|
3064 /* Generate return instruction by using 'return_internal' pattern.
|
|
3065 Make sure this instruction is after gen_blockage(). */
|
|
3066 if (!sibcall_p)
|
|
3067 emit_jump_insn (gen_return_internal ());
|
|
3068 return;
|
|
3069 }
|
|
3070
|
|
3071 if (frame_pointer_needed)
|
|
3072 {
|
|
3073 /* adjust $sp = $fp - ($fp size) - ($gp size) - ($lp size)
|
|
3074 - (4 * callee-saved-registers)
|
|
3075 Note: No need to adjust
|
|
3076 cfun->machine->callee_saved_area_gpr_padding_bytes,
|
|
3077 because we want to adjust stack pointer
|
|
3078 to the position for pop instruction. */
|
|
3079 sp_adjust = cfun->machine->fp_size
|
|
3080 + cfun->machine->gp_size
|
|
3081 + cfun->machine->lp_size
|
|
3082 + cfun->machine->callee_saved_gpr_regs_size;
|
|
3083 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
|
|
3084 hard_frame_pointer_rtx,
|
|
3085 GEN_INT (-1 * sp_adjust));
|
|
3086 /* Emit rtx into instructions list and receive INSN rtx form. */
|
|
3087 sp_adjust_insn = emit_insn (sp_adjust_insn);
|
|
3088
|
|
3089 /* The insn rtx 'sp_adjust_insn' will change frame layout. */
|
|
3090 RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
|
|
3091 }
|
|
3092 else
|
|
3093 {
|
|
3094 /* If frame pointer is NOT needed,
|
|
3095 we cannot calculate the sp adjustment from frame pointer.
|
|
3096 Instead, we calculate the adjustment by local_size,
|
|
3097 out_args_size, and callee_saved_area_padding_bytes.
|
|
3098 Notice that such sp adjustment value may be out of range,
|
|
3099 so we have to deal with it as well. */
|
|
3100
|
|
3101 /* Adjust $sp = $sp + local_size + out_args_size
|
|
3102 + callee_saved_area_padding_bytes. */
|
|
3103 sp_adjust = cfun->machine->local_size
|
|
3104 + cfun->machine->out_args_size
|
|
3105 + cfun->machine->callee_saved_area_gpr_padding_bytes;
|
|
3106 /* sp_adjust value may be out of range of the addi instruction,
|
|
3107 create alternative add behavior with TA_REGNUM if necessary,
|
|
3108 using POSITIVE value to tell that we are increasing address. */
|
|
3109 sp_adjust = nds32_force_addi_stack_int (sp_adjust);
|
|
3110 if (sp_adjust)
|
|
3111 {
|
|
3112 /* Generate sp adjustment instruction
|
|
3113 if and only if sp_adjust != 0. */
|
|
3114 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
|
|
3115 stack_pointer_rtx,
|
|
3116 GEN_INT (sp_adjust));
|
|
3117 /* Emit rtx into instructions list and receive INSN rtx form. */
|
|
3118 sp_adjust_insn = emit_insn (sp_adjust_insn);
|
|
3119
|
|
3120 /* The insn rtx 'sp_adjust_insn' will change frame layout. */
|
|
3121 RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
|
|
3122 }
|
|
3123 }
|
|
3124
|
|
3125 /* Get callee_first_regno and callee_last_regno. */
|
|
3126 Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_first_gpr_regno);
|
|
3127 Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_last_gpr_regno);
|
|
3128
|
|
3129 /* nds32_emit_stack_pop_multiple(first_regno, last_regno),
|
|
3130 the pattern 'stack_pop_multiple' is implementad in nds32.md.
|
|
3131 For En4 field, we have to calculate its constant value.
|
|
3132 Refer to Andes ISA for more information. */
|
|
3133 en4_const = 0;
|
|
3134 if (cfun->machine->fp_size)
|
|
3135 en4_const += 8;
|
|
3136 if (cfun->machine->gp_size)
|
|
3137 en4_const += 4;
|
|
3138 if (cfun->machine->lp_size)
|
|
3139 en4_const += 2;
|
|
3140
|
|
3141 /* If $fp, $gp, $lp, and all callee-save registers are NOT required
|
|
3142 to be saved, we don't have to create multiple pop instruction.
|
|
3143 Otherwise, a multiple pop instruction is needed. */
|
|
3144 if (!(REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM && en4_const == 0))
|
|
3145 {
|
|
3146 /* Create multiple pop instruction rtx. */
|
|
3147 nds32_emit_stack_pop_multiple (Rb, Re, GEN_INT (en4_const));
|
|
3148 }
|
|
3149
|
|
3150 /* If this is a variadic function, we do not have to restore argument
|
|
3151 registers but need to adjust stack pointer back to previous stack
|
|
3152 frame location before return. */
|
|
3153 if (cfun->machine->va_args_size != 0)
|
|
3154 {
|
|
3155 /* Generate sp adjustment instruction.
|
|
3156 We need to consider padding bytes here. */
|
|
3157 sp_adjust = cfun->machine->va_args_size
|
|
3158 + cfun->machine->va_args_area_padding_bytes;
|
|
3159 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
|
|
3160 stack_pointer_rtx,
|
|
3161 GEN_INT (sp_adjust));
|
|
3162 /* Emit rtx into instructions list and receive INSN rtx form. */
|
|
3163 sp_adjust_insn = emit_insn (sp_adjust_insn);
|
|
3164
|
|
3165 /* The insn rtx 'sp_adjust_insn' will change frame layout.
|
|
3166 We need to use RTX_FRAME_RELATED_P so that GCC is able to
|
|
3167 generate CFI (Call Frame Information) stuff. */
|
|
3168 RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
|
|
3169 }
|
|
3170
|
|
3171 /* Generate return instruction. */
|
|
3172 if (!sibcall_p)
|
|
3173 emit_jump_insn (gen_return_internal ());
|
|
3174 }
|
|
3175
|
|
3176 /* Function for v3push prologue. */
|
|
3177 void
|
|
3178 nds32_expand_prologue_v3push (void)
|
|
3179 {
|
|
3180 int fp_adjust;
|
|
3181 int sp_adjust;
|
|
3182
|
|
3183 rtx Rb, Re;
|
|
3184 rtx fp_adjust_insn, sp_adjust_insn;
|
|
3185
|
|
3186 /* Compute and setup stack frame size.
|
|
3187 The result will be in cfun->machine. */
|
|
3188 nds32_compute_stack_frame ();
|
|
3189
|
|
3190 /* If the function is 'naked',
|
|
3191 we do not have to generate prologue code fragment. */
|
|
3192 if (cfun->machine->naked_p)
|
|
3193 return;
|
|
3194
|
|
3195 /* Get callee_first_regno and callee_last_regno. */
|
|
3196 Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_first_gpr_regno);
|
|
3197 Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_last_gpr_regno);
|
|
3198
|
|
3199 /* Calculate sp_adjust first to test if 'push25 Re,imm8u' is available,
|
|
3200 where imm8u has to be 8-byte alignment. */
|
|
3201 sp_adjust = cfun->machine->local_size
|
|
3202 + cfun->machine->out_args_size
|
|
3203 + cfun->machine->callee_saved_area_gpr_padding_bytes;
|
|
3204
|
|
3205 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
|
|
3206 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust))
|
|
3207 {
|
|
3208 /* We can use 'push25 Re,imm8u'. */
|
|
3209
|
|
3210 /* nds32_emit_stack_v3push(last_regno, sp_adjust),
|
|
3211 the pattern 'stack_v3push' is implemented in nds32.md.
|
|
3212 The (const_int 14) means v3push always push { $fp $gp $lp }. */
|
|
3213 nds32_emit_stack_v3push (Rb, Re,
|
|
3214 GEN_INT (14), GEN_INT (sp_adjust));
|
|
3215
|
|
3216 /* Check frame_pointer_needed to see
|
|
3217 if we shall emit fp adjustment instruction. */
|
|
3218 if (frame_pointer_needed)
|
|
3219 {
|
|
3220 /* adjust $fp = $sp + 4 ($fp size)
|
|
3221 + 4 ($gp size)
|
|
3222 + 4 ($lp size)
|
|
3223 + (4 * n) (callee-saved registers)
|
|
3224 + sp_adjust ('push25 Re,imm8u')
|
|
3225 Note: Since we use 'push25 Re,imm8u',
|
|
3226 the position of stack pointer is further
|
|
3227 changed after push instruction.
|
|
3228 Hence, we need to take sp_adjust value
|
|
3229 into consideration. */
|
|
3230 fp_adjust = cfun->machine->fp_size
|
|
3231 + cfun->machine->gp_size
|
|
3232 + cfun->machine->lp_size
|
|
3233 + cfun->machine->callee_saved_gpr_regs_size
|
|
3234 + sp_adjust;
|
|
3235 fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx,
|
|
3236 stack_pointer_rtx,
|
|
3237 GEN_INT (fp_adjust));
|
|
3238 /* Emit rtx into instructions list and receive INSN rtx form. */
|
|
3239 fp_adjust_insn = emit_insn (fp_adjust_insn);
|
|
3240 }
|
|
3241 }
|
|
3242 else
|
|
3243 {
|
|
3244 /* We have to use 'push25 Re,0' and
|
|
3245 expand one more instruction to adjust $sp later. */
|
|
3246
|
|
3247 /* nds32_emit_stack_v3push(last_regno, sp_adjust),
|
|
3248 the pattern 'stack_v3push' is implemented in nds32.md.
|
|
3249 The (const_int 14) means v3push always push { $fp $gp $lp }. */
|
|
3250 nds32_emit_stack_v3push (Rb, Re,
|
|
3251 GEN_INT (14), GEN_INT (0));
|
|
3252
|
|
3253 /* Check frame_pointer_needed to see
|
|
3254 if we shall emit fp adjustment instruction. */
|
|
3255 if (frame_pointer_needed)
|
|
3256 {
|
|
3257 /* adjust $fp = $sp + 4 ($fp size)
|
|
3258 + 4 ($gp size)
|
|
3259 + 4 ($lp size)
|
|
3260 + (4 * n) (callee-saved registers)
|
|
3261 Note: Since we use 'push25 Re,0',
|
|
3262 the stack pointer is just at the position
|
|
3263 after push instruction.
|
|
3264 No need to take sp_adjust into consideration. */
|
|
3265 fp_adjust = cfun->machine->fp_size
|
|
3266 + cfun->machine->gp_size
|
|
3267 + cfun->machine->lp_size
|
|
3268 + cfun->machine->callee_saved_gpr_regs_size;
|
|
3269 fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx,
|
|
3270 stack_pointer_rtx,
|
|
3271 GEN_INT (fp_adjust));
|
|
3272 /* Emit rtx into instructions list and receive INSN rtx form. */
|
|
3273 fp_adjust_insn = emit_insn (fp_adjust_insn);
|
|
3274 }
|
|
3275
|
|
3276 /* Because we use 'push25 Re,0',
|
|
3277 we need to expand one more instruction to adjust $sp.
|
|
3278 However, sp_adjust value may be out of range of the addi instruction,
|
|
3279 create alternative add behavior with TA_REGNUM if necessary,
|
|
3280 using NEGATIVE value to tell that we are decreasing address. */
|
|
3281 sp_adjust = nds32_force_addi_stack_int ( (-1) * sp_adjust);
|
|
3282 if (sp_adjust)
|
|
3283 {
|
|
3284 /* Generate sp adjustment instruction
|
|
3285 if and only if sp_adjust != 0. */
|
|
3286 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
|
|
3287 stack_pointer_rtx,
|
|
3288 GEN_INT (-1 * sp_adjust));
|
|
3289 /* Emit rtx into instructions list and receive INSN rtx form. */
|
|
3290 sp_adjust_insn = emit_insn (sp_adjust_insn);
|
|
3291
|
|
3292 /* The insn rtx 'sp_adjust_insn' will change frame layout.
|
|
3293 We need to use RTX_FRAME_RELATED_P so that GCC is able to
|
|
3294 generate CFI (Call Frame Information) stuff. */
|
|
3295 RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
|
|
3296 }
|
|
3297 }
|
|
3298
|
|
3299 /* Prevent the instruction scheduler from
|
|
3300 moving instructions across the boundary. */
|
|
3301 emit_insn (gen_blockage ());
|
|
3302 }
|
|
3303
|
|
3304 /* Function for v3pop epilogue. */
|
|
3305 void
|
|
3306 nds32_expand_epilogue_v3pop (bool sibcall_p)
|
|
3307 {
|
|
3308 int sp_adjust;
|
|
3309
|
|
3310 rtx Rb, Re;
|
|
3311 rtx sp_adjust_insn;
|
|
3312
|
|
3313 /* Compute and setup stack frame size.
|
|
3314 The result will be in cfun->machine. */
|
|
3315 nds32_compute_stack_frame ();
|
|
3316
|
|
3317 /* Prevent the instruction scheduler from
|
|
3318 moving instructions across the boundary. */
|
|
3319 emit_insn (gen_blockage ());
|
|
3320
|
|
3321 /* If the function is 'naked', we do not have to generate
|
|
3322 epilogue code fragment BUT 'ret' instruction. */
|
|
3323 if (cfun->machine->naked_p)
|
|
3324 {
|
|
3325 /* Generate return instruction by using 'return_internal' pattern.
|
|
3326 Make sure this instruction is after gen_blockage(). */
|
|
3327 if (!sibcall_p)
|
|
3328 emit_jump_insn (gen_return_internal ());
|
|
3329 return;
|
|
3330 }
|
|
3331
|
|
3332 /* Get callee_first_regno and callee_last_regno. */
|
|
3333 Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_first_gpr_regno);
|
|
3334 Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_last_gpr_regno);
|
|
3335
|
|
3336 /* Calculate sp_adjust first to test if 'pop25 Re,imm8u' is available,
|
|
3337 where imm8u has to be 8-byte alignment. */
|
|
3338 sp_adjust = cfun->machine->local_size
|
|
3339 + cfun->machine->out_args_size
|
|
3340 + cfun->machine->callee_saved_area_gpr_padding_bytes;
|
|
3341
|
|
3342 /* We have to consider alloca issue as well.
|
|
3343 If the function does call alloca(), the stack pointer is not fixed.
|
|
3344 In that case, we cannot use 'pop25 Re,imm8u' directly.
|
|
3345 We have to caculate stack pointer from frame pointer
|
|
3346 and then use 'pop25 Re,0'.
|
|
3347 Of course, the frame_pointer_needed should be nonzero
|
|
3348 if the function calls alloca(). */
|
|
3349 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
|
|
3350 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)
|
|
3351 && !cfun->calls_alloca)
|
|
3352 {
|
|
3353 /* We can use 'pop25 Re,imm8u'. */
|
|
3354
|
|
3355 /* nds32_emit_stack_v3pop(last_regno, sp_adjust),
|
|
3356 the pattern 'stack_v3pop' is implementad in nds32.md.
|
|
3357 The (const_int 14) means v3pop always pop { $fp $gp $lp }. */
|
|
3358 nds32_emit_stack_v3pop (Rb, Re,
|
|
3359 GEN_INT (14), GEN_INT (sp_adjust));
|
|
3360 }
|
|
3361 else
|
|
3362 {
|
|
3363 /* We have to use 'pop25 Re,0', and prior to it,
|
|
3364 we must expand one more instruction to adjust $sp. */
|
|
3365
|
|
3366 if (frame_pointer_needed)
|
|
3367 {
|
|
3368 /* adjust $sp = $fp - 4 ($fp size)
|
|
3369 - 4 ($gp size)
|
|
3370 - 4 ($lp size)
|
|
3371 - (4 * n) (callee-saved registers)
|
|
3372 Note: No need to adjust
|
|
3373 cfun->machine->callee_saved_area_gpr_padding_bytes,
|
|
3374 because we want to adjust stack pointer
|
|
3375 to the position for pop instruction. */
|
|
3376 sp_adjust = cfun->machine->fp_size
|
|
3377 + cfun->machine->gp_size
|
|
3378 + cfun->machine->lp_size
|
|
3379 + cfun->machine->callee_saved_gpr_regs_size;
|
|
3380 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
|
|
3381 hard_frame_pointer_rtx,
|
|
3382 GEN_INT (-1 * sp_adjust));
|
|
3383 /* Emit rtx into instructions list and receive INSN rtx form. */
|
|
3384 sp_adjust_insn = emit_insn (sp_adjust_insn);
|
|
3385 }
|
|
3386 else
|
|
3387 {
|
|
3388 /* If frame pointer is NOT needed,
|
|
3389 we cannot calculate the sp adjustment from frame pointer.
|
|
3390 Instead, we calculate the adjustment by local_size,
|
|
3391 out_args_size, and callee_saved_area_padding_bytes.
|
|
3392 Notice that such sp adjustment value may be out of range,
|
|
3393 so we have to deal with it as well. */
|
|
3394
|
|
3395 /* Adjust $sp = $sp + local_size + out_args_size
|
|
3396 + callee_saved_area_gpr_padding_bytes. */
|
|
3397 sp_adjust = cfun->machine->local_size
|
|
3398 + cfun->machine->out_args_size
|
|
3399 + cfun->machine->callee_saved_area_gpr_padding_bytes;
|
|
3400 /* sp_adjust value may be out of range of the addi instruction,
|
|
3401 create alternative add behavior with TA_REGNUM if necessary,
|
|
3402 using POSITIVE value to tell that we are increasing address. */
|
|
3403 sp_adjust = nds32_force_addi_stack_int (sp_adjust);
|
|
3404 if (sp_adjust)
|
|
3405 {
|
|
3406 /* Generate sp adjustment instruction
|
|
3407 if and only if sp_adjust != 0. */
|
|
3408 sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
|
|
3409 stack_pointer_rtx,
|
|
3410 GEN_INT (sp_adjust));
|
|
3411 /* Emit rtx into instructions list and receive INSN rtx form. */
|
|
3412 sp_adjust_insn = emit_insn (sp_adjust_insn);
|
|
3413 }
|
|
3414 }
|
|
3415
|
|
3416 /* nds32_emit_stack_v3pop(last_regno, sp_adjust),
|
|
3417 the pattern 'stack_v3pop' is implementad in nds32.md. */
|
|
3418 /* The (const_int 14) means v3pop always pop { $fp $gp $lp }. */
|
|
3419 nds32_emit_stack_v3pop (Rb, Re,
|
|
3420 GEN_INT (14), GEN_INT (0));
|
|
3421 }
|
|
3422
|
|
3423 /* Generate return instruction. */
|
|
3424 emit_jump_insn (gen_pop25return ());
|
|
3425 }
|
|
3426
|
|
3427 /* Return nonzero if this function is known to have a null epilogue.
|
|
3428 This allows the optimizer to omit jumps to jumps if no stack
|
|
3429 was created. */
|
|
3430 int
|
|
3431 nds32_can_use_return_insn (void)
|
|
3432 {
|
|
3433 /* Prior to reloading, we can't tell how many registers must be saved.
|
|
3434 Thus we can not determine whether this function has null epilogue. */
|
|
3435 if (!reload_completed)
|
|
3436 return 0;
|
|
3437
|
|
3438 /* If no stack was created, two conditions must be satisfied:
|
|
3439 1. This is a naked function.
|
|
3440 So there is no callee-saved, local size, or outgoing size.
|
|
3441 2. This is NOT a variadic function.
|
|
3442 So there is no pushing arguement registers into the stack. */
|
|
3443 return (cfun->machine->naked_p && (cfun->machine->va_args_size == 0));
|
|
3444 }
|
|
3445
|
|
3446 /* ------------------------------------------------------------------------ */
|
|
3447
|
|
3448 /* Function to test 333-form for load/store instructions.
|
|
3449 This is auxiliary extern function for auxiliary macro in nds32.h.
|
|
3450 Because it is a little complicated, we use function instead of macro. */
|
|
3451 bool
|
|
3452 nds32_ls_333_p (rtx rt, rtx ra, rtx imm, machine_mode mode)
|
|
3453 {
|
|
3454 if (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS
|
|
3455 && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS)
|
|
3456 {
|
|
3457 if (GET_MODE_SIZE (mode) == 4)
|
|
3458 return satisfies_constraint_Iu05 (imm);
|
|
3459
|
|
3460 if (GET_MODE_SIZE (mode) == 2)
|
|
3461 return satisfies_constraint_Iu04 (imm);
|
|
3462
|
|
3463 if (GET_MODE_SIZE (mode) == 1)
|
|
3464 return satisfies_constraint_Iu03 (imm);
|
|
3465 }
|
|
3466
|
|
3467 return false;
|
|
3468 }
|
|
3469
|
|
3470
|
|
3471 /* Computing the Length of an Insn.
|
|
3472 Modifies the length assigned to instruction INSN.
|
|
3473 LEN is the initially computed length of the insn. */
|
|
3474 int
|
|
3475 nds32_adjust_insn_length (rtx_insn *insn, int length)
|
|
3476 {
|
|
3477 rtx src, dst;
|
|
3478
|
|
3479 switch (recog_memoized (insn))
|
|
3480 {
|
|
3481 case CODE_FOR_move_df:
|
|
3482 case CODE_FOR_move_di:
|
|
3483 /* Adjust length of movd44 to 2. */
|
|
3484 src = XEXP (PATTERN (insn), 1);
|
|
3485 dst = XEXP (PATTERN (insn), 0);
|
|
3486
|
|
3487 if (REG_P (src)
|
|
3488 && REG_P (dst)
|
|
3489 && (REGNO (src) % 2) == 0
|
|
3490 && (REGNO (dst) % 2) == 0)
|
|
3491 length = 2;
|
|
3492 break;
|
|
3493
|
|
3494 default:
|
|
3495 break;
|
|
3496 }
|
|
3497
|
|
3498 return length;
|
|
3499 }
|
|
3500
|
|
3501
|
|
3502 /* Return align 2 (log base 2) if the next instruction of LABEL is 4 byte. */
|
|
3503 int
|
|
3504 nds32_target_alignment (rtx_insn *label)
|
|
3505 {
|
|
3506 rtx_insn *insn;
|
|
3507
|
|
3508 if (optimize_size)
|
|
3509 return 0;
|
|
3510
|
|
3511 insn = next_active_insn (label);
|
|
3512
|
|
3513 if (insn == 0)
|
|
3514 return 0;
|
|
3515 else if ((get_attr_length (insn) % 4) == 0)
|
|
3516 return 2;
|
|
3517 else
|
|
3518 return 0;
|
|
3519 }
|
|
3520
|
|
3521 /* ------------------------------------------------------------------------ */
|
|
3522
|
|
3523 /* PART 5: Initialize target hook structure and definitions. */
|
|
3524
|
|
3525 /* Controlling the Compilation Driver. */
|
|
3526
|
|
3527
|
|
3528 /* Run-time Target Specification. */
|
|
3529
|
|
3530
|
|
3531 /* Defining Data Structures for Per-function Information. */
|
|
3532
|
|
3533
|
|
3534 /* Storage Layout. */
|
|
3535
|
|
3536 #undef TARGET_PROMOTE_FUNCTION_MODE
|
|
3537 #define TARGET_PROMOTE_FUNCTION_MODE \
|
|
3538 default_promote_function_mode_always_promote
|
|
3539
|
|
3540
|
|
3541 /* Layout of Source Language Data Types. */
|
|
3542
|
|
3543
|
|
3544 /* Register Usage. */
|
|
3545
|
|
3546 /* -- Basic Characteristics of Registers. */
|
|
3547
|
|
3548 /* -- Order of Allocation of Registers. */
|
|
3549
|
|
3550 /* -- How Values Fit in Registers. */
|
|
3551
|
|
3552 /* -- Handling Leaf Functions. */
|
|
3553
|
|
3554 /* -- Registers That Form a Stack. */
|
|
3555
|
|
3556
|
|
3557 /* Register Classes. */
|
|
3558
|
|
3559 #undef TARGET_CLASS_MAX_NREGS
|
|
3560 #define TARGET_CLASS_MAX_NREGS nds32_class_max_nregs
|
|
3561
|
|
3562 #undef TARGET_REGISTER_PRIORITY
|
|
3563 #define TARGET_REGISTER_PRIORITY nds32_register_priority
|
|
3564
|
|
3565
|
|
3566 /* Obsolete Macros for Defining Constraints. */
|
|
3567
|
|
3568
|
|
3569 /* Stack Layout and Calling Conventions. */
|
|
3570
|
|
3571 /* -- Basic Stack Layout. */
|
|
3572
|
|
3573 /* -- Exception Handling Support. */
|
|
3574
|
|
3575 /* -- Specifying How Stack Checking is Done. */
|
|
3576
|
|
3577 /* -- Registers That Address the Stack Frame. */
|
|
3578
|
|
3579 /* -- Eliminating Frame Pointer and Arg Pointer. */
|
|
3580
|
|
3581 #undef TARGET_CAN_ELIMINATE
|
|
3582 #define TARGET_CAN_ELIMINATE nds32_can_eliminate
|
|
3583
|
|
3584 /* -- Passing Function Arguments on the Stack. */
|
|
3585
|
|
3586 /* -- Passing Arguments in Registers. */
|
|
3587
|
|
3588 #undef TARGET_FUNCTION_ARG
|
|
3589 #define TARGET_FUNCTION_ARG nds32_function_arg
|
|
3590
|
|
3591 #undef TARGET_MUST_PASS_IN_STACK
|
|
3592 #define TARGET_MUST_PASS_IN_STACK nds32_must_pass_in_stack
|
|
3593
|
|
3594 #undef TARGET_ARG_PARTIAL_BYTES
|
|
3595 #define TARGET_ARG_PARTIAL_BYTES nds32_arg_partial_bytes
|
|
3596
|
|
3597 #undef TARGET_FUNCTION_ARG_ADVANCE
|
|
3598 #define TARGET_FUNCTION_ARG_ADVANCE nds32_function_arg_advance
|
|
3599
|
|
3600 #undef TARGET_FUNCTION_ARG_BOUNDARY
|
|
3601 #define TARGET_FUNCTION_ARG_BOUNDARY nds32_function_arg_boundary
|
|
3602
|
|
3603 /* -- How Scalar Function Values Are Returned. */
|
|
3604
|
|
3605 #undef TARGET_FUNCTION_VALUE
|
|
3606 #define TARGET_FUNCTION_VALUE nds32_function_value
|
|
3607
|
|
3608 #undef TARGET_LIBCALL_VALUE
|
|
3609 #define TARGET_LIBCALL_VALUE nds32_libcall_value
|
|
3610
|
|
3611 #undef TARGET_FUNCTION_VALUE_REGNO_P
|
|
3612 #define TARGET_FUNCTION_VALUE_REGNO_P nds32_function_value_regno_p
|
|
3613
|
|
3614 /* -- How Large Values Are Returned. */
|
|
3615
|
|
3616 /* -- Caller-Saves Register Allocation. */
|
|
3617
|
|
3618 /* -- Function Entry and Exit. */
|
|
3619
|
|
3620 #undef TARGET_ASM_FUNCTION_PROLOGUE
|
|
3621 #define TARGET_ASM_FUNCTION_PROLOGUE nds32_asm_function_prologue
|
|
3622
|
|
3623 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
|
|
3624 #define TARGET_ASM_FUNCTION_END_PROLOGUE nds32_asm_function_end_prologue
|
|
3625
|
|
3626 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
|
|
3627 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE nds32_asm_function_begin_epilogue
|
|
3628
|
|
3629 #undef TARGET_ASM_FUNCTION_EPILOGUE
|
|
3630 #define TARGET_ASM_FUNCTION_EPILOGUE nds32_asm_function_epilogue
|
|
3631
|
|
3632 #undef TARGET_ASM_OUTPUT_MI_THUNK
|
|
3633 #define TARGET_ASM_OUTPUT_MI_THUNK nds32_asm_output_mi_thunk
|
|
3634
|
|
3635 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
|
|
3636 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
|
|
3637
|
|
3638 /* -- Generating Code for Profiling. */
|
|
3639
|
|
3640 /* -- Permitting tail calls. */
|
|
3641
|
|
3642 #undef TARGET_WARN_FUNC_RETURN
|
|
3643 #define TARGET_WARN_FUNC_RETURN nds32_warn_func_return
|
|
3644
|
|
3645 /* Stack smashing protection. */
|
|
3646
|
|
3647
|
|
3648 /* Implementing the Varargs Macros. */
|
|
3649
|
|
3650 #undef TARGET_SETUP_INCOMING_VARARGS
|
|
3651 #define TARGET_SETUP_INCOMING_VARARGS nds32_setup_incoming_varargs
|
|
3652
|
|
3653 #undef TARGET_STRICT_ARGUMENT_NAMING
|
|
3654 #define TARGET_STRICT_ARGUMENT_NAMING nds32_strict_argument_naming
|
|
3655
|
|
3656
|
|
3657 /* Trampolines for Nested Functions. */
|
|
3658
|
|
3659 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
|
|
3660 #define TARGET_ASM_TRAMPOLINE_TEMPLATE nds32_asm_trampoline_template
|
|
3661
|
|
3662 #undef TARGET_TRAMPOLINE_INIT
|
|
3663 #define TARGET_TRAMPOLINE_INIT nds32_trampoline_init
|
|
3664
|
|
3665
|
|
3666 /* Implicit Calls to Library Routines. */
|
|
3667
|
|
3668
|
|
3669 /* Addressing Modes. */
|
|
3670
|
|
3671 #undef TARGET_LEGITIMATE_ADDRESS_P
|
|
3672 #define TARGET_LEGITIMATE_ADDRESS_P nds32_legitimate_address_p
|
|
3673
|
|
3674
|
|
3675 /* Anchored Addresses. */
|
|
3676
|
|
3677
|
|
3678 /* Condition Code Status. */
|
|
3679
|
|
3680 /* -- Representation of condition codes using (cc0). */
|
|
3681
|
|
3682 /* -- Representation of condition codes using registers. */
|
|
3683
|
|
3684 /* -- Macros to control conditional execution. */
|
|
3685
|
|
3686
|
|
3687 /* Describing Relative Costs of Operations. */
|
|
3688
|
|
3689 #undef TARGET_REGISTER_MOVE_COST
|
|
3690 #define TARGET_REGISTER_MOVE_COST nds32_register_move_cost
|
|
3691
|
|
3692 #undef TARGET_MEMORY_MOVE_COST
|
|
3693 #define TARGET_MEMORY_MOVE_COST nds32_memory_move_cost
|
|
3694
|
|
3695 #undef TARGET_RTX_COSTS
|
|
3696 #define TARGET_RTX_COSTS nds32_rtx_costs
|
|
3697
|
|
3698 #undef TARGET_ADDRESS_COST
|
|
3699 #define TARGET_ADDRESS_COST nds32_address_cost
|
|
3700
|
|
3701
|
|
3702 /* Adjusting the Instruction Scheduler. */
|
|
3703
|
|
3704
|
|
3705 /* Dividing the Output into Sections (Texts, Data, . . . ). */
|
|
3706
|
|
3707 #undef TARGET_ENCODE_SECTION_INFO
|
|
3708 #define TARGET_ENCODE_SECTION_INFO nds32_encode_section_info
|
|
3709
|
|
3710
|
|
3711 /* Position Independent Code. */
|
|
3712
|
|
3713
|
|
3714 /* Defining the Output Assembler Language. */
|
|
3715
|
|
3716 /* -- The Overall Framework of an Assembler File. */
|
|
3717
|
|
3718 #undef TARGET_ASM_FILE_START
|
|
3719 #define TARGET_ASM_FILE_START nds32_asm_file_start
|
|
3720 #undef TARGET_ASM_FILE_END
|
|
3721 #define TARGET_ASM_FILE_END nds32_asm_file_end
|
|
3722
|
|
3723 /* -- Output of Data. */
|
|
3724
|
|
3725 #undef TARGET_ASM_ALIGNED_HI_OP
|
|
3726 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
|
|
3727
|
|
3728 #undef TARGET_ASM_ALIGNED_SI_OP
|
|
3729 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
|
|
3730
|
|
3731 /* -- Output of Uninitialized Variables. */
|
|
3732
|
|
3733 /* -- Output and Generation of Labels. */
|
|
3734
|
|
3735 #undef TARGET_ASM_GLOBALIZE_LABEL
|
|
3736 #define TARGET_ASM_GLOBALIZE_LABEL nds32_asm_globalize_label
|
|
3737
|
|
3738 /* -- How Initialization Functions Are Handled. */
|
|
3739
|
|
3740 /* -- Macros Controlling Initialization Routines. */
|
|
3741
|
|
3742 /* -- Output of Assembler Instructions. */
|
|
3743
|
|
3744 #undef TARGET_PRINT_OPERAND
|
|
3745 #define TARGET_PRINT_OPERAND nds32_print_operand
|
|
3746 #undef TARGET_PRINT_OPERAND_ADDRESS
|
|
3747 #define TARGET_PRINT_OPERAND_ADDRESS nds32_print_operand_address
|
|
3748
|
|
3749 /* -- Output of Dispatch Tables. */
|
|
3750
|
|
3751 /* -- Assembler Commands for Exception Regions. */
|
|
3752
|
|
3753 /* -- Assembler Commands for Alignment. */
|
|
3754
|
|
3755
|
|
3756 /* Controlling Debugging Information Format. */
|
|
3757
|
|
3758 /* -- Macros Affecting All Debugging Formats. */
|
|
3759
|
|
3760 /* -- Specific Options for DBX Output. */
|
|
3761
|
|
3762 /* -- Open-Ended Hooks for DBX Format. */
|
|
3763
|
|
3764 /* -- File Names in DBX Format. */
|
|
3765
|
|
3766 /* -- Macros for SDB and DWARF Output. */
|
|
3767
|
|
3768 /* -- Macros for VMS Debug Format. */
|
|
3769
|
|
3770
|
|
3771 /* Cross Compilation and Floating Point. */
|
|
3772
|
|
3773
|
|
3774 /* Mode Switching Instructions. */
|
|
3775
|
|
3776
|
|
3777 /* Defining target-specific uses of __attribute__. */
|
|
3778
|
|
3779 #undef TARGET_ATTRIBUTE_TABLE
|
|
3780 #define TARGET_ATTRIBUTE_TABLE nds32_attribute_table
|
|
3781
|
|
3782 #undef TARGET_MERGE_DECL_ATTRIBUTES
|
|
3783 #define TARGET_MERGE_DECL_ATTRIBUTES nds32_merge_decl_attributes
|
|
3784
|
|
3785 #undef TARGET_INSERT_ATTRIBUTES
|
|
3786 #define TARGET_INSERT_ATTRIBUTES nds32_insert_attributes
|
|
3787
|
|
3788 #undef TARGET_OPTION_PRAGMA_PARSE
|
|
3789 #define TARGET_OPTION_PRAGMA_PARSE nds32_option_pragma_parse
|
|
3790
|
|
3791 #undef TARGET_OPTION_OVERRIDE
|
|
3792 #define TARGET_OPTION_OVERRIDE nds32_option_override
|
|
3793
|
|
3794
|
|
3795 /* Emulating TLS. */
|
|
3796
|
|
3797
|
|
3798 /* Defining coprocessor specifics for MIPS targets. */
|
|
3799
|
|
3800
|
|
3801 /* Parameters for Precompiled Header Validity Checking. */
|
|
3802
|
|
3803
|
|
3804 /* C++ ABI parameters. */
|
|
3805
|
|
3806
|
|
3807 /* Adding support for named address spaces. */
|
|
3808
|
|
3809
|
|
3810 /* Miscellaneous Parameters. */
|
|
3811
|
|
3812 #undef TARGET_INIT_BUILTINS
|
|
3813 #define TARGET_INIT_BUILTINS nds32_init_builtins
|
|
3814
|
|
3815 #undef TARGET_EXPAND_BUILTIN
|
|
3816 #define TARGET_EXPAND_BUILTIN nds32_expand_builtin
|
|
3817
|
|
3818
|
|
3819 /* ------------------------------------------------------------------------ */
|
|
3820
|
|
3821 /* Initialize the GCC target structure. */
|
|
3822
|
|
3823 struct gcc_target targetm = TARGET_INITIALIZER;
|
|
3824
|
|
3825 /* ------------------------------------------------------------------------ */
|