]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/fr30/fr30.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / config / fr30 / fr30.cc
CommitLineData
309dd885 1/* FR30 specific functions.
83ffe9cd 2 Copyright (C) 1998-2023 Free Software Foundation, Inc.
309dd885
NC
3 Contributed by Cygnus Solutions.
4
7ec022b2 5 This file is part of GCC.
309dd885 6
7ec022b2 7 GCC is free software; you can redistribute it and/or modify
b2fc915b 8 it under the terms of the GNU General Public License as published by
2f83c7d6 9 the Free Software Foundation; either version 3, or (at your option)
b2fc915b 10 any later version.
309dd885 11
7ec022b2 12 GCC is distributed in the hope that it will be useful,
b2fc915b
NC
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
309dd885 16
b2fc915b 17 You should have received a copy of the GNU General Public License
2f83c7d6
NC
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
309dd885 20
309dd885
NC
21/*{{{ Includes */
22
8fcc61f8
RS
23#define IN_TARGET_CODE 1
24
309dd885 25#include "config.h"
aeb4f5ef 26#include "system.h"
4977bab6 27#include "coretypes.h"
c7131fb2 28#include "backend.h"
e11c4407 29#include "target.h"
309dd885 30#include "rtl.h"
e11c4407 31#include "tree.h"
314e6352
ML
32#include "stringpool.h"
33#include "attribs.h"
c7131fb2 34#include "df.h"
4d0cdd0c 35#include "memmodel.h"
e11c4407 36#include "emit-rtl.h"
d8a2d370
DN
37#include "stor-layout.h"
38#include "varasm.h"
b2fc915b 39#include "output.h"
309dd885 40#include "expr.h"
9b2b7279 41#include "builtins.h"
a7c81bc1 42#include "calls.h"
309dd885 43
994c5d85 44/* This file should be included last. */
d58627a0
RS
45#include "target-def.h"
46
309dd885
NC
47/*}}}*/
48/*{{{ Function Prologues & Epilogues */
49
309dd885
NC
50/* The FR30 stack looks like this:
51
52 Before call After call
53 FP ->| | | |
54 +-----------------------+ +-----------------------+ high
55 | | | | memory
56 | local variables, | | local variables, |
57 | reg save area, etc. | | reg save area, etc. |
58 | | | |
59 +-----------------------+ +-----------------------+
60 | | | |
61 | args to the func that | | args to this func. |
62 | is being called that | | |
63 SP ->| do not fit in regs | | |
64 +-----------------------+ +-----------------------+
65 | args that used to be | \
66 | in regs; only created | | pretend_size
67 AP-> | for vararg funcs | /
68 +-----------------------+
69 | | \
70 | register save area | |
71 | | |
72 +-----------------------+ | reg_size
73 | return address | |
74 +-----------------------+ |
75 FP ->| previous frame ptr | /
76 +-----------------------+
77 | | \
78 | local variables | | var_size
79 | | /
80 +-----------------------+
81 | | \
82 low | room for args to | |
83 memory | other funcs called | | args_size
84 | from this one | |
85 SP ->| | /
86 +-----------------------+
87
9cd10576 88 Note, AP is a fake hard register. It will be eliminated in favor of
309dd885
NC
89 SP or FP as appropriate.
90
91 Note, Some or all of the stack sections above may be omitted if they
92 are not needed. */
93
94/* Structure to be filled in by fr30_compute_frame_size() with register
95 save masks, and offsets for the current function. */
96struct fr30_frame_info
97{
ff482c8d
KH
98 unsigned int total_size; /* # Bytes that the entire frame takes up. */
99 unsigned int pretend_size; /* # Bytes we push and pretend caller did. */
100 unsigned int args_size; /* # Bytes that outgoing arguments take up. */
101 unsigned int reg_size; /* # Bytes needed to store regs. */
102 unsigned int var_size; /* # Bytes that variables take up. */
309dd885 103 unsigned int frame_size; /* # Bytes in current frame. */
ff482c8d
KH
104 unsigned int gmask; /* Mask of saved registers. */
105 unsigned int save_fp; /* Nonzero if frame pointer must be saved. */
106 unsigned int save_rp; /* Nonzero if return pointer must be saved. */
107 int initialised; /* Nonzero if frame size already calculated. */
309dd885
NC
108};
109
110/* Current frame information calculated by fr30_compute_frame_size(). */
111static struct fr30_frame_info current_frame_info;
112
113/* Zero structure to initialize current_frame_info. */
114static struct fr30_frame_info zero_frame_info;
115
e7056ca4
RS
116static void fr30_setup_incoming_varargs (cumulative_args_t,
117 const function_arg_info &,
118 int *, int);
0ffef200 119static bool fr30_must_pass_in_stack (const function_arg_info &);
a7c81bc1
RS
120static int fr30_arg_partial_bytes (cumulative_args_t,
121 const function_arg_info &);
6783fdb7 122static rtx fr30_function_arg (cumulative_args_t, const function_arg_info &);
6930c98c
RS
123static void fr30_function_arg_advance (cumulative_args_t,
124 const function_arg_info &);
b52b1749 125static bool fr30_frame_pointer_required (void);
da0dc818 126static rtx fr30_function_value (const_tree, const_tree, bool);
ef4bddc2 127static rtx fr30_libcall_value (machine_mode, const_rtx);
da0dc818 128static bool fr30_function_value_regno_p (const unsigned int);
7b5cbb57 129static bool fr30_can_eliminate (const int, const int);
98689f5e
RH
130static void fr30_asm_trampoline_template (FILE *);
131static void fr30_trampoline_init (rtx, tree, rtx);
0ffef200 132static int fr30_num_arg_regs (const function_arg_info &);
1943c2c1 133
309dd885
NC
134#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
135#define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM))
136
137/* Tell prologue and epilogue if register REGNO should be saved / restored.
138 The return address and frame pointer are treated separately.
139 Don't consider them here. */
140#define MUST_SAVE_REGISTER(regno) \
141 ( (regno) != RETURN_POINTER_REGNUM \
142 && (regno) != FRAME_POINTER_REGNUM \
6fb5fa3c 143 && df_regs_ever_live_p (regno) \
a365fa06 144 && ! call_used_or_fixed_reg_p (regno))
309dd885 145
6fb5fa3c 146#define MUST_SAVE_FRAME_POINTER (df_regs_ever_live_p (FRAME_POINTER_REGNUM) || frame_pointer_needed)
e3b5732b 147#define MUST_SAVE_RETURN_POINTER (df_regs_ever_live_p (RETURN_POINTER_REGNUM) || crtl->profile)
309dd885
NC
148
149#if UNITS_PER_WORD == 4
150#define WORD_ALIGN(SIZE) (((SIZE) + 3) & ~3)
151#endif
672a6f42
NB
152\f
153/* Initialize the GCC target structure. */
6b66447a 154#undef TARGET_ASM_ALIGNED_HI_OP
301d03af 155#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
6b66447a 156#undef TARGET_ASM_ALIGNED_SI_OP
301d03af 157#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
672a6f42 158
6b66447a 159#undef TARGET_PROMOTE_PROTOTYPES
586de218 160#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
8cd5a4e0
RH
161#undef TARGET_PASS_BY_REFERENCE
162#define TARGET_PASS_BY_REFERENCE hook_pass_by_reference_must_pass_in_stack
78a52f11
RH
163#undef TARGET_ARG_PARTIAL_BYTES
164#define TARGET_ARG_PARTIAL_BYTES fr30_arg_partial_bytes
b60613c3
NF
165#undef TARGET_FUNCTION_ARG
166#define TARGET_FUNCTION_ARG fr30_function_arg
167#undef TARGET_FUNCTION_ARG_ADVANCE
168#define TARGET_FUNCTION_ARG_ADVANCE fr30_function_arg_advance
8cd5a4e0 169
da0dc818
AS
170#undef TARGET_FUNCTION_VALUE
171#define TARGET_FUNCTION_VALUE fr30_function_value
172#undef TARGET_LIBCALL_VALUE
173#define TARGET_LIBCALL_VALUE fr30_libcall_value
174#undef TARGET_FUNCTION_VALUE_REGNO_P
175#define TARGET_FUNCTION_VALUE_REGNO_P fr30_function_value_regno_p
176
6b66447a 177#undef TARGET_SETUP_INCOMING_VARARGS
3e29e2aa 178#define TARGET_SETUP_INCOMING_VARARGS fr30_setup_incoming_varargs
fe984136
RH
179#undef TARGET_MUST_PASS_IN_STACK
180#define TARGET_MUST_PASS_IN_STACK fr30_must_pass_in_stack
181
b52b1749
AS
182#undef TARGET_FRAME_POINTER_REQUIRED
183#define TARGET_FRAME_POINTER_REQUIRED fr30_frame_pointer_required
184
7b5cbb57
AS
185#undef TARGET_CAN_ELIMINATE
186#define TARGET_CAN_ELIMINATE fr30_can_eliminate
187
d81db636
SB
188#undef TARGET_LRA_P
189#define TARGET_LRA_P hook_bool_void_false
190
98689f5e
RH
191#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
192#define TARGET_ASM_TRAMPOLINE_TEMPLATE fr30_asm_trampoline_template
193#undef TARGET_TRAMPOLINE_INIT
194#define TARGET_TRAMPOLINE_INIT fr30_trampoline_init
195
58e17cf8
RS
196#undef TARGET_CONSTANT_ALIGNMENT
197#define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
198
aa429991
NC
199#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
200#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
201
f6897b10 202struct gcc_target targetm = TARGET_INITIALIZER;
672a6f42 203\f
7b5cbb57
AS
204
205/* Worker function for TARGET_CAN_ELIMINATE. */
206
207bool
208fr30_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
209{
210 return (to == FRAME_POINTER_REGNUM || ! frame_pointer_needed);
211}
212
309dd885
NC
213/* Returns the number of bytes offset between FROM_REG and TO_REG
214 for the current function. As a side effect it fills in the
215 current_frame_info structure, if the data is available. */
216unsigned int
f1777882 217fr30_compute_frame_size (int from_reg, int to_reg)
309dd885
NC
218{
219 int regno;
220 unsigned int return_value;
221 unsigned int var_size;
222 unsigned int args_size;
223 unsigned int pretend_size;
224 unsigned int reg_size;
225 unsigned int gmask;
226
227 var_size = WORD_ALIGN (get_frame_size ());
38173d38
JH
228 args_size = WORD_ALIGN (crtl->outgoing_args_size);
229 pretend_size = crtl->args.pretend_args_size;
309dd885
NC
230
231 reg_size = 0;
232 gmask = 0;
233
234 /* Calculate space needed for registers. */
235 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++)
236 {
237 if (MUST_SAVE_REGISTER (regno))
238 {
239 reg_size += UNITS_PER_WORD;
240 gmask |= 1 << regno;
241 }
242 }
243
244 current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER;
245 current_frame_info.save_rp = MUST_SAVE_RETURN_POINTER;
246
247 reg_size += (current_frame_info.save_fp + current_frame_info.save_rp)
248 * UNITS_PER_WORD;
249
250 /* Save computed information. */
251 current_frame_info.pretend_size = pretend_size;
252 current_frame_info.var_size = var_size;
253 current_frame_info.args_size = args_size;
254 current_frame_info.reg_size = reg_size;
255 current_frame_info.frame_size = args_size + var_size;
256 current_frame_info.total_size = args_size + var_size + reg_size + pretend_size;
257 current_frame_info.gmask = gmask;
258 current_frame_info.initialised = reload_completed;
259
260 /* Calculate the required distance. */
261 return_value = 0;
262
263 if (to_reg == STACK_POINTER_REGNUM)
264 return_value += args_size + var_size;
265
266 if (from_reg == ARG_POINTER_REGNUM)
267 return_value += reg_size;
268
269 return return_value;
270}
271
272/* Called after register allocation to add any instructions needed for the
273 prologue. Using a prologue insn is favored compared to putting all of the
08c148a8 274 instructions in output_function_prologue(), since it allows the scheduler
309dd885
NC
275 to intermix instructions with the saves of the caller saved registers. In
276 some cases, it might be necessary to emit a barrier instruction as the last
277 insn to prevent such scheduling. */
278
279void
f1777882 280fr30_expand_prologue (void)
309dd885
NC
281{
282 int regno;
283 rtx insn;
284
285 if (! current_frame_info.initialised)
286 fr30_compute_frame_size (0, 0);
287
288 /* This cases shouldn't happen. Catch it now. */
4e81e7c2 289 gcc_assert (current_frame_info.total_size || !current_frame_info.gmask);
309dd885
NC
290
291 /* Allocate space for register arguments if this is a variadic function. */
292 if (current_frame_info.pretend_size)
293 {
294 int regs_to_save = current_frame_info.pretend_size / UNITS_PER_WORD;
295
296 /* Push argument registers into the pretend arg area. */
297 for (regno = FIRST_ARG_REGNUM + FR30_NUM_ARG_REGS; regno --, regs_to_save --;)
298 {
299 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
300 RTX_FRAME_RELATED_P (insn) = 1;
301 }
302 }
303
304 if (current_frame_info.gmask)
305 {
306 /* Save any needed call-saved regs. */
307 for (regno = STACK_POINTER_REGNUM; regno--;)
308 {
309 if ((current_frame_info.gmask & (1 << regno)) != 0)
310 {
311 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
312 RTX_FRAME_RELATED_P (insn) = 1;
313 }
314 }
315 }
316
317 /* Save return address if necessary. */
318 if (current_frame_info.save_rp)
319 {
320 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode,
321 RETURN_POINTER_REGNUM)));
322 RTX_FRAME_RELATED_P (insn) = 1;
323 }
324
325 /* Save old frame pointer and create new one, if necessary. */
326 if (current_frame_info.save_fp)
327 {
328 if (current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
329 {
330 int enter_size = current_frame_info.frame_size + UNITS_PER_WORD;
331 rtx pattern;
332
333 insn = emit_insn (gen_enter_func (GEN_INT (enter_size)));
334 RTX_FRAME_RELATED_P (insn) = 1;
335
336 pattern = PATTERN (insn);
337
338 /* Also mark all 3 subexpressions as RTX_FRAME_RELATED_P. */
339 if (GET_CODE (pattern) == PARALLEL)
340 {
341 int x;
342 for (x = XVECLEN (pattern, 0); x--;)
343 {
344 rtx part = XVECEXP (pattern, 0, x);
345
346 /* One of the insns in the ENTER pattern updates the
347 frame pointer. If we do not actually need the frame
348 pointer in this function then this is a side effect
349 rather than a desired effect, so we do not mark that
350 insn as being related to the frame set up. Doing this
351 allows us to compile the crash66.C test file in the
352 G++ testsuite. */
353 if (! frame_pointer_needed
354 && GET_CODE (part) == SET
e2972de5 355 && SET_DEST (part) == hard_frame_pointer_rtx)
309dd885
NC
356 RTX_FRAME_RELATED_P (part) = 0;
357 else
358 RTX_FRAME_RELATED_P (part) = 1;
359 }
360 }
361 }
362 else
363 {
364 insn = emit_insn (gen_movsi_push (frame_pointer_rtx));
365 RTX_FRAME_RELATED_P (insn) = 1;
366
367 if (frame_pointer_needed)
368 {
369 insn = emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
370 RTX_FRAME_RELATED_P (insn) = 1;
371 }
372 }
373 }
374
375 /* Allocate the stack frame. */
376 if (current_frame_info.frame_size == 0)
377 ; /* Nothing to do. */
378 else if (current_frame_info.save_fp
379 && current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
380 ; /* Nothing to do. */
381 else if (current_frame_info.frame_size <= 512)
382 {
e2972de5
RIL
383 insn = emit_insn (gen_add_to_stack
384 (GEN_INT (- (signed) current_frame_info.frame_size)));
309dd885
NC
385 RTX_FRAME_RELATED_P (insn) = 1;
386 }
387 else
388 {
389 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
390 insn = emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
391 RTX_FRAME_RELATED_P (insn) = 1;
392 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
393 RTX_FRAME_RELATED_P (insn) = 1;
394 }
395
e3b5732b 396 if (crtl->profile)
309dd885
NC
397 emit_insn (gen_blockage ());
398}
399
400/* Called after register allocation to add any instructions needed for the
5519a4f9 401 epilogue. Using an epilogue insn is favored compared to putting all of the
08c148a8 402 instructions in output_function_epilogue(), since it allows the scheduler
309dd885
NC
403 to intermix instructions with the restores of the caller saved registers.
404 In some cases, it might be necessary to emit a barrier instruction as the
405 first insn to prevent such scheduling. */
406void
f1777882 407fr30_expand_epilogue (void)
309dd885
NC
408{
409 int regno;
410
411 /* Perform the inversion operations of the prologue. */
4e81e7c2
NS
412 gcc_assert (current_frame_info.initialised);
413
309dd885
NC
414 /* Pop local variables and arguments off the stack.
415 If frame_pointer_needed is TRUE then the frame pointer register
416 has actually been used as a frame pointer, and we can recover
417 the stack pointer from it, otherwise we must unwind the stack
418 manually. */
419 if (current_frame_info.frame_size > 0)
420 {
421 if (current_frame_info.save_fp && frame_pointer_needed)
422 {
423 emit_insn (gen_leave_func ());
424 current_frame_info.save_fp = 0;
425 }
426 else if (current_frame_info.frame_size <= 508)
427 emit_insn (gen_add_to_stack
428 (GEN_INT (current_frame_info.frame_size)));
429 else
430 {
431 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
432 emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
433 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
434 }
435 }
436
437 if (current_frame_info.save_fp)
438 emit_insn (gen_movsi_pop (frame_pointer_rtx));
439
440 /* Pop all the registers that were pushed. */
441 if (current_frame_info.save_rp)
442 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, RETURN_POINTER_REGNUM)));
443
444 for (regno = 0; regno < STACK_POINTER_REGNUM; regno ++)
445 if (current_frame_info.gmask & (1 << regno))
c99df684 446 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno)));
309dd885
NC
447
448 if (current_frame_info.pretend_size)
449 emit_insn (gen_add_to_stack (GEN_INT (current_frame_info.pretend_size)));
450
451 /* Reset state info for each function. */
452 current_frame_info = zero_frame_info;
453
c99df684 454 emit_jump_insn (gen_return_from_func ());
309dd885
NC
455}
456
457/* Do any needed setup for a variadic function. We must create a register
458 parameter block, and then copy any anonymous arguments, plus the last
459 named argument, from registers into memory. * copying actually done in
460 fr30_expand_prologue().
461
e7056ca4
RS
462 CUM has not been updated for the last named argument which has type TYPE
463 and mode MODE, and we rely on this fact. */
309dd885 464void
d5cc9181 465fr30_setup_incoming_varargs (cumulative_args_t arg_regs_used_so_far_v,
e7056ca4 466 const function_arg_info &arg,
6b66447a
NC
467 int *pretend_size,
468 int second_time ATTRIBUTE_UNUSED)
309dd885 469{
d5cc9181
JR
470 CUMULATIVE_ARGS *arg_regs_used_so_far
471 = get_cumulative_args (arg_regs_used_so_far_v);
6b66447a 472 int size;
309dd885 473
4fe34cdc
JM
474 if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl)))
475 {
476 /* All BLKmode values are passed by reference. */
477 gcc_assert (arg.mode != BLKmode);
478
479 /* ??? This run-time test as well as the code inside the if
480 statement is probably unnecessary. */
481 if (targetm.calls.strict_argument_naming (arg_regs_used_so_far_v))
482 /* If TARGET_STRICT_ARGUMENT_NAMING returns true, then the last named
483 arg must not be treated as an anonymous arg. */
484 /* ??? This is a pointer increment, which makes no sense. */
485 arg_regs_used_so_far += fr30_num_arg_regs (arg);
486 }
6b66447a
NC
487
488 size = FR30_NUM_ARG_REGS - (* arg_regs_used_so_far);
309dd885
NC
489
490 if (size <= 0)
491 return;
492
493 * pretend_size = (size * UNITS_PER_WORD);
494}
495
496/*}}}*/
497/*{{{ Printing operands */
498
499/* Print a memory address as an operand to reference that memory location. */
500
501void
f1777882 502fr30_print_operand_address (FILE *stream, rtx address)
309dd885
NC
503{
504 switch (GET_CODE (address))
505 {
506 case SYMBOL_REF:
507 output_addr_const (stream, address);
508 break;
509
510 default:
511 fprintf (stderr, "code = %x\n", GET_CODE (address));
512 debug_rtx (address);
513 output_operand_lossage ("fr30_print_operand_address: unhandled address");
514 break;
515 }
516}
517
518/* Print an operand. */
519
520void
f1777882 521fr30_print_operand (FILE *file, rtx x, int code)
309dd885
NC
522{
523 rtx x0;
524
525 switch (code)
526 {
527 case '#':
528 /* Output a :D if this instruction is delayed. */
529 if (dbr_sequence_length () != 0)
530 fputs (":D", file);
531 return;
532
533 case 'p':
534 /* Compute the register name of the second register in a hi/lo
535 register pair. */
536 if (GET_CODE (x) != REG)
a52453cc 537 output_operand_lossage ("fr30_print_operand: unrecognized %%p code");
309dd885
NC
538 else
539 fprintf (file, "r%d", REGNO (x) + 1);
540 return;
541
542 case 'b':
543 /* Convert GCC's comparison operators into FR30 comparison codes. */
544 switch (GET_CODE (x))
545 {
546 case EQ: fprintf (file, "eq"); break;
547 case NE: fprintf (file, "ne"); break;
548 case LT: fprintf (file, "lt"); break;
549 case LE: fprintf (file, "le"); break;
550 case GT: fprintf (file, "gt"); break;
551 case GE: fprintf (file, "ge"); break;
552 case LTU: fprintf (file, "c"); break;
553 case LEU: fprintf (file, "ls"); break;
554 case GTU: fprintf (file, "hi"); break;
555 case GEU: fprintf (file, "nc"); break;
556 default:
a52453cc 557 output_operand_lossage ("fr30_print_operand: unrecognized %%b code");
309dd885
NC
558 break;
559 }
560 return;
561
562 case 'B':
563 /* Convert GCC's comparison operators into the complimentary FR30
564 comparison codes. */
565 switch (GET_CODE (x))
566 {
567 case EQ: fprintf (file, "ne"); break;
568 case NE: fprintf (file, "eq"); break;
569 case LT: fprintf (file, "ge"); break;
570 case LE: fprintf (file, "gt"); break;
571 case GT: fprintf (file, "le"); break;
572 case GE: fprintf (file, "lt"); break;
573 case LTU: fprintf (file, "nc"); break;
574 case LEU: fprintf (file, "hi"); break;
575 case GTU: fprintf (file, "ls"); break;
576 case GEU: fprintf (file, "c"); break;
577 default:
a52453cc 578 output_operand_lossage ("fr30_print_operand: unrecognized %%B code");
309dd885
NC
579 break;
580 }
581 return;
582
583 case 'A':
584 /* Print a signed byte value as an unsigned value. */
585 if (GET_CODE (x) != CONST_INT)
a52453cc 586 output_operand_lossage ("fr30_print_operand: invalid operand to %%A code");
309dd885
NC
587 else
588 {
589 HOST_WIDE_INT val;
590
591 val = INTVAL (x);
592
593 val &= 0xff;
594
1bdfacf6 595 fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
309dd885
NC
596 }
597 return;
598
599 case 'x':
600 if (GET_CODE (x) != CONST_INT
601 || INTVAL (x) < 16
602 || INTVAL (x) > 32)
a52453cc 603 output_operand_lossage ("fr30_print_operand: invalid %%x code");
309dd885 604 else
1bdfacf6 605 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) - 16);
309dd885
NC
606 return;
607
608 case 'F':
609 if (GET_CODE (x) != CONST_DOUBLE)
a52453cc 610 output_operand_lossage ("fr30_print_operand: invalid %%F code");
309dd885
NC
611 else
612 {
c1b4f089 613 char str[30];
309dd885 614
da6eec72
RH
615 real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x),
616 sizeof (str), 0, 1);
c1b4f089 617 fputs (str, file);
309dd885
NC
618 }
619 return;
620
621 case 0:
622 /* Handled below. */
623 break;
624
625 default:
626 fprintf (stderr, "unknown code = %x\n", code);
627 output_operand_lossage ("fr30_print_operand: unknown code");
628 return;
629 }
630
631 switch (GET_CODE (x))
632 {
633 case REG:
634 fputs (reg_names [REGNO (x)], file);
635 break;
636
637 case MEM:
638 x0 = XEXP (x,0);
639
640 switch (GET_CODE (x0))
641 {
642 case REG:
4e81e7c2 643 gcc_assert ((unsigned) REGNO (x0) < ARRAY_SIZE (reg_names));
309dd885
NC
644 fprintf (file, "@%s", reg_names [REGNO (x0)]);
645 break;
646
647 case PLUS:
648 if (GET_CODE (XEXP (x0, 0)) != REG
649 || REGNO (XEXP (x0, 0)) < FRAME_POINTER_REGNUM
650 || REGNO (XEXP (x0, 0)) > STACK_POINTER_REGNUM
651 || GET_CODE (XEXP (x0, 1)) != CONST_INT)
652 {
653 fprintf (stderr, "bad INDEXed address:");
654 debug_rtx (x);
655 output_operand_lossage ("fr30_print_operand: unhandled MEM");
656 }
657 else if (REGNO (XEXP (x0, 0)) == FRAME_POINTER_REGNUM)
658 {
659 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
660 if (val < -(1 << 9) || val > ((1 << 9) - 4))
661 {
662 fprintf (stderr, "frame INDEX out of range:");
663 debug_rtx (x);
664 output_operand_lossage ("fr30_print_operand: unhandled MEM");
665 }
1bdfacf6 666 fprintf (file, "@(r14, #" HOST_WIDE_INT_PRINT_DEC ")", val);
309dd885
NC
667 }
668 else
669 {
670 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
671 if (val < 0 || val > ((1 << 6) - 4))
672 {
673 fprintf (stderr, "stack INDEX out of range:");
674 debug_rtx (x);
675 output_operand_lossage ("fr30_print_operand: unhandled MEM");
676 }
1bdfacf6 677 fprintf (file, "@(r15, #" HOST_WIDE_INT_PRINT_DEC ")", val);
309dd885
NC
678 }
679 break;
680
681 case SYMBOL_REF:
cc8ca59e 682 output_address (VOIDmode, x0);
309dd885
NC
683 break;
684
685 default:
686 fprintf (stderr, "bad MEM code = %x\n", GET_CODE (x0));
687 debug_rtx (x);
688 output_operand_lossage ("fr30_print_operand: unhandled MEM");
689 break;
690 }
691 break;
692
693 case CONST_DOUBLE :
694 /* We handle SFmode constants here as output_addr_const doesn't. */
695 if (GET_MODE (x) == SFmode)
696 {
309dd885
NC
697 long l;
698
34a72c33 699 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), l);
309dd885
NC
700 fprintf (file, "0x%08lx", l);
701 break;
702 }
703
32502b58
JL
704 /* FALLTHRU */
705 /* Let output_addr_const deal with it. */
309dd885
NC
706 default:
707 output_addr_const (file, x);
708 break;
709 }
710
711 return;
712}
713
714/*}}}*/
da0dc818
AS
715
716/* Implements TARGET_FUNCTION_VALUE. */
717
718static rtx
719fr30_function_value (const_tree valtype,
720 const_tree fntype_or_decli ATTRIBUTE_UNUSED,
721 bool outgoing ATTRIBUTE_UNUSED)
722{
723 return gen_rtx_REG (TYPE_MODE (valtype), RETURN_VALUE_REGNUM);
724}
725
726/* Implements TARGET_LIBCALL_VALUE. */
727
728static rtx
ef4bddc2 729fr30_libcall_value (machine_mode mode,
da0dc818
AS
730 const_rtx fun ATTRIBUTE_UNUSED)
731{
732 return gen_rtx_REG (mode, RETURN_VALUE_REGNUM);
733}
734
735/* Implements TARGET_FUNCTION_VALUE_REGNO_P. */
736
737static bool
738fr30_function_value_regno_p (const unsigned int regno)
739{
740 return (regno == RETURN_VALUE_REGNUM);
741}
742
309dd885
NC
743/*{{{ Function arguments */
744
fe984136
RH
745/* Return true if we should pass an argument on the stack rather than
746 in registers. */
747
748static bool
0ffef200 749fr30_must_pass_in_stack (const function_arg_info &arg)
fe984136 750{
0ffef200 751 return arg.mode == BLKmode || arg.aggregate_type_p ();
fe984136
RH
752}
753
0ffef200
RS
754/* Compute the number of word sized registers needed to hold function
755 argument ARG. */
b60613c3 756static int
0ffef200 757fr30_num_arg_regs (const function_arg_info &arg)
309dd885 758{
0ffef200 759 if (targetm.calls.must_pass_in_stack (arg))
309dd885
NC
760 return 0;
761
0ffef200 762 int size = arg.promoted_size_in_bytes ();
309dd885
NC
763 return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
764}
765
a7c81bc1
RS
766/* Returns the number of bytes of argument registers required to hold *part*
767 of argument ARG. If the argument fits entirely in the argument registers,
768 or entirely on the stack, then 0 is returned. CUM is the number of
769 argument registers already used by earlier parameters to the function. */
309dd885 770
78a52f11 771static int
a7c81bc1 772fr30_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
309dd885 773{
d5cc9181
JR
774 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
775
112cdef5 776 /* Unnamed arguments, i.e. those that are prototyped as ...
309dd885
NC
777 are always passed on the stack.
778 Also check here to see if all the argument registers are full. */
a7c81bc1 779 if (!arg.named || *cum >= FR30_NUM_ARG_REGS)
309dd885
NC
780 return 0;
781
782 /* Work out how many argument registers would be needed if this
783 parameter were to be passed entirely in registers. If there
784 are sufficient argument registers available (or if no registers
785 are needed because the parameter must be passed on the stack)
786 then return zero, as this parameter does not require partial
700d4cb0 787 register, partial stack space. */
0ffef200 788 if (*cum + fr30_num_arg_regs (arg) <= FR30_NUM_ARG_REGS)
309dd885
NC
789 return 0;
790
78a52f11 791 return (FR30_NUM_ARG_REGS - *cum) * UNITS_PER_WORD;
309dd885
NC
792}
793
b60613c3 794static rtx
6783fdb7 795fr30_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
b60613c3 796{
d5cc9181
JR
797 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
798
6783fdb7 799 if (!arg.named
0ffef200 800 || fr30_must_pass_in_stack (arg)
b60613c3
NF
801 || *cum >= FR30_NUM_ARG_REGS)
802 return NULL_RTX;
803 else
6783fdb7 804 return gen_rtx_REG (arg.mode, *cum + FIRST_ARG_REGNUM);
b60613c3
NF
805}
806
6930c98c 807/* Implement TARGET_FUNCTION_ARG_ADVANCE. */
b60613c3 808static void
6930c98c
RS
809fr30_function_arg_advance (cumulative_args_t cum,
810 const function_arg_info &arg)
b60613c3 811{
6930c98c 812 if (arg.named)
0ffef200 813 *get_cumulative_args (cum) += fr30_num_arg_regs (arg);
b60613c3
NF
814}
815
309dd885
NC
816/*}}}*/
817/*{{{ Operand predicates */
818
82a9bba5 819#ifndef Mmode
ef4bddc2 820#define Mmode machine_mode
82a9bba5
NC
821#endif
822
309dd885
NC
823/* Returns true iff all the registers in the operands array
824 are in descending or ascending order. */
825int
f1777882 826fr30_check_multiple_regs (rtx *operands, int num_operands, int descending)
309dd885
NC
827{
828 if (descending)
829 {
aeb4f5ef 830 unsigned int prev_regno = 0;
309dd885 831
aeb4f5ef 832 while (num_operands --)
309dd885
NC
833 {
834 if (GET_CODE (operands [num_operands]) != REG)
835 return 0;
836
837 if (REGNO (operands [num_operands]) < prev_regno)
838 return 0;
839
840 prev_regno = REGNO (operands [num_operands]);
841 }
842 }
843 else
844 {
aeb4f5ef 845 unsigned int prev_regno = CONDITION_CODE_REGNUM;
309dd885 846
aeb4f5ef 847 while (num_operands --)
309dd885
NC
848 {
849 if (GET_CODE (operands [num_operands]) != REG)
850 return 0;
851
852 if (REGNO (operands [num_operands]) > prev_regno)
853 return 0;
854
855 prev_regno = REGNO (operands [num_operands]);
856 }
857 }
858
859 return 1;
860}
861
3d5ee65b 862int
f1777882 863fr30_const_double_is_zero (rtx operand)
3d5ee65b 864{
3d5ee65b
NC
865 if (operand == NULL || GET_CODE (operand) != CONST_DOUBLE)
866 return 0;
867
34a72c33 868 return real_equal (CONST_DOUBLE_REAL_VALUE (operand), &dconst0);
3d5ee65b
NC
869}
870
aeb4f5ef
NC
871/*}}}*/
872/*{{{ Instruction Output Routines */
873
874/* Output a double word move.
875 It must be REG<-REG, REG<-MEM, MEM<-REG or REG<-CONST.
839a4992 876 On the FR30 we are constrained by the fact that it does not
aeb4f5ef
NC
877 support offsetable addresses, and so we have to load the
878 address of the secnd word into the second destination register
879 before we can use it. */
880
881rtx
f1777882 882fr30_move_double (rtx * operands)
aeb4f5ef
NC
883{
884 rtx src = operands[1];
885 rtx dest = operands[0];
886 enum rtx_code src_code = GET_CODE (src);
887 enum rtx_code dest_code = GET_CODE (dest);
ef4bddc2 888 machine_mode mode = GET_MODE (dest);
aeb4f5ef
NC
889 rtx val;
890
891 start_sequence ();
892
893 if (dest_code == REG)
894 {
895 if (src_code == REG)
896 {
897 int reverse = (REGNO (dest) == REGNO (src) + 1);
898
899 /* We normally copy the low-numbered register first. However, if
900 the first register of operand 0 is the same as the second register
901 of operand 1, we must copy in the opposite order. */
f7df4a84 902 emit_insn (gen_rtx_SET (operand_subword (dest, reverse, TRUE, mode),
aeb4f5ef
NC
903 operand_subword (src, reverse, TRUE, mode)));
904
f7df4a84
RS
905 emit_insn
906 (gen_rtx_SET (operand_subword (dest, !reverse, TRUE, mode),
907 operand_subword (src, !reverse, TRUE, mode)));
aeb4f5ef
NC
908 }
909 else if (src_code == MEM)
910 {
911 rtx addr = XEXP (src, 0);
08350106
NF
912 rtx dest0 = operand_subword (dest, 0, TRUE, mode);
913 rtx dest1 = operand_subword (dest, 1, TRUE, mode);
aeb4f5ef
NC
914 rtx new_mem;
915
4e81e7c2 916 gcc_assert (GET_CODE (addr) == REG);
aeb4f5ef 917
916a659b 918 /* Copy the address before clobbering it. See PR 34174. */
f7df4a84
RS
919 emit_insn (gen_rtx_SET (dest1, addr));
920 emit_insn (gen_rtx_SET (dest0, adjust_address (src, SImode, 0)));
921 emit_insn (gen_rtx_SET (dest1, plus_constant (SImode, dest1,
922 UNITS_PER_WORD)));
916a659b
RIL
923
924 new_mem = gen_rtx_MEM (SImode, dest1);
925 MEM_COPY_ATTRIBUTES (new_mem, src);
aeb4f5ef 926
f7df4a84 927 emit_insn (gen_rtx_SET (dest1, new_mem));
aeb4f5ef
NC
928 }
929 else if (src_code == CONST_INT || src_code == CONST_DOUBLE)
930 {
931 rtx words[2];
932 split_double (src, &words[0], &words[1]);
f7df4a84 933 emit_insn (gen_rtx_SET (operand_subword (dest, 0, TRUE, mode),
aeb4f5ef
NC
934 words[0]));
935
f7df4a84 936 emit_insn (gen_rtx_SET (operand_subword (dest, 1, TRUE, mode),
aeb4f5ef
NC
937 words[1]));
938 }
939 }
940 else if (src_code == REG && dest_code == MEM)
941 {
942 rtx addr = XEXP (dest, 0);
943 rtx src0;
944 rtx src1;
945
4e81e7c2 946 gcc_assert (GET_CODE (addr) == REG);
ed31d14c 947
aeb4f5ef
NC
948 src0 = operand_subword (src, 0, TRUE, mode);
949 src1 = operand_subword (src, 1, TRUE, mode);
ed31d14c
LP
950
951 emit_move_insn (adjust_address (dest, SImode, 0), src0);
f4ef873c
RK
952
953 if (REGNO (addr) == STACK_POINTER_REGNUM
954 || REGNO (addr) == FRAME_POINTER_REGNUM)
f7df4a84 955 emit_insn (gen_rtx_SET (adjust_address (dest, SImode, UNITS_PER_WORD),
f4ef873c 956 src1));
aeb4f5ef
NC
957 else
958 {
959 rtx new_mem;
ed31d14c
LP
960 rtx scratch_reg_r0 = gen_rtx_REG (SImode, 0);
961
aeb4f5ef 962 /* We need a scratch register to hold the value of 'address + 4'.
ed31d14c
LP
963 We use r0 for this purpose. It is used for example for long
964 jumps and is already marked to not be used by normal register
965 allocation. */
966 emit_insn (gen_movsi_internal (scratch_reg_r0, addr));
967 emit_insn (gen_addsi_small_int (scratch_reg_r0, scratch_reg_r0,
968 GEN_INT (UNITS_PER_WORD)));
969 new_mem = gen_rtx_MEM (SImode, scratch_reg_r0);
aeb4f5ef 970 MEM_COPY_ATTRIBUTES (new_mem, dest);
ed31d14c
LP
971 emit_move_insn (new_mem, src1);
972 emit_insn (gen_blockage ());
aeb4f5ef
NC
973 }
974 }
975 else
f710504c 976 /* This should have been prevented by the constraints on movdi_insn. */
4e81e7c2 977 gcc_unreachable ();
ed31d14c 978
2f937369 979 val = get_insns ();
aeb4f5ef
NC
980 end_sequence ();
981
982 return val;
983}
ed31d14c 984
b52b1749
AS
985/* Implement TARGET_FRAME_POINTER_REQUIRED. */
986
987bool
988fr30_frame_pointer_required (void)
989{
990 return (flag_omit_frame_pointer == 0 || crtl->args.pretend_args_size > 0);
991}
992
98689f5e
RH
993/*}}}*/
994/*{{{ Trampoline Output Routines */
995
996/* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE.
997 On the FR30, the trampoline is:
998
999 nop
1000 ldi:32 STATIC, r12
1001 nop
1002 ldi:32 FUNCTION, r0
1003 jmp @r0
1004
1005 The no-ops are to guarantee that the static chain and final
1006 target are 32 bit aligned within the trampoline. That allows us to
1007 initialize those locations with simple SImode stores. The alternative
1008 would be to use HImode stores. */
1009
1010static void
1011fr30_asm_trampoline_template (FILE *f)
1012{
1013 fprintf (f, "\tnop\n");
1014 fprintf (f, "\tldi:32\t#0, %s\n", reg_names [STATIC_CHAIN_REGNUM]);
1015 fprintf (f, "\tnop\n");
1016 fprintf (f, "\tldi:32\t#0, %s\n", reg_names [COMPILER_SCRATCH_REGISTER]);
1017 fprintf (f, "\tjmp\t@%s\n", reg_names [COMPILER_SCRATCH_REGISTER]);
1018}
1019
1020/* Implement TARGET_TRAMPOLINE_INIT. */
1021
1022static void
1023fr30_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
1024{
1025 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
1026 rtx mem;
1027
1028 emit_block_move (m_tramp, assemble_trampoline_template (),
1029 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
1030
1031 mem = adjust_address (m_tramp, SImode, 4);
1032 emit_move_insn (mem, chain_value);
1033 mem = adjust_address (m_tramp, SImode, 12);
1034 emit_move_insn (mem, fnaddr);
1035}
1036
b2fc915b
NC
1037/*}}}*/
1038/* Local Variables: */
1039/* folded-file: t */
1040/* End: */