FSF GCC merge 02/23/03
[official-gcc.git] / gcc / config / fr30 / fr30.c
blob0c143b3422491a626c49282db1bf66e0aac355a6
1 /* FR30 specific functions.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Cygnus Solutions.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU CC is distributed in the hope that it will be useful,
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.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /*{{{ Includes */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "rtl.h"
29 #include "regs.h"
30 #include "hard-reg-set.h"
31 #include "real.h"
32 #include "insn-config.h"
33 #include "conditions.h"
34 #include "insn-attr.h"
35 #include "flags.h"
36 #include "recog.h"
37 #include "tree.h"
38 #include "output.h"
39 #include "expr.h"
40 #include "obstack.h"
41 #include "except.h"
42 #include "function.h"
43 #include "tm_p.h"
44 #include "target.h"
45 #include "target-def.h"
47 /*}}}*/
48 /*{{{ Function Prologues & Epilogues */
50 /* Define the information needed to generate branch and scc insns. This is
51 stored from the compare operation. */
53 struct rtx_def * fr30_compare_op0;
54 struct rtx_def * fr30_compare_op1;
56 /* The FR30 stack looks like this:
58 Before call After call
59 FP ->| | | |
60 +-----------------------+ +-----------------------+ high
61 | | | | memory
62 | local variables, | | local variables, |
63 | reg save area, etc. | | reg save area, etc. |
64 | | | |
65 +-----------------------+ +-----------------------+
66 | | | |
67 | args to the func that | | args to this func. |
68 | is being called that | | |
69 SP ->| do not fit in regs | | |
70 +-----------------------+ +-----------------------+
71 | args that used to be | \
72 | in regs; only created | | pretend_size
73 AP-> | for vararg funcs | /
74 +-----------------------+
75 | | \
76 | register save area | |
77 | | |
78 +-----------------------+ | reg_size
79 | return address | |
80 +-----------------------+ |
81 FP ->| previous frame ptr | /
82 +-----------------------+
83 | | \
84 | local variables | | var_size
85 | | /
86 +-----------------------+
87 | | \
88 low | room for args to | |
89 memory | other funcs called | | args_size
90 | from this one | |
91 SP ->| | /
92 +-----------------------+
94 Note, AP is a fake hard register. It will be eliminated in favor of
95 SP or FP as appropriate.
97 Note, Some or all of the stack sections above may be omitted if they
98 are not needed. */
100 /* Structure to be filled in by fr30_compute_frame_size() with register
101 save masks, and offsets for the current function. */
102 struct fr30_frame_info
104 unsigned int total_size; /* # Bytes that the entire frame takes up. */
105 unsigned int pretend_size; /* # Bytes we push and pretend caller did. */
106 unsigned int args_size; /* # Bytes that outgoing arguments take up. */
107 unsigned int reg_size; /* # Bytes needed to store regs. */
108 unsigned int var_size; /* # Bytes that variables take up. */
109 unsigned int frame_size; /* # Bytes in current frame. */
110 unsigned int gmask; /* Mask of saved registers. */
111 unsigned int save_fp; /* Nonzero if frame pointer must be saved. */
112 unsigned int save_rp; /* Nonzero if return popinter must be saved. */
113 int initialised; /* Nonzero if frame size already calculated. */
116 /* Current frame information calculated by fr30_compute_frame_size(). */
117 static struct fr30_frame_info current_frame_info;
119 /* Zero structure to initialize current_frame_info. */
120 static struct fr30_frame_info zero_frame_info;
122 static rtx fr30_pass_by_reference PARAMS ((tree, tree));
123 static rtx fr30_pass_by_value PARAMS ((tree, tree));
125 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
126 #define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM))
128 /* Tell prologue and epilogue if register REGNO should be saved / restored.
129 The return address and frame pointer are treated separately.
130 Don't consider them here. */
131 #define MUST_SAVE_REGISTER(regno) \
132 ( (regno) != RETURN_POINTER_REGNUM \
133 && (regno) != FRAME_POINTER_REGNUM \
134 && regs_ever_live [regno] \
135 && ! call_used_regs [regno] )
137 #define MUST_SAVE_FRAME_POINTER (regs_ever_live [FRAME_POINTER_REGNUM] || frame_pointer_needed)
138 #define MUST_SAVE_RETURN_POINTER (regs_ever_live [RETURN_POINTER_REGNUM] || current_function_profile)
140 #if UNITS_PER_WORD == 4
141 #define WORD_ALIGN(SIZE) (((SIZE) + 3) & ~3)
142 #endif
144 /* Initialize the GCC target structure. */
145 #undef TARGET_ASM_ALIGNED_HI_OP
146 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
147 #undef TARGET_ASM_ALIGNED_SI_OP
148 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
150 struct gcc_target targetm = TARGET_INITIALIZER;
152 /* Returns the number of bytes offset between FROM_REG and TO_REG
153 for the current function. As a side effect it fills in the
154 current_frame_info structure, if the data is available. */
155 unsigned int
156 fr30_compute_frame_size (from_reg, to_reg)
157 int from_reg;
158 int to_reg;
160 int regno;
161 unsigned int return_value;
162 unsigned int var_size;
163 unsigned int args_size;
164 unsigned int pretend_size;
165 unsigned int reg_size;
166 unsigned int gmask;
168 var_size = WORD_ALIGN (get_frame_size ());
169 args_size = WORD_ALIGN (current_function_outgoing_args_size);
170 pretend_size = current_function_pretend_args_size;
172 reg_size = 0;
173 gmask = 0;
175 /* Calculate space needed for registers. */
176 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++)
178 if (MUST_SAVE_REGISTER (regno))
180 reg_size += UNITS_PER_WORD;
181 gmask |= 1 << regno;
185 current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER;
186 current_frame_info.save_rp = MUST_SAVE_RETURN_POINTER;
188 reg_size += (current_frame_info.save_fp + current_frame_info.save_rp)
189 * UNITS_PER_WORD;
191 /* Save computed information. */
192 current_frame_info.pretend_size = pretend_size;
193 current_frame_info.var_size = var_size;
194 current_frame_info.args_size = args_size;
195 current_frame_info.reg_size = reg_size;
196 current_frame_info.frame_size = args_size + var_size;
197 current_frame_info.total_size = args_size + var_size + reg_size + pretend_size;
198 current_frame_info.gmask = gmask;
199 current_frame_info.initialised = reload_completed;
201 /* Calculate the required distance. */
202 return_value = 0;
204 if (to_reg == STACK_POINTER_REGNUM)
205 return_value += args_size + var_size;
207 if (from_reg == ARG_POINTER_REGNUM)
208 return_value += reg_size;
210 return return_value;
213 /* Called after register allocation to add any instructions needed for the
214 prologue. Using a prologue insn is favored compared to putting all of the
215 instructions in output_function_prologue(), since it allows the scheduler
216 to intermix instructions with the saves of the caller saved registers. In
217 some cases, it might be necessary to emit a barrier instruction as the last
218 insn to prevent such scheduling. */
220 void
221 fr30_expand_prologue ()
223 int regno;
224 rtx insn;
226 if (! current_frame_info.initialised)
227 fr30_compute_frame_size (0, 0);
229 /* This cases shouldn't happen. Catch it now. */
230 if (current_frame_info.total_size == 0
231 && current_frame_info.gmask)
232 abort ();
234 /* Allocate space for register arguments if this is a variadic function. */
235 if (current_frame_info.pretend_size)
237 int regs_to_save = current_frame_info.pretend_size / UNITS_PER_WORD;
239 /* Push argument registers into the pretend arg area. */
240 for (regno = FIRST_ARG_REGNUM + FR30_NUM_ARG_REGS; regno --, regs_to_save --;)
242 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
243 RTX_FRAME_RELATED_P (insn) = 1;
247 if (current_frame_info.gmask)
249 /* Save any needed call-saved regs. */
250 for (regno = STACK_POINTER_REGNUM; regno--;)
252 if ((current_frame_info.gmask & (1 << regno)) != 0)
254 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
255 RTX_FRAME_RELATED_P (insn) = 1;
260 /* Save return address if necessary. */
261 if (current_frame_info.save_rp)
263 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode,
264 RETURN_POINTER_REGNUM)));
265 RTX_FRAME_RELATED_P (insn) = 1;
268 /* Save old frame pointer and create new one, if necessary. */
269 if (current_frame_info.save_fp)
271 if (current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
273 int enter_size = current_frame_info.frame_size + UNITS_PER_WORD;
274 rtx pattern;
276 insn = emit_insn (gen_enter_func (GEN_INT (enter_size)));
277 RTX_FRAME_RELATED_P (insn) = 1;
279 pattern = PATTERN (insn);
281 /* Also mark all 3 subexpressions as RTX_FRAME_RELATED_P. */
282 if (GET_CODE (pattern) == PARALLEL)
284 int x;
285 for (x = XVECLEN (pattern, 0); x--;)
287 rtx part = XVECEXP (pattern, 0, x);
289 /* One of the insns in the ENTER pattern updates the
290 frame pointer. If we do not actually need the frame
291 pointer in this function then this is a side effect
292 rather than a desired effect, so we do not mark that
293 insn as being related to the frame set up. Doing this
294 allows us to compile the crash66.C test file in the
295 G++ testsuite. */
296 if (! frame_pointer_needed
297 && GET_CODE (part) == SET
298 && REGNO (SET_DEST (part)) == HARD_FRAME_POINTER_REGNUM)
299 RTX_FRAME_RELATED_P (part) = 0;
300 else
301 RTX_FRAME_RELATED_P (part) = 1;
305 else
307 insn = emit_insn (gen_movsi_push (frame_pointer_rtx));
308 RTX_FRAME_RELATED_P (insn) = 1;
310 if (frame_pointer_needed)
312 insn = emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
313 RTX_FRAME_RELATED_P (insn) = 1;
318 /* Allocate the stack frame. */
319 if (current_frame_info.frame_size == 0)
320 ; /* Nothing to do. */
321 else if (current_frame_info.save_fp
322 && current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
323 ; /* Nothing to do. */
324 else if (current_frame_info.frame_size <= 512)
326 insn = emit_insn (gen_add_to_stack (GEN_INT (- current_frame_info.frame_size)));
327 RTX_FRAME_RELATED_P (insn) = 1;
329 else
331 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
332 insn = emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
333 RTX_FRAME_RELATED_P (insn) = 1;
334 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
335 RTX_FRAME_RELATED_P (insn) = 1;
338 if (current_function_profile)
339 emit_insn (gen_blockage ());
342 /* Called after register allocation to add any instructions needed for the
343 epilogue. Using an epilogue insn is favored compared to putting all of the
344 instructions in output_function_epilogue(), since it allows the scheduler
345 to intermix instructions with the restores of the caller saved registers.
346 In some cases, it might be necessary to emit a barrier instruction as the
347 first insn to prevent such scheduling. */
348 void
349 fr30_expand_epilogue ()
351 int regno;
353 /* Perform the inversion operations of the prologue. */
354 if (! current_frame_info.initialised)
355 abort ();
357 /* Pop local variables and arguments off the stack.
358 If frame_pointer_needed is TRUE then the frame pointer register
359 has actually been used as a frame pointer, and we can recover
360 the stack pointer from it, otherwise we must unwind the stack
361 manually. */
362 if (current_frame_info.frame_size > 0)
364 if (current_frame_info.save_fp && frame_pointer_needed)
366 emit_insn (gen_leave_func ());
367 current_frame_info.save_fp = 0;
369 else if (current_frame_info.frame_size <= 508)
370 emit_insn (gen_add_to_stack
371 (GEN_INT (current_frame_info.frame_size)));
372 else
374 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
375 emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
376 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
380 if (current_frame_info.save_fp)
381 emit_insn (gen_movsi_pop (frame_pointer_rtx));
383 /* Pop all the registers that were pushed. */
384 if (current_frame_info.save_rp)
385 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, RETURN_POINTER_REGNUM)));
387 for (regno = 0; regno < STACK_POINTER_REGNUM; regno ++)
388 if (current_frame_info.gmask & (1 << regno))
389 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno)));
391 if (current_frame_info.pretend_size)
392 emit_insn (gen_add_to_stack (GEN_INT (current_frame_info.pretend_size)));
394 /* Reset state info for each function. */
395 current_frame_info = zero_frame_info;
397 emit_jump_insn (gen_return_from_func ());
400 /* Do any needed setup for a variadic function. We must create a register
401 parameter block, and then copy any anonymous arguments, plus the last
402 named argument, from registers into memory. * copying actually done in
403 fr30_expand_prologue().
405 ARG_REGS_USED_SO_FAR has *not* been updated for the last named argument
406 which has type TYPE and mode MODE, and we rely on this fact. */
407 void
408 fr30_setup_incoming_varargs (arg_regs_used_so_far, int_mode, type, pretend_size)
409 CUMULATIVE_ARGS arg_regs_used_so_far;
410 int int_mode;
411 tree type ATTRIBUTE_UNUSED;
412 int * pretend_size;
414 enum machine_mode mode = (enum machine_mode)int_mode;
415 int size;
418 /* All BLKmode values are passed by reference. */
419 if (mode == BLKmode)
420 abort ();
422 #if STRICT_ARGUMENT_NAMING
423 /* If STRICT_ARGUMENT_NAMING is true then the last named
424 arg must not be treated as an anonymous arg. */
425 arg_regs_used_so_far += fr30_num_arg_regs (int_mode, type);
426 #endif
428 size = FR30_NUM_ARG_REGS - arg_regs_used_so_far;
430 if (size <= 0)
431 return;
433 * pretend_size = (size * UNITS_PER_WORD);
436 /*}}}*/
437 /*{{{ Printing operands */
439 /* Print a memory address as an operand to reference that memory location. */
441 void
442 fr30_print_operand_address (stream, address)
443 FILE * stream;
444 rtx address;
446 switch (GET_CODE (address))
448 case SYMBOL_REF:
449 output_addr_const (stream, address);
450 break;
452 default:
453 fprintf (stderr, "code = %x\n", GET_CODE (address));
454 debug_rtx (address);
455 output_operand_lossage ("fr30_print_operand_address: unhandled address");
456 break;
460 /* Print an operand. */
462 void
463 fr30_print_operand (file, x, code)
464 FILE * file;
465 rtx x;
466 int code;
468 rtx x0;
470 switch (code)
472 case '#':
473 /* Output a :D if this instruction is delayed. */
474 if (dbr_sequence_length () != 0)
475 fputs (":D", file);
476 return;
478 case 'p':
479 /* Compute the register name of the second register in a hi/lo
480 register pair. */
481 if (GET_CODE (x) != REG)
482 output_operand_lossage ("fr30_print_operand: unrecognized %%p code");
483 else
484 fprintf (file, "r%d", REGNO (x) + 1);
485 return;
487 case 'b':
488 /* Convert GCC's comparison operators into FR30 comparison codes. */
489 switch (GET_CODE (x))
491 case EQ: fprintf (file, "eq"); break;
492 case NE: fprintf (file, "ne"); break;
493 case LT: fprintf (file, "lt"); break;
494 case LE: fprintf (file, "le"); break;
495 case GT: fprintf (file, "gt"); break;
496 case GE: fprintf (file, "ge"); break;
497 case LTU: fprintf (file, "c"); break;
498 case LEU: fprintf (file, "ls"); break;
499 case GTU: fprintf (file, "hi"); break;
500 case GEU: fprintf (file, "nc"); break;
501 default:
502 output_operand_lossage ("fr30_print_operand: unrecognized %%b code");
503 break;
505 return;
507 case 'B':
508 /* Convert GCC's comparison operators into the complimentary FR30
509 comparison codes. */
510 switch (GET_CODE (x))
512 case EQ: fprintf (file, "ne"); break;
513 case NE: fprintf (file, "eq"); break;
514 case LT: fprintf (file, "ge"); break;
515 case LE: fprintf (file, "gt"); break;
516 case GT: fprintf (file, "le"); break;
517 case GE: fprintf (file, "lt"); break;
518 case LTU: fprintf (file, "nc"); break;
519 case LEU: fprintf (file, "hi"); break;
520 case GTU: fprintf (file, "ls"); break;
521 case GEU: fprintf (file, "c"); break;
522 default:
523 output_operand_lossage ("fr30_print_operand: unrecognized %%B code");
524 break;
526 return;
528 case 'A':
529 /* Print a signed byte value as an unsigned value. */
530 if (GET_CODE (x) != CONST_INT)
531 output_operand_lossage ("fr30_print_operand: invalid operand to %%A code");
532 else
534 HOST_WIDE_INT val;
536 val = INTVAL (x);
538 val &= 0xff;
540 fprintf (file, "%d", val);
542 return;
544 case 'x':
545 if (GET_CODE (x) != CONST_INT
546 || INTVAL (x) < 16
547 || INTVAL (x) > 32)
548 output_operand_lossage ("fr30_print_operand: invalid %%x code");
549 else
550 fprintf (file, "%d", INTVAL (x) - 16);
551 return;
553 case 'F':
554 if (GET_CODE (x) != CONST_DOUBLE)
555 output_operand_lossage ("fr30_print_operand: invalid %%F code");
556 else
558 char str[30];
560 real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x),
561 sizeof (str), 0, 1);
562 fputs (str, file);
564 return;
566 case 0:
567 /* Handled below. */
568 break;
570 default:
571 fprintf (stderr, "unknown code = %x\n", code);
572 output_operand_lossage ("fr30_print_operand: unknown code");
573 return;
576 switch (GET_CODE (x))
578 case REG:
579 fputs (reg_names [REGNO (x)], file);
580 break;
582 case MEM:
583 x0 = XEXP (x,0);
585 switch (GET_CODE (x0))
587 case REG:
588 if ((unsigned) REGNO (x0) >= ARRAY_SIZE (reg_names))
589 abort ();
590 fprintf (file, "@%s", reg_names [REGNO (x0)]);
591 break;
593 case PLUS:
594 if (GET_CODE (XEXP (x0, 0)) != REG
595 || REGNO (XEXP (x0, 0)) < FRAME_POINTER_REGNUM
596 || REGNO (XEXP (x0, 0)) > STACK_POINTER_REGNUM
597 || GET_CODE (XEXP (x0, 1)) != CONST_INT)
599 fprintf (stderr, "bad INDEXed address:");
600 debug_rtx (x);
601 output_operand_lossage ("fr30_print_operand: unhandled MEM");
603 else if (REGNO (XEXP (x0, 0)) == FRAME_POINTER_REGNUM)
605 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
606 if (val < -(1 << 9) || val > ((1 << 9) - 4))
608 fprintf (stderr, "frame INDEX out of range:");
609 debug_rtx (x);
610 output_operand_lossage ("fr30_print_operand: unhandled MEM");
612 fprintf (file, "@(r14, #%d)", val);
614 else
616 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
617 if (val < 0 || val > ((1 << 6) - 4))
619 fprintf (stderr, "stack INDEX out of range:");
620 debug_rtx (x);
621 output_operand_lossage ("fr30_print_operand: unhandled MEM");
623 fprintf (file, "@(r15, #%d)", val);
625 break;
627 case SYMBOL_REF:
628 output_address (x0);
629 break;
631 default:
632 fprintf (stderr, "bad MEM code = %x\n", GET_CODE (x0));
633 debug_rtx (x);
634 output_operand_lossage ("fr30_print_operand: unhandled MEM");
635 break;
637 break;
639 case CONST_DOUBLE :
640 /* We handle SFmode constants here as output_addr_const doesn't. */
641 if (GET_MODE (x) == SFmode)
643 REAL_VALUE_TYPE d;
644 long l;
646 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
647 REAL_VALUE_TO_TARGET_SINGLE (d, l);
648 fprintf (file, "0x%08lx", l);
649 break;
652 /* Fall through. Let output_addr_const deal with it. */
653 default:
654 output_addr_const (file, x);
655 break;
658 return;
661 /*}}}*/
662 /*{{{ Function arguments */
664 /* Compute the number of word sized registers needed to hold a
665 function argument of mode INT_MODE and tree type TYPE. */
667 fr30_num_arg_regs (int_mode, type)
668 int int_mode;
669 tree type;
671 enum machine_mode mode = (enum machine_mode) int_mode;
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 entirly 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 (cum, int_mode, type, named)
695 CUMULATIVE_ARGS cum;
696 int int_mode;
697 tree type;
698 int named;
700 /* Unnamed arguments, ie those that are prototyped as ...
701 are always passed on the stack.
702 Also check here to see if all the argument registers are full. */
703 if (named == 0 || cum >= FR30_NUM_ARG_REGS)
704 return 0;
706 /* Work out how many argument registers would be needed if this
707 parameter were to be passed entirely in registers. If there
708 are sufficient argument registers available (or if no registers
709 are needed because the parameter must be passed on the stack)
710 then return zero, as this parameter does not require partial
711 register, partial stack stack space. */
712 if (cum + fr30_num_arg_regs (int_mode, type) <= FR30_NUM_ARG_REGS)
713 return 0;
715 /* Otherwise return the number of registers that would be used. */
716 return FR30_NUM_ARG_REGS - cum;
719 static rtx
720 fr30_pass_by_reference (valist, type)
721 tree valist;
722 tree type;
724 tree type_ptr;
725 tree type_ptr_ptr;
726 tree t;
728 type_ptr = build_pointer_type (type);
729 type_ptr_ptr = build_pointer_type (type_ptr);
731 t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (UNITS_PER_WORD, 0));
732 TREE_SIDE_EFFECTS (t) = 1;
733 t = build1 (NOP_EXPR, type_ptr_ptr, t);
734 TREE_SIDE_EFFECTS (t) = 1;
735 t = build1 (INDIRECT_REF, type_ptr, t);
737 return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
740 static rtx
741 fr30_pass_by_value (valist, type)
742 tree valist;
743 tree type;
745 HOST_WIDE_INT size = int_size_in_bytes (type);
746 HOST_WIDE_INT rsize;
747 rtx addr_rtx;
748 tree t;
750 if ((size % UNITS_PER_WORD) == 0)
752 t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (size, 0));
753 TREE_SIDE_EFFECTS (t) = 1;
755 return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
758 rsize = (size + UNITS_PER_WORD - 1) & - UNITS_PER_WORD;
760 /* Care for bigendian correction on the aligned address. */
761 t = build (PLUS_EXPR, ptr_type_node, valist, build_int_2 (rsize - size, 0));
762 addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
763 addr_rtx = copy_to_reg (addr_rtx);
765 /* Increment AP. */
766 t = build (PLUS_EXPR, va_list_type_node, valist, build_int_2 (rsize, 0));
767 t = build (MODIFY_EXPR, va_list_type_node, valist, t);
768 TREE_SIDE_EFFECTS (t) = 1;
769 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
771 return addr_rtx;
774 /* Implement `va_arg'. */
777 fr30_va_arg (valist, type)
778 tree valist;
779 tree type;
781 HOST_WIDE_INT size;
783 if (AGGREGATE_TYPE_P (type))
784 return fr30_pass_by_reference (valist, type);
786 size = int_size_in_bytes (type);
788 if ((size % sizeof (int)) == 0
789 || size < 4)
790 return fr30_pass_by_value (valist, type);
792 return fr30_pass_by_reference (valist, type);
795 /*}}}*/
796 /*{{{ Operand predicates */
798 #ifndef Mmode
799 #define Mmode enum machine_mode
800 #endif
802 /* Returns true if OPERAND is an integer value suitable for use in
803 an ADDSP instruction. */
805 stack_add_operand (operand, mode)
806 rtx operand;
807 Mmode mode ATTRIBUTE_UNUSED;
809 return
810 (GET_CODE (operand) == CONST_INT
811 && INTVAL (operand) >= -512
812 && INTVAL (operand) <= 508
813 && ((INTVAL (operand) & 3) == 0));
816 /* Returns true if OPERAND is an integer value suitable for use in
817 an ADD por ADD2 instruction, or if it is a register. */
819 add_immediate_operand (operand, mode)
820 rtx operand;
821 Mmode mode ATTRIBUTE_UNUSED;
823 return
824 (GET_CODE (operand) == REG
825 || (GET_CODE (operand) == CONST_INT
826 && INTVAL (operand) >= -16
827 && INTVAL (operand) <= 15));
830 /* Returns true if OPERAND is hard register in the range 8 - 15. */
832 high_register_operand (operand, mode)
833 rtx operand;
834 Mmode mode ATTRIBUTE_UNUSED;
836 return
837 (GET_CODE (operand) == REG
838 && REGNO (operand) <= 15
839 && REGNO (operand) >= 8);
842 /* Returns true if OPERAND is hard register in the range 0 - 7. */
844 low_register_operand (operand, mode)
845 rtx operand;
846 Mmode mode ATTRIBUTE_UNUSED;
848 return
849 (GET_CODE (operand) == REG
850 && REGNO (operand) <= 7);
853 /* Returns true if OPERAND is suitable for use in a CALL insn. */
855 call_operand (operand, mode)
856 rtx operand;
857 Mmode mode ATTRIBUTE_UNUSED;
859 return (GET_CODE (operand) == MEM
860 && (GET_CODE (XEXP (operand, 0)) == SYMBOL_REF
861 || GET_CODE (XEXP (operand, 0)) == REG));
864 /* Returns TRUE if OP is a valid operand of a DImode operation. */
866 di_operand (op, mode)
867 rtx op;
868 Mmode mode;
870 if (register_operand (op, mode))
871 return TRUE;
873 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
874 return FALSE;
876 if (GET_CODE (op) == SUBREG)
877 op = SUBREG_REG (op);
879 switch (GET_CODE (op))
881 case CONST_DOUBLE:
882 case CONST_INT:
883 return TRUE;
885 case MEM:
886 return memory_address_p (DImode, XEXP (op, 0));
888 default:
889 return FALSE;
893 /* Returns TRUE if OP is a DImode register or MEM. */
895 nonimmediate_di_operand (op, mode)
896 rtx op;
897 Mmode mode;
899 if (register_operand (op, mode))
900 return TRUE;
902 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
903 return FALSE;
905 if (GET_CODE (op) == SUBREG)
906 op = SUBREG_REG (op);
908 if (GET_CODE (op) == MEM)
909 return memory_address_p (DImode, XEXP (op, 0));
911 return FALSE;
914 /* Returns true iff all the registers in the operands array
915 are in descending or ascending order. */
917 fr30_check_multiple_regs (operands, num_operands, descending)
918 rtx * operands;
919 int num_operands;
920 int descending;
922 if (descending)
924 unsigned int prev_regno = 0;
926 while (num_operands --)
928 if (GET_CODE (operands [num_operands]) != REG)
929 return 0;
931 if (REGNO (operands [num_operands]) < prev_regno)
932 return 0;
934 prev_regno = REGNO (operands [num_operands]);
937 else
939 unsigned int prev_regno = CONDITION_CODE_REGNUM;
941 while (num_operands --)
943 if (GET_CODE (operands [num_operands]) != REG)
944 return 0;
946 if (REGNO (operands [num_operands]) > prev_regno)
947 return 0;
949 prev_regno = REGNO (operands [num_operands]);
953 return 1;
957 fr30_const_double_is_zero (operand)
958 rtx operand;
960 REAL_VALUE_TYPE d;
962 if (operand == NULL || GET_CODE (operand) != CONST_DOUBLE)
963 return 0;
965 REAL_VALUE_FROM_CONST_DOUBLE (d, operand);
967 return REAL_VALUES_EQUAL (d, dconst0);
970 /*}}}*/
971 /*{{{ Instruction Output Routines */
973 /* Output a double word move.
974 It must be REG<-REG, REG<-MEM, MEM<-REG or REG<-CONST.
975 On the FR30 we are contrained by the fact that it does not
976 support offsetable addresses, and so we have to load the
977 address of the secnd word into the second destination register
978 before we can use it. */
981 fr30_move_double (operands)
982 rtx * operands;
984 rtx src = operands[1];
985 rtx dest = operands[0];
986 enum rtx_code src_code = GET_CODE (src);
987 enum rtx_code dest_code = GET_CODE (dest);
988 enum machine_mode mode = GET_MODE (dest);
989 rtx val;
991 start_sequence ();
993 if (dest_code == REG)
995 if (src_code == REG)
997 int reverse = (REGNO (dest) == REGNO (src) + 1);
999 /* We normally copy the low-numbered register first. However, if
1000 the first register of operand 0 is the same as the second register
1001 of operand 1, we must copy in the opposite order. */
1002 emit_insn (gen_rtx_SET (VOIDmode,
1003 operand_subword (dest, reverse, TRUE, mode),
1004 operand_subword (src, reverse, TRUE, mode)));
1006 emit_insn (gen_rtx_SET (VOIDmode,
1007 operand_subword (dest, !reverse, TRUE, mode),
1008 operand_subword (src, !reverse, TRUE, mode)));
1010 else if (src_code == MEM)
1012 rtx addr = XEXP (src, 0);
1013 int dregno = REGNO (dest);
1014 rtx dest0;
1015 rtx dest1;
1016 rtx new_mem;
1018 /* If the high-address word is used in the address, we
1019 must load it last. Otherwise, load it first. */
1020 int reverse = (refers_to_regno_p (dregno, dregno + 1, addr, 0) != 0);
1022 if (GET_CODE (addr) != REG)
1023 abort ();
1025 dest0 = operand_subword (dest, reverse, TRUE, mode);
1026 dest1 = operand_subword (dest, !reverse, TRUE, mode);
1028 if (reverse)
1030 emit_insn (gen_rtx_SET (VOIDmode, dest1,
1031 adjust_address (src, SImode, 0)));
1032 emit_insn (gen_rtx_SET (SImode, dest0,
1033 gen_rtx_REG (SImode, REGNO (addr))));
1034 emit_insn (gen_rtx_SET (SImode, dest0,
1035 plus_constant (dest0, UNITS_PER_WORD)));
1037 new_mem = gen_rtx_MEM (SImode, dest0);
1038 MEM_COPY_ATTRIBUTES (new_mem, src);
1040 emit_insn (gen_rtx_SET (VOIDmode, dest0, new_mem));
1042 else
1044 emit_insn (gen_rtx_SET (VOIDmode, dest0,
1045 adjust_address (src, SImode, 0)));
1046 emit_insn (gen_rtx_SET (SImode, dest1,
1047 gen_rtx_REG (SImode, REGNO (addr))));
1048 emit_insn (gen_rtx_SET (SImode, dest1,
1049 plus_constant (dest1, UNITS_PER_WORD)));
1051 new_mem = gen_rtx_MEM (SImode, dest1);
1052 MEM_COPY_ATTRIBUTES (new_mem, src);
1054 emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem));
1057 else if (src_code == CONST_INT || src_code == CONST_DOUBLE)
1059 rtx words[2];
1060 split_double (src, &words[0], &words[1]);
1061 emit_insn (gen_rtx_SET (VOIDmode,
1062 operand_subword (dest, 0, TRUE, mode),
1063 words[0]));
1065 emit_insn (gen_rtx_SET (VOIDmode,
1066 operand_subword (dest, 1, TRUE, mode),
1067 words[1]));
1070 else if (src_code == REG && dest_code == MEM)
1072 rtx addr = XEXP (dest, 0);
1073 rtx src0;
1074 rtx src1;
1076 if (GET_CODE (addr) != REG)
1077 abort ();
1079 src0 = operand_subword (src, 0, TRUE, mode);
1080 src1 = operand_subword (src, 1, TRUE, mode);
1082 emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, 0),
1083 src0));
1085 if (REGNO (addr) == STACK_POINTER_REGNUM
1086 || REGNO (addr) == FRAME_POINTER_REGNUM)
1087 emit_insn (gen_rtx_SET (VOIDmode,
1088 adjust_address (dest, SImode, UNITS_PER_WORD),
1089 src1));
1090 else
1092 rtx new_mem;
1094 /* We need a scratch register to hold the value of 'address + 4'.
1095 We ought to allow gcc to find one for us, but for now, just
1096 push one of the source registers. */
1097 emit_insn (gen_movsi_push (src0));
1098 emit_insn (gen_movsi_internal (src0, addr));
1099 emit_insn (gen_addsi_small_int (src0, src0, GEN_INT (UNITS_PER_WORD)));
1101 new_mem = gen_rtx_MEM (SImode, src0);
1102 MEM_COPY_ATTRIBUTES (new_mem, dest);
1104 emit_insn (gen_rtx_SET (VOIDmode, new_mem, src1));
1105 emit_insn (gen_movsi_pop (src0));
1108 else
1109 /* This should have been prevented by the constraints on movdi_insn. */
1110 abort ();
1112 val = get_insns ();
1113 end_sequence ();
1115 return val;
1117 /*}}}*/
1118 /* Local Variables: */
1119 /* folded-file: t */
1120 /* End: */