* config/ia64/ia64.md: Define new attribute "empty".
[official-gcc.git] / gcc / config / fr30 / fr30.c
blob7a4f04ff9c3a22502eae809f3006dc51f7dafa61
1 /* FR30 specific functions.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004
3 Free Software Foundation, Inc.
4 Contributed by Cygnus Solutions.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 /*{{{ Includes */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "rtl.h"
30 #include "regs.h"
31 #include "hard-reg-set.h"
32 #include "real.h"
33 #include "insn-config.h"
34 #include "conditions.h"
35 #include "insn-attr.h"
36 #include "flags.h"
37 #include "recog.h"
38 #include "tree.h"
39 #include "output.h"
40 #include "expr.h"
41 #include "obstack.h"
42 #include "except.h"
43 #include "function.h"
44 #include "toplev.h"
45 #include "tm_p.h"
46 #include "target.h"
47 #include "target-def.h"
49 /*}}}*/
50 /*{{{ Function Prologues & Epilogues */
52 /* Define the information needed to generate branch and scc insns. This is
53 stored from the compare operation. */
55 struct rtx_def * fr30_compare_op0;
56 struct rtx_def * fr30_compare_op1;
58 /* The FR30 stack looks like this:
60 Before call After call
61 FP ->| | | |
62 +-----------------------+ +-----------------------+ high
63 | | | | memory
64 | local variables, | | local variables, |
65 | reg save area, etc. | | reg save area, etc. |
66 | | | |
67 +-----------------------+ +-----------------------+
68 | | | |
69 | args to the func that | | args to this func. |
70 | is being called that | | |
71 SP ->| do not fit in regs | | |
72 +-----------------------+ +-----------------------+
73 | args that used to be | \
74 | in regs; only created | | pretend_size
75 AP-> | for vararg funcs | /
76 +-----------------------+
77 | | \
78 | register save area | |
79 | | |
80 +-----------------------+ | reg_size
81 | return address | |
82 +-----------------------+ |
83 FP ->| previous frame ptr | /
84 +-----------------------+
85 | | \
86 | local variables | | var_size
87 | | /
88 +-----------------------+
89 | | \
90 low | room for args to | |
91 memory | other funcs called | | args_size
92 | from this one | |
93 SP ->| | /
94 +-----------------------+
96 Note, AP is a fake hard register. It will be eliminated in favor of
97 SP or FP as appropriate.
99 Note, Some or all of the stack sections above may be omitted if they
100 are not needed. */
102 /* Structure to be filled in by fr30_compute_frame_size() with register
103 save masks, and offsets for the current function. */
104 struct fr30_frame_info
106 unsigned int total_size; /* # Bytes that the entire frame takes up. */
107 unsigned int pretend_size; /* # Bytes we push and pretend caller did. */
108 unsigned int args_size; /* # Bytes that outgoing arguments take up. */
109 unsigned int reg_size; /* # Bytes needed to store regs. */
110 unsigned int var_size; /* # Bytes that variables take up. */
111 unsigned int frame_size; /* # Bytes in current frame. */
112 unsigned int gmask; /* Mask of saved registers. */
113 unsigned int save_fp; /* Nonzero if frame pointer must be saved. */
114 unsigned int save_rp; /* Nonzero if return pointer must be saved. */
115 int initialised; /* Nonzero if frame size already calculated. */
118 /* Current frame information calculated by fr30_compute_frame_size(). */
119 static struct fr30_frame_info current_frame_info;
121 /* Zero structure to initialize current_frame_info. */
122 static struct fr30_frame_info zero_frame_info;
124 static void fr30_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
125 tree, int *, int);
126 static rtx fr30_pass_by_reference (tree, tree);
127 static rtx fr30_pass_by_value (tree, tree);
129 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
130 #define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM))
132 /* Tell prologue and epilogue if register REGNO should be saved / restored.
133 The return address and frame pointer are treated separately.
134 Don't consider them here. */
135 #define MUST_SAVE_REGISTER(regno) \
136 ( (regno) != RETURN_POINTER_REGNUM \
137 && (regno) != FRAME_POINTER_REGNUM \
138 && regs_ever_live [regno] \
139 && ! call_used_regs [regno] )
141 #define MUST_SAVE_FRAME_POINTER (regs_ever_live [FRAME_POINTER_REGNUM] || frame_pointer_needed)
142 #define MUST_SAVE_RETURN_POINTER (regs_ever_live [RETURN_POINTER_REGNUM] || current_function_profile)
144 #if UNITS_PER_WORD == 4
145 #define WORD_ALIGN(SIZE) (((SIZE) + 3) & ~3)
146 #endif
148 /* Initialize the GCC target structure. */
149 #undef TARGET_ASM_ALIGNED_HI_OP
150 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
151 #undef TARGET_ASM_ALIGNED_SI_OP
152 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
154 #undef TARGET_PROMOTE_PROTOTYPES
155 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
157 #undef TARGET_SETUP_INCOMING_VARARGS
158 #define TARGET_SETUP_INCOMING_VARARGS fr30_setup_incoming_varargs
160 struct gcc_target targetm = TARGET_INITIALIZER;
162 /* Returns the number of bytes offset between FROM_REG and TO_REG
163 for the current function. As a side effect it fills in the
164 current_frame_info structure, if the data is available. */
165 unsigned int
166 fr30_compute_frame_size (int from_reg, int to_reg)
168 int regno;
169 unsigned int return_value;
170 unsigned int var_size;
171 unsigned int args_size;
172 unsigned int pretend_size;
173 unsigned int reg_size;
174 unsigned int gmask;
176 var_size = WORD_ALIGN (get_frame_size ());
177 args_size = WORD_ALIGN (current_function_outgoing_args_size);
178 pretend_size = current_function_pretend_args_size;
180 reg_size = 0;
181 gmask = 0;
183 /* Calculate space needed for registers. */
184 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++)
186 if (MUST_SAVE_REGISTER (regno))
188 reg_size += UNITS_PER_WORD;
189 gmask |= 1 << regno;
193 current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER;
194 current_frame_info.save_rp = MUST_SAVE_RETURN_POINTER;
196 reg_size += (current_frame_info.save_fp + current_frame_info.save_rp)
197 * UNITS_PER_WORD;
199 /* Save computed information. */
200 current_frame_info.pretend_size = pretend_size;
201 current_frame_info.var_size = var_size;
202 current_frame_info.args_size = args_size;
203 current_frame_info.reg_size = reg_size;
204 current_frame_info.frame_size = args_size + var_size;
205 current_frame_info.total_size = args_size + var_size + reg_size + pretend_size;
206 current_frame_info.gmask = gmask;
207 current_frame_info.initialised = reload_completed;
209 /* Calculate the required distance. */
210 return_value = 0;
212 if (to_reg == STACK_POINTER_REGNUM)
213 return_value += args_size + var_size;
215 if (from_reg == ARG_POINTER_REGNUM)
216 return_value += reg_size;
218 return return_value;
221 /* Called after register allocation to add any instructions needed for the
222 prologue. Using a prologue insn is favored compared to putting all of the
223 instructions in output_function_prologue(), since it allows the scheduler
224 to intermix instructions with the saves of the caller saved registers. In
225 some cases, it might be necessary to emit a barrier instruction as the last
226 insn to prevent such scheduling. */
228 void
229 fr30_expand_prologue (void)
231 int regno;
232 rtx insn;
234 if (! current_frame_info.initialised)
235 fr30_compute_frame_size (0, 0);
237 /* This cases shouldn't happen. Catch it now. */
238 if (current_frame_info.total_size == 0
239 && current_frame_info.gmask)
240 abort ();
242 /* Allocate space for register arguments if this is a variadic function. */
243 if (current_frame_info.pretend_size)
245 int regs_to_save = current_frame_info.pretend_size / UNITS_PER_WORD;
247 /* Push argument registers into the pretend arg area. */
248 for (regno = FIRST_ARG_REGNUM + FR30_NUM_ARG_REGS; regno --, regs_to_save --;)
250 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
251 RTX_FRAME_RELATED_P (insn) = 1;
255 if (current_frame_info.gmask)
257 /* Save any needed call-saved regs. */
258 for (regno = STACK_POINTER_REGNUM; regno--;)
260 if ((current_frame_info.gmask & (1 << regno)) != 0)
262 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
263 RTX_FRAME_RELATED_P (insn) = 1;
268 /* Save return address if necessary. */
269 if (current_frame_info.save_rp)
271 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode,
272 RETURN_POINTER_REGNUM)));
273 RTX_FRAME_RELATED_P (insn) = 1;
276 /* Save old frame pointer and create new one, if necessary. */
277 if (current_frame_info.save_fp)
279 if (current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
281 int enter_size = current_frame_info.frame_size + UNITS_PER_WORD;
282 rtx pattern;
284 insn = emit_insn (gen_enter_func (GEN_INT (enter_size)));
285 RTX_FRAME_RELATED_P (insn) = 1;
287 pattern = PATTERN (insn);
289 /* Also mark all 3 subexpressions as RTX_FRAME_RELATED_P. */
290 if (GET_CODE (pattern) == PARALLEL)
292 int x;
293 for (x = XVECLEN (pattern, 0); x--;)
295 rtx part = XVECEXP (pattern, 0, x);
297 /* One of the insns in the ENTER pattern updates the
298 frame pointer. If we do not actually need the frame
299 pointer in this function then this is a side effect
300 rather than a desired effect, so we do not mark that
301 insn as being related to the frame set up. Doing this
302 allows us to compile the crash66.C test file in the
303 G++ testsuite. */
304 if (! frame_pointer_needed
305 && GET_CODE (part) == SET
306 && REGNO (SET_DEST (part)) == HARD_FRAME_POINTER_REGNUM)
307 RTX_FRAME_RELATED_P (part) = 0;
308 else
309 RTX_FRAME_RELATED_P (part) = 1;
313 else
315 insn = emit_insn (gen_movsi_push (frame_pointer_rtx));
316 RTX_FRAME_RELATED_P (insn) = 1;
318 if (frame_pointer_needed)
320 insn = emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
321 RTX_FRAME_RELATED_P (insn) = 1;
326 /* Allocate the stack frame. */
327 if (current_frame_info.frame_size == 0)
328 ; /* Nothing to do. */
329 else if (current_frame_info.save_fp
330 && current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
331 ; /* Nothing to do. */
332 else if (current_frame_info.frame_size <= 512)
334 insn = emit_insn (gen_add_to_stack (GEN_INT (- current_frame_info.frame_size)));
335 RTX_FRAME_RELATED_P (insn) = 1;
337 else
339 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
340 insn = emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
341 RTX_FRAME_RELATED_P (insn) = 1;
342 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
343 RTX_FRAME_RELATED_P (insn) = 1;
346 if (current_function_profile)
347 emit_insn (gen_blockage ());
350 /* Called after register allocation to add any instructions needed for the
351 epilogue. Using an epilogue insn is favored compared to putting all of the
352 instructions in output_function_epilogue(), since it allows the scheduler
353 to intermix instructions with the restores of the caller saved registers.
354 In some cases, it might be necessary to emit a barrier instruction as the
355 first insn to prevent such scheduling. */
356 void
357 fr30_expand_epilogue (void)
359 int regno;
361 /* Perform the inversion operations of the prologue. */
362 if (! current_frame_info.initialised)
363 abort ();
365 /* Pop local variables and arguments off the stack.
366 If frame_pointer_needed is TRUE then the frame pointer register
367 has actually been used as a frame pointer, and we can recover
368 the stack pointer from it, otherwise we must unwind the stack
369 manually. */
370 if (current_frame_info.frame_size > 0)
372 if (current_frame_info.save_fp && frame_pointer_needed)
374 emit_insn (gen_leave_func ());
375 current_frame_info.save_fp = 0;
377 else if (current_frame_info.frame_size <= 508)
378 emit_insn (gen_add_to_stack
379 (GEN_INT (current_frame_info.frame_size)));
380 else
382 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
383 emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
384 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
388 if (current_frame_info.save_fp)
389 emit_insn (gen_movsi_pop (frame_pointer_rtx));
391 /* Pop all the registers that were pushed. */
392 if (current_frame_info.save_rp)
393 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, RETURN_POINTER_REGNUM)));
395 for (regno = 0; regno < STACK_POINTER_REGNUM; regno ++)
396 if (current_frame_info.gmask & (1 << regno))
397 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno)));
399 if (current_frame_info.pretend_size)
400 emit_insn (gen_add_to_stack (GEN_INT (current_frame_info.pretend_size)));
402 /* Reset state info for each function. */
403 current_frame_info = zero_frame_info;
405 emit_jump_insn (gen_return_from_func ());
408 /* Do any needed setup for a variadic function. We must create a register
409 parameter block, and then copy any anonymous arguments, plus the last
410 named argument, from registers into memory. * copying actually done in
411 fr30_expand_prologue().
413 ARG_REGS_USED_SO_FAR has *not* been updated for the last named argument
414 which has type TYPE and mode MODE, and we rely on this fact. */
415 void
416 fr30_setup_incoming_varargs (CUMULATIVE_ARGS arg_regs_used_so_far,
417 int int_mode,
418 tree type ATTRIBUTE_UNUSED,
419 int *pretend_size)
421 enum machine_mode mode = (enum machine_mode)int_mode;
422 int size;
425 /* All BLKmode values are passed by reference. */
426 if (mode == BLKmode)
427 abort ();
429 /* ??? This run-time test as well as the code inside the if
430 statement is probably unnecessary. */
431 if (targetm.calls.strict_argument_naming (&arg_regs_used_so_far))
432 /* If TARGET_STRICT_ARGUMENT_NAMING returns true, then the last named
433 arg must not be treated as an anonymous arg. */
434 arg_regs_used_so_far += fr30_num_arg_regs (int_mode, type);
436 size = FR30_NUM_ARG_REGS - arg_regs_used_so_far;
438 if (size <= 0)
439 return;
441 * pretend_size = (size * UNITS_PER_WORD);
444 /*}}}*/
445 /*{{{ Printing operands */
447 /* Print a memory address as an operand to reference that memory location. */
449 void
450 fr30_print_operand_address (FILE *stream, rtx address)
452 switch (GET_CODE (address))
454 case SYMBOL_REF:
455 output_addr_const (stream, address);
456 break;
458 default:
459 fprintf (stderr, "code = %x\n", GET_CODE (address));
460 debug_rtx (address);
461 output_operand_lossage ("fr30_print_operand_address: unhandled address");
462 break;
466 /* Print an operand. */
468 void
469 fr30_print_operand (FILE *file, rtx x, int code)
471 rtx x0;
473 switch (code)
475 case '#':
476 /* Output a :D if this instruction is delayed. */
477 if (dbr_sequence_length () != 0)
478 fputs (":D", file);
479 return;
481 case 'p':
482 /* Compute the register name of the second register in a hi/lo
483 register pair. */
484 if (GET_CODE (x) != REG)
485 output_operand_lossage ("fr30_print_operand: unrecognized %%p code");
486 else
487 fprintf (file, "r%d", REGNO (x) + 1);
488 return;
490 case 'b':
491 /* Convert GCC's comparison operators into FR30 comparison codes. */
492 switch (GET_CODE (x))
494 case EQ: fprintf (file, "eq"); break;
495 case NE: fprintf (file, "ne"); break;
496 case LT: fprintf (file, "lt"); break;
497 case LE: fprintf (file, "le"); break;
498 case GT: fprintf (file, "gt"); break;
499 case GE: fprintf (file, "ge"); break;
500 case LTU: fprintf (file, "c"); break;
501 case LEU: fprintf (file, "ls"); break;
502 case GTU: fprintf (file, "hi"); break;
503 case GEU: fprintf (file, "nc"); break;
504 default:
505 output_operand_lossage ("fr30_print_operand: unrecognized %%b code");
506 break;
508 return;
510 case 'B':
511 /* Convert GCC's comparison operators into the complimentary FR30
512 comparison codes. */
513 switch (GET_CODE (x))
515 case EQ: fprintf (file, "ne"); break;
516 case NE: fprintf (file, "eq"); break;
517 case LT: fprintf (file, "ge"); break;
518 case LE: fprintf (file, "gt"); break;
519 case GT: fprintf (file, "le"); break;
520 case GE: fprintf (file, "lt"); break;
521 case LTU: fprintf (file, "nc"); break;
522 case LEU: fprintf (file, "hi"); break;
523 case GTU: fprintf (file, "ls"); break;
524 case GEU: fprintf (file, "c"); break;
525 default:
526 output_operand_lossage ("fr30_print_operand: unrecognized %%B code");
527 break;
529 return;
531 case 'A':
532 /* Print a signed byte value as an unsigned value. */
533 if (GET_CODE (x) != CONST_INT)
534 output_operand_lossage ("fr30_print_operand: invalid operand to %%A code");
535 else
537 HOST_WIDE_INT val;
539 val = INTVAL (x);
541 val &= 0xff;
543 fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
545 return;
547 case 'x':
548 if (GET_CODE (x) != CONST_INT
549 || INTVAL (x) < 16
550 || INTVAL (x) > 32)
551 output_operand_lossage ("fr30_print_operand: invalid %%x code");
552 else
553 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) - 16);
554 return;
556 case 'F':
557 if (GET_CODE (x) != CONST_DOUBLE)
558 output_operand_lossage ("fr30_print_operand: invalid %%F code");
559 else
561 char str[30];
563 real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x),
564 sizeof (str), 0, 1);
565 fputs (str, file);
567 return;
569 case 0:
570 /* Handled below. */
571 break;
573 default:
574 fprintf (stderr, "unknown code = %x\n", code);
575 output_operand_lossage ("fr30_print_operand: unknown code");
576 return;
579 switch (GET_CODE (x))
581 case REG:
582 fputs (reg_names [REGNO (x)], file);
583 break;
585 case MEM:
586 x0 = XEXP (x,0);
588 switch (GET_CODE (x0))
590 case REG:
591 if ((unsigned) REGNO (x0) >= ARRAY_SIZE (reg_names))
592 abort ();
593 fprintf (file, "@%s", reg_names [REGNO (x0)]);
594 break;
596 case PLUS:
597 if (GET_CODE (XEXP (x0, 0)) != REG
598 || REGNO (XEXP (x0, 0)) < FRAME_POINTER_REGNUM
599 || REGNO (XEXP (x0, 0)) > STACK_POINTER_REGNUM
600 || GET_CODE (XEXP (x0, 1)) != CONST_INT)
602 fprintf (stderr, "bad INDEXed address:");
603 debug_rtx (x);
604 output_operand_lossage ("fr30_print_operand: unhandled MEM");
606 else if (REGNO (XEXP (x0, 0)) == FRAME_POINTER_REGNUM)
608 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
609 if (val < -(1 << 9) || val > ((1 << 9) - 4))
611 fprintf (stderr, "frame INDEX out of range:");
612 debug_rtx (x);
613 output_operand_lossage ("fr30_print_operand: unhandled MEM");
615 fprintf (file, "@(r14, #" HOST_WIDE_INT_PRINT_DEC ")", val);
617 else
619 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
620 if (val < 0 || val > ((1 << 6) - 4))
622 fprintf (stderr, "stack INDEX out of range:");
623 debug_rtx (x);
624 output_operand_lossage ("fr30_print_operand: unhandled MEM");
626 fprintf (file, "@(r15, #" HOST_WIDE_INT_PRINT_DEC ")", val);
628 break;
630 case SYMBOL_REF:
631 output_address (x0);
632 break;
634 default:
635 fprintf (stderr, "bad MEM code = %x\n", GET_CODE (x0));
636 debug_rtx (x);
637 output_operand_lossage ("fr30_print_operand: unhandled MEM");
638 break;
640 break;
642 case CONST_DOUBLE :
643 /* We handle SFmode constants here as output_addr_const doesn't. */
644 if (GET_MODE (x) == SFmode)
646 REAL_VALUE_TYPE d;
647 long l;
649 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
650 REAL_VALUE_TO_TARGET_SINGLE (d, l);
651 fprintf (file, "0x%08lx", l);
652 break;
655 /* Fall through. Let output_addr_const deal with it. */
656 default:
657 output_addr_const (file, x);
658 break;
661 return;
664 /*}}}*/
665 /*{{{ Function arguments */
667 /* Compute the number of word sized registers needed to hold a
668 function argument of mode INT_MODE and tree type TYPE. */
670 fr30_num_arg_regs (enum machine_mode mode, tree type)
672 int size;
674 if (MUST_PASS_IN_STACK (mode, type))
675 return 0;
677 if (type && mode == BLKmode)
678 size = int_size_in_bytes (type);
679 else
680 size = GET_MODE_SIZE (mode);
682 return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
685 /* Implements the FUNCTION_ARG_PARTIAL_NREGS macro.
686 Returns the number of argument registers required to hold *part* of
687 a parameter of machine mode MODE and tree type TYPE (which may be
688 NULL if the type is not known). If the argument fits entirely in
689 the argument registers, or entirely on the stack, then 0 is returned.
690 CUM is the number of argument registers already used by earlier
691 parameters to the function. */
694 fr30_function_arg_partial_nregs (CUMULATIVE_ARGS cum, enum machine_mode mode,
695 tree type, int named)
697 /* Unnamed arguments, ie those that are prototyped as ...
698 are always passed on the stack.
699 Also check here to see if all the argument registers are full. */
700 if (named == 0 || cum >= FR30_NUM_ARG_REGS)
701 return 0;
703 /* Work out how many argument registers would be needed if this
704 parameter were to be passed entirely in registers. If there
705 are sufficient argument registers available (or if no registers
706 are needed because the parameter must be passed on the stack)
707 then return zero, as this parameter does not require partial
708 register, partial stack stack space. */
709 if (cum + fr30_num_arg_regs (mode, type) <= FR30_NUM_ARG_REGS)
710 return 0;
712 /* Otherwise return the number of registers that would be used. */
713 return FR30_NUM_ARG_REGS - cum;
716 static rtx
717 fr30_pass_by_reference (tree valist, tree type)
719 tree type_ptr;
720 tree type_ptr_ptr;
721 tree t;
723 type_ptr = build_pointer_type (type);
724 type_ptr_ptr = build_pointer_type (type_ptr);
726 t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (UNITS_PER_WORD, 0));
727 TREE_SIDE_EFFECTS (t) = 1;
728 t = build1 (NOP_EXPR, type_ptr_ptr, t);
729 TREE_SIDE_EFFECTS (t) = 1;
730 t = build1 (INDIRECT_REF, type_ptr, t);
732 return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
735 static rtx
736 fr30_pass_by_value (tree valist, tree type)
738 HOST_WIDE_INT size = int_size_in_bytes (type);
739 HOST_WIDE_INT rsize;
740 rtx addr_rtx;
741 tree t;
743 if ((size % UNITS_PER_WORD) == 0)
745 t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (size, 0));
746 TREE_SIDE_EFFECTS (t) = 1;
748 return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
751 rsize = (size + UNITS_PER_WORD - 1) & - UNITS_PER_WORD;
753 /* Care for bigendian correction on the aligned address. */
754 t = build (PLUS_EXPR, ptr_type_node, valist, build_int_2 (rsize - size, 0));
755 addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
756 addr_rtx = copy_to_reg (addr_rtx);
758 /* Increment AP. */
759 t = build (PLUS_EXPR, va_list_type_node, valist, build_int_2 (rsize, 0));
760 t = build (MODIFY_EXPR, va_list_type_node, valist, t);
761 TREE_SIDE_EFFECTS (t) = 1;
762 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
764 return addr_rtx;
767 /* Implement `va_arg'. */
770 fr30_va_arg (tree valist, tree type)
772 HOST_WIDE_INT size;
774 if (AGGREGATE_TYPE_P (type))
775 return fr30_pass_by_reference (valist, type);
777 size = int_size_in_bytes (type);
779 if ((size % sizeof (int)) == 0
780 || size < 4)
781 return fr30_pass_by_value (valist, type);
783 return fr30_pass_by_reference (valist, type);
786 /*}}}*/
787 /*{{{ Operand predicates */
789 #ifndef Mmode
790 #define Mmode enum machine_mode
791 #endif
793 /* Returns true if OPERAND is an integer value suitable for use in
794 an ADDSP instruction. */
796 stack_add_operand (rtx operand, Mmode mode ATTRIBUTE_UNUSED)
798 return
799 (GET_CODE (operand) == CONST_INT
800 && INTVAL (operand) >= -512
801 && INTVAL (operand) <= 508
802 && ((INTVAL (operand) & 3) == 0));
805 /* Returns true if OPERAND is an integer value suitable for use in
806 an ADD por ADD2 instruction, or if it is a register. */
808 add_immediate_operand (rtx operand, Mmode mode ATTRIBUTE_UNUSED)
810 return
811 (GET_CODE (operand) == REG
812 || (GET_CODE (operand) == CONST_INT
813 && INTVAL (operand) >= -16
814 && INTVAL (operand) <= 15));
817 /* Returns true if OPERAND is hard register in the range 8 - 15. */
819 high_register_operand (rtx operand, Mmode mode ATTRIBUTE_UNUSED)
821 return
822 (GET_CODE (operand) == REG
823 && REGNO (operand) <= 15
824 && REGNO (operand) >= 8);
827 /* Returns true if OPERAND is hard register in the range 0 - 7. */
829 low_register_operand (rtx operand, Mmode mode ATTRIBUTE_UNUSED)
831 return
832 (GET_CODE (operand) == REG
833 && REGNO (operand) <= 7);
836 /* Returns true if OPERAND is suitable for use in a CALL insn. */
838 call_operand (rtx operand, Mmode mode ATTRIBUTE_UNUSED)
840 return (GET_CODE (operand) == MEM
841 && (GET_CODE (XEXP (operand, 0)) == SYMBOL_REF
842 || GET_CODE (XEXP (operand, 0)) == REG));
845 /* Returns TRUE if OP is a valid operand of a DImode operation. */
847 di_operand (rtx op, Mmode mode)
849 if (register_operand (op, mode))
850 return TRUE;
852 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
853 return FALSE;
855 if (GET_CODE (op) == SUBREG)
856 op = SUBREG_REG (op);
858 switch (GET_CODE (op))
860 case CONST_DOUBLE:
861 case CONST_INT:
862 return TRUE;
864 case MEM:
865 return memory_address_p (DImode, XEXP (op, 0));
867 default:
868 return FALSE;
872 /* Returns TRUE if OP is a DImode register or MEM. */
874 nonimmediate_di_operand (rtx op, Mmode mode)
876 if (register_operand (op, mode))
877 return TRUE;
879 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
880 return FALSE;
882 if (GET_CODE (op) == SUBREG)
883 op = SUBREG_REG (op);
885 if (GET_CODE (op) == MEM)
886 return memory_address_p (DImode, XEXP (op, 0));
888 return FALSE;
891 /* Returns true iff all the registers in the operands array
892 are in descending or ascending order. */
894 fr30_check_multiple_regs (rtx *operands, int num_operands, int descending)
896 if (descending)
898 unsigned int prev_regno = 0;
900 while (num_operands --)
902 if (GET_CODE (operands [num_operands]) != REG)
903 return 0;
905 if (REGNO (operands [num_operands]) < prev_regno)
906 return 0;
908 prev_regno = REGNO (operands [num_operands]);
911 else
913 unsigned int prev_regno = CONDITION_CODE_REGNUM;
915 while (num_operands --)
917 if (GET_CODE (operands [num_operands]) != REG)
918 return 0;
920 if (REGNO (operands [num_operands]) > prev_regno)
921 return 0;
923 prev_regno = REGNO (operands [num_operands]);
927 return 1;
931 fr30_const_double_is_zero (rtx operand)
933 REAL_VALUE_TYPE d;
935 if (operand == NULL || GET_CODE (operand) != CONST_DOUBLE)
936 return 0;
938 REAL_VALUE_FROM_CONST_DOUBLE (d, operand);
940 return REAL_VALUES_EQUAL (d, dconst0);
943 /*}}}*/
944 /*{{{ Instruction Output Routines */
946 /* Output a double word move.
947 It must be REG<-REG, REG<-MEM, MEM<-REG or REG<-CONST.
948 On the FR30 we are constrained by the fact that it does not
949 support offsetable addresses, and so we have to load the
950 address of the secnd word into the second destination register
951 before we can use it. */
954 fr30_move_double (rtx * operands)
956 rtx src = operands[1];
957 rtx dest = operands[0];
958 enum rtx_code src_code = GET_CODE (src);
959 enum rtx_code dest_code = GET_CODE (dest);
960 enum machine_mode mode = GET_MODE (dest);
961 rtx val;
963 start_sequence ();
965 if (dest_code == REG)
967 if (src_code == REG)
969 int reverse = (REGNO (dest) == REGNO (src) + 1);
971 /* We normally copy the low-numbered register first. However, if
972 the first register of operand 0 is the same as the second register
973 of operand 1, we must copy in the opposite order. */
974 emit_insn (gen_rtx_SET (VOIDmode,
975 operand_subword (dest, reverse, TRUE, mode),
976 operand_subword (src, reverse, TRUE, mode)));
978 emit_insn (gen_rtx_SET (VOIDmode,
979 operand_subword (dest, !reverse, TRUE, mode),
980 operand_subword (src, !reverse, TRUE, mode)));
982 else if (src_code == MEM)
984 rtx addr = XEXP (src, 0);
985 int dregno = REGNO (dest);
986 rtx dest0;
987 rtx dest1;
988 rtx new_mem;
990 /* If the high-address word is used in the address, we
991 must load it last. Otherwise, load it first. */
992 int reverse = (refers_to_regno_p (dregno, dregno + 1, addr, 0) != 0);
994 if (GET_CODE (addr) != REG)
995 abort ();
997 dest0 = operand_subword (dest, reverse, TRUE, mode);
998 dest1 = operand_subword (dest, !reverse, TRUE, mode);
1000 if (reverse)
1002 emit_insn (gen_rtx_SET (VOIDmode, dest1,
1003 adjust_address (src, SImode, 0)));
1004 emit_insn (gen_rtx_SET (SImode, dest0,
1005 gen_rtx_REG (SImode, REGNO (addr))));
1006 emit_insn (gen_rtx_SET (SImode, dest0,
1007 plus_constant (dest0, UNITS_PER_WORD)));
1009 new_mem = gen_rtx_MEM (SImode, dest0);
1010 MEM_COPY_ATTRIBUTES (new_mem, src);
1012 emit_insn (gen_rtx_SET (VOIDmode, dest0, new_mem));
1014 else
1016 emit_insn (gen_rtx_SET (VOIDmode, dest0,
1017 adjust_address (src, SImode, 0)));
1018 emit_insn (gen_rtx_SET (SImode, dest1,
1019 gen_rtx_REG (SImode, REGNO (addr))));
1020 emit_insn (gen_rtx_SET (SImode, dest1,
1021 plus_constant (dest1, UNITS_PER_WORD)));
1023 new_mem = gen_rtx_MEM (SImode, dest1);
1024 MEM_COPY_ATTRIBUTES (new_mem, src);
1026 emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem));
1029 else if (src_code == CONST_INT || src_code == CONST_DOUBLE)
1031 rtx words[2];
1032 split_double (src, &words[0], &words[1]);
1033 emit_insn (gen_rtx_SET (VOIDmode,
1034 operand_subword (dest, 0, TRUE, mode),
1035 words[0]));
1037 emit_insn (gen_rtx_SET (VOIDmode,
1038 operand_subword (dest, 1, TRUE, mode),
1039 words[1]));
1042 else if (src_code == REG && dest_code == MEM)
1044 rtx addr = XEXP (dest, 0);
1045 rtx src0;
1046 rtx src1;
1048 if (GET_CODE (addr) != REG)
1049 abort ();
1051 src0 = operand_subword (src, 0, TRUE, mode);
1052 src1 = operand_subword (src, 1, TRUE, mode);
1054 emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, 0),
1055 src0));
1057 if (REGNO (addr) == STACK_POINTER_REGNUM
1058 || REGNO (addr) == FRAME_POINTER_REGNUM)
1059 emit_insn (gen_rtx_SET (VOIDmode,
1060 adjust_address (dest, SImode, UNITS_PER_WORD),
1061 src1));
1062 else
1064 rtx new_mem;
1066 /* We need a scratch register to hold the value of 'address + 4'.
1067 We ought to allow gcc to find one for us, but for now, just
1068 push one of the source registers. */
1069 emit_insn (gen_movsi_push (src0));
1070 emit_insn (gen_movsi_internal (src0, addr));
1071 emit_insn (gen_addsi_small_int (src0, src0, GEN_INT (UNITS_PER_WORD)));
1073 new_mem = gen_rtx_MEM (SImode, src0);
1074 MEM_COPY_ATTRIBUTES (new_mem, dest);
1076 emit_insn (gen_rtx_SET (VOIDmode, new_mem, src1));
1077 emit_insn (gen_movsi_pop (src0));
1080 else
1081 /* This should have been prevented by the constraints on movdi_insn. */
1082 abort ();
1084 val = get_insns ();
1085 end_sequence ();
1087 return val;
1089 /*}}}*/
1090 /* Local Variables: */
1091 /* folded-file: t */
1092 /* End: */