* target.h (asm_out.byte_op, asm_out.aligned_op, asm_out.unaligned_op,
[official-gcc.git] / gcc / config / fr30 / fr30.c
blobc386297a6465565612f91a4938cfe95055634772
1 /* FR30 specific functions.
2 Copyright (C) 1998, 1999, 2000, 2001 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 /*}}}*/
23 /*{{{ Includes */
25 #include "config.h"
26 #include "system.h"
27 #include "rtl.h"
28 #include "regs.h"
29 #include "hard-reg-set.h"
30 #include "real.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "output.h"
34 #include "insn-attr.h"
35 #include "flags.h"
36 #include "recog.h"
37 #include "tree.h"
38 #include "expr.h"
39 #include "obstack.h"
40 #include "except.h"
41 #include "function.h"
42 #include "tm_p.h"
43 #include "target.h"
44 #include "target-def.h"
46 /*}}}*/
47 /*{{{ Function Prologues & Epilogues */
49 /* Define the information needed to generate branch and scc insns. This is
50 stored from the compare operation. */
52 struct rtx_def * fr30_compare_op0;
53 struct rtx_def * fr30_compare_op1;
55 /* The FR30 stack looks like this:
57 Before call After call
58 FP ->| | | |
59 +-----------------------+ +-----------------------+ high
60 | | | | memory
61 | local variables, | | local variables, |
62 | reg save area, etc. | | reg save area, etc. |
63 | | | |
64 +-----------------------+ +-----------------------+
65 | | | |
66 | args to the func that | | args to this func. |
67 | is being called that | | |
68 SP ->| do not fit in regs | | |
69 +-----------------------+ +-----------------------+
70 | args that used to be | \
71 | in regs; only created | | pretend_size
72 AP-> | for vararg funcs | /
73 +-----------------------+
74 | | \
75 | register save area | |
76 | | |
77 +-----------------------+ | reg_size
78 | return address | |
79 +-----------------------+ |
80 FP ->| previous frame ptr | /
81 +-----------------------+
82 | | \
83 | local variables | | var_size
84 | | /
85 +-----------------------+
86 | | \
87 low | room for args to | |
88 memory | other funcs called | | args_size
89 | from this one | |
90 SP ->| | /
91 +-----------------------+
93 Note, AP is a fake hard register. It will be eliminated in favour of
94 SP or FP as appropriate.
96 Note, Some or all of the stack sections above may be omitted if they
97 are not needed. */
99 /* Structure to be filled in by fr30_compute_frame_size() with register
100 save masks, and offsets for the current function. */
101 struct fr30_frame_info
103 unsigned int total_size; /* # Bytes that the entire frame takes up. */
104 unsigned int pretend_size; /* # Bytes we push and pretend caller did. */
105 unsigned int args_size; /* # Bytes that outgoing arguments take up. */
106 unsigned int reg_size; /* # Bytes needed to store regs. */
107 unsigned int var_size; /* # Bytes that variables take up. */
108 unsigned int frame_size; /* # Bytes in current frame. */
109 unsigned int gmask; /* Mask of saved registers. */
110 unsigned int save_fp; /* Nonzero if frame pointer must be saved. */
111 unsigned int save_rp; /* Nonzero if return popinter must be saved. */
112 int initialised; /* Nonzero if frame size already calculated. */
115 /* Current frame information calculated by fr30_compute_frame_size(). */
116 static struct fr30_frame_info current_frame_info;
118 /* Zero structure to initialize current_frame_info. */
119 static struct fr30_frame_info zero_frame_info;
121 static rtx fr30_pass_by_reference PARAMS ((tree, tree));
122 static rtx fr30_pass_by_value PARAMS ((tree, tree));
124 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
125 #define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM))
127 /* Tell prologue and epilogue if register REGNO should be saved / restored.
128 The return address and frame pointer are treated separately.
129 Don't consider them here. */
130 #define MUST_SAVE_REGISTER(regno) \
131 ( (regno) != RETURN_POINTER_REGNUM \
132 && (regno) != FRAME_POINTER_REGNUM \
133 && regs_ever_live [regno] \
134 && ! call_used_regs [regno] )
136 #define MUST_SAVE_FRAME_POINTER (regs_ever_live [FRAME_POINTER_REGNUM] || frame_pointer_needed)
137 #define MUST_SAVE_RETURN_POINTER (regs_ever_live [RETURN_POINTER_REGNUM] || profile_flag)
139 #if UNITS_PER_WORD == 4
140 #define WORD_ALIGN(SIZE) (((SIZE) + 3) & ~3)
141 #endif
143 /* Initialize the GCC target structure. */
144 #undef TARGET_ASM_ALIGNED_HI_OP
145 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
146 #undef TARGET_ASM_ALIGNED_SI_OP
147 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
149 struct gcc_target targetm = TARGET_INITIALIZER;
151 /* Returns the number of bytes offset between FROM_REG and TO_REG
152 for the current function. As a side effect it fills in the
153 current_frame_info structure, if the data is available. */
154 unsigned int
155 fr30_compute_frame_size (from_reg, to_reg)
156 int from_reg;
157 int to_reg;
159 int regno;
160 unsigned int return_value;
161 unsigned int var_size;
162 unsigned int args_size;
163 unsigned int pretend_size;
164 unsigned int reg_size;
165 unsigned int gmask;
167 var_size = WORD_ALIGN (get_frame_size ());
168 args_size = WORD_ALIGN (current_function_outgoing_args_size);
169 pretend_size = current_function_pretend_args_size;
171 reg_size = 0;
172 gmask = 0;
174 /* Calculate space needed for registers. */
175 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++)
177 if (MUST_SAVE_REGISTER (regno))
179 reg_size += UNITS_PER_WORD;
180 gmask |= 1 << regno;
184 current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER;
185 current_frame_info.save_rp = MUST_SAVE_RETURN_POINTER;
187 reg_size += (current_frame_info.save_fp + current_frame_info.save_rp)
188 * UNITS_PER_WORD;
190 /* Save computed information. */
191 current_frame_info.pretend_size = pretend_size;
192 current_frame_info.var_size = var_size;
193 current_frame_info.args_size = args_size;
194 current_frame_info.reg_size = reg_size;
195 current_frame_info.frame_size = args_size + var_size;
196 current_frame_info.total_size = args_size + var_size + reg_size + pretend_size;
197 current_frame_info.gmask = gmask;
198 current_frame_info.initialised = reload_completed;
200 /* Calculate the required distance. */
201 return_value = 0;
203 if (to_reg == STACK_POINTER_REGNUM)
204 return_value += args_size + var_size;
206 if (from_reg == ARG_POINTER_REGNUM)
207 return_value += reg_size;
209 return return_value;
212 /* Called after register allocation to add any instructions needed for the
213 prologue. Using a prologue insn is favored compared to putting all of the
214 instructions in output_function_prologue(), since it allows the scheduler
215 to intermix instructions with the saves of the caller saved registers. In
216 some cases, it might be necessary to emit a barrier instruction as the last
217 insn to prevent such scheduling. */
219 void
220 fr30_expand_prologue ()
222 int regno;
223 rtx insn;
225 if (! current_frame_info.initialised)
226 fr30_compute_frame_size (0, 0);
228 /* This cases shouldn't happen. Catch it now. */
229 if (current_frame_info.total_size == 0
230 && current_frame_info.gmask)
231 abort ();
233 /* Allocate space for register arguments if this is a variadic function. */
234 if (current_frame_info.pretend_size)
236 int regs_to_save = current_frame_info.pretend_size / UNITS_PER_WORD;
238 /* Push argument registers into the pretend arg area. */
239 for (regno = FIRST_ARG_REGNUM + FR30_NUM_ARG_REGS; regno --, regs_to_save --;)
241 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
242 RTX_FRAME_RELATED_P (insn) = 1;
246 if (current_frame_info.gmask)
248 /* Save any needed call-saved regs. */
249 for (regno = STACK_POINTER_REGNUM; regno--;)
251 if ((current_frame_info.gmask & (1 << regno)) != 0)
253 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
254 RTX_FRAME_RELATED_P (insn) = 1;
259 /* Save return address if necessary. */
260 if (current_frame_info.save_rp)
262 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode,
263 RETURN_POINTER_REGNUM)));
264 RTX_FRAME_RELATED_P (insn) = 1;
267 /* Save old frame pointer and create new one, if necessary. */
268 if (current_frame_info.save_fp)
270 if (current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
272 int enter_size = current_frame_info.frame_size + UNITS_PER_WORD;
273 rtx pattern;
275 insn = emit_insn (gen_enter_func (GEN_INT (enter_size)));
276 RTX_FRAME_RELATED_P (insn) = 1;
278 pattern = PATTERN (insn);
280 /* Also mark all 3 subexpressions as RTX_FRAME_RELATED_P. */
281 if (GET_CODE (pattern) == PARALLEL)
283 int x;
284 for (x = XVECLEN (pattern, 0); x--;)
286 rtx part = XVECEXP (pattern, 0, x);
288 /* One of the insns in the ENTER pattern updates the
289 frame pointer. If we do not actually need the frame
290 pointer in this function then this is a side effect
291 rather than a desired effect, so we do not mark that
292 insn as being related to the frame set up. Doing this
293 allows us to compile the crash66.C test file in the
294 G++ testsuite. */
295 if (! frame_pointer_needed
296 && GET_CODE (part) == SET
297 && REGNO (SET_DEST (part)) == HARD_FRAME_POINTER_REGNUM)
298 RTX_FRAME_RELATED_P (part) = 0;
299 else
300 RTX_FRAME_RELATED_P (part) = 1;
304 else
306 insn = emit_insn (gen_movsi_push (frame_pointer_rtx));
307 RTX_FRAME_RELATED_P (insn) = 1;
309 if (frame_pointer_needed)
311 insn = emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
312 RTX_FRAME_RELATED_P (insn) = 1;
317 /* Allocate the stack frame. */
318 if (current_frame_info.frame_size == 0)
319 ; /* Nothing to do. */
320 else if (current_frame_info.save_fp
321 && current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
322 ; /* Nothing to do. */
323 else if (current_frame_info.frame_size <= 512)
325 insn = emit_insn (gen_add_to_stack (GEN_INT (- current_frame_info.frame_size)));
326 RTX_FRAME_RELATED_P (insn) = 1;
328 else
330 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
331 insn = emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
332 RTX_FRAME_RELATED_P (insn) = 1;
333 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
334 RTX_FRAME_RELATED_P (insn) = 1;
337 if (profile_flag)
338 emit_insn (gen_blockage ());
341 /* Called after register allocation to add any instructions needed for the
342 epilogue. Using an epilogue insn is favored compared to putting all of the
343 instructions in output_function_epilogue(), since it allows the scheduler
344 to intermix instructions with the restores of the caller saved registers.
345 In some cases, it might be necessary to emit a barrier instruction as the
346 first insn to prevent such scheduling. */
347 void
348 fr30_expand_epilogue ()
350 int regno;
352 /* Perform the inversion operations of the prologue. */
353 if (! current_frame_info.initialised)
354 abort ();
356 /* Pop local variables and arguments off the stack.
357 If frame_pointer_needed is TRUE then the frame pointer register
358 has actually been used as a frame pointer, and we can recover
359 the stack pointer from it, otherwise we must unwind the stack
360 manually. */
361 if (current_frame_info.frame_size > 0)
363 if (current_frame_info.save_fp && frame_pointer_needed)
365 emit_insn (gen_leave_func ());
366 current_frame_info.save_fp = 0;
368 else if (current_frame_info.frame_size <= 508)
369 emit_insn (gen_add_to_stack
370 (GEN_INT (current_frame_info.frame_size)));
371 else
373 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
374 emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
375 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
379 if (current_frame_info.save_fp)
380 emit_insn (gen_movsi_pop (frame_pointer_rtx));
382 /* Pop all the registers that were pushed. */
383 if (current_frame_info.save_rp)
384 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, RETURN_POINTER_REGNUM)));
386 for (regno = 0; regno < STACK_POINTER_REGNUM; regno ++)
387 if (current_frame_info.gmask & (1 << regno))
388 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno)));
390 if (current_frame_info.pretend_size)
391 emit_insn (gen_add_to_stack (GEN_INT (current_frame_info.pretend_size)));
393 /* Reset state info for each function. */
394 current_frame_info = zero_frame_info;
396 emit_jump_insn (gen_return_from_func ());
399 /* Do any needed setup for a variadic function. We must create a register
400 parameter block, and then copy any anonymous arguments, plus the last
401 named argument, from registers into memory. * copying actually done in
402 fr30_expand_prologue().
404 ARG_REGS_USED_SO_FAR has *not* been updated for the last named argument
405 which has type TYPE and mode MODE, and we rely on this fact. */
406 void
407 fr30_setup_incoming_varargs (arg_regs_used_so_far, int_mode, type, pretend_size)
408 CUMULATIVE_ARGS arg_regs_used_so_far;
409 int int_mode;
410 tree type ATTRIBUTE_UNUSED;
411 int * pretend_size;
413 enum machine_mode mode = (enum machine_mode)int_mode;
414 int size;
417 /* All BLKmode values are passed by reference. */
418 if (mode == BLKmode)
419 abort ();
421 #if STRICT_ARGUMENT_NAMING
422 /* We must treat `__builtin_va_alist' as an anonymous arg.
423 But otherwise if STRICT_ARGUMENT_NAMING is true then the
424 last named arg must not be treated as an anonymous arg. */
425 if (! current_function_varargs)
426 arg_regs_used_so_far += fr30_num_arg_regs (int_mode, type);
427 #endif
429 size = FR30_NUM_ARG_REGS - arg_regs_used_so_far;
431 if (size <= 0)
432 return;
434 * pretend_size = (size * UNITS_PER_WORD);
437 /*}}}*/
438 /*{{{ Printing operands */
440 /* Print a memory address as an operand to reference that memory location. */
442 void
443 fr30_print_operand_address (stream, address)
444 FILE * stream;
445 rtx address;
447 switch (GET_CODE (address))
449 case SYMBOL_REF:
450 output_addr_const (stream, address);
451 break;
453 default:
454 fprintf (stderr, "code = %x\n", GET_CODE (address));
455 debug_rtx (address);
456 output_operand_lossage ("fr30_print_operand_address: unhandled address");
457 break;
461 /* Print an operand. */
463 void
464 fr30_print_operand (file, x, code)
465 FILE * file;
466 rtx x;
467 int code;
469 rtx x0;
471 switch (code)
473 case '#':
474 /* Output a :D if this instruction is delayed. */
475 if (dbr_sequence_length () != 0)
476 fputs (":D", file);
477 return;
479 case 'p':
480 /* Compute the register name of the second register in a hi/lo
481 register pair. */
482 if (GET_CODE (x) != REG)
483 output_operand_lossage ("fr30_print_operand: unrecognized %p code");
484 else
485 fprintf (file, "r%d", REGNO (x) + 1);
486 return;
488 case 'b':
489 /* Convert GCC's comparison operators into FR30 comparison codes. */
490 switch (GET_CODE (x))
492 case EQ: fprintf (file, "eq"); break;
493 case NE: fprintf (file, "ne"); break;
494 case LT: fprintf (file, "lt"); break;
495 case LE: fprintf (file, "le"); break;
496 case GT: fprintf (file, "gt"); break;
497 case GE: fprintf (file, "ge"); break;
498 case LTU: fprintf (file, "c"); break;
499 case LEU: fprintf (file, "ls"); break;
500 case GTU: fprintf (file, "hi"); break;
501 case GEU: fprintf (file, "nc"); break;
502 default:
503 output_operand_lossage ("fr30_print_operand: unrecognized %b code");
504 break;
506 return;
508 case 'B':
509 /* Convert GCC's comparison operators into the complimentary FR30
510 comparison codes. */
511 switch (GET_CODE (x))
513 case EQ: fprintf (file, "ne"); break;
514 case NE: fprintf (file, "eq"); break;
515 case LT: fprintf (file, "ge"); break;
516 case LE: fprintf (file, "gt"); break;
517 case GT: fprintf (file, "le"); break;
518 case GE: fprintf (file, "lt"); break;
519 case LTU: fprintf (file, "nc"); break;
520 case LEU: fprintf (file, "hi"); break;
521 case GTU: fprintf (file, "ls"); break;
522 case GEU: fprintf (file, "c"); break;
523 default:
524 output_operand_lossage ("fr30_print_operand: unrecognized %B code");
525 break;
527 return;
529 case 'A':
530 /* Print a signed byte value as an unsigned value. */
531 if (GET_CODE (x) != CONST_INT)
532 output_operand_lossage ("fr30_print_operand: invalid operand to %A code");
533 else
535 HOST_WIDE_INT val;
537 val = INTVAL (x);
539 val &= 0xff;
541 fprintf (file, "%d", val);
543 return;
545 case 'x':
546 if (GET_CODE (x) != CONST_INT
547 || INTVAL (x) < 16
548 || INTVAL (x) > 32)
549 output_operand_lossage ("fr30_print_operand: invalid %x code");
550 else
551 fprintf (file, "%d", INTVAL (x) - 16);
552 return;
554 case 'F':
555 if (GET_CODE (x) != CONST_DOUBLE)
556 output_operand_lossage ("fr30_print_operand: invalid %F code");
557 else
559 REAL_VALUE_TYPE d;
561 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
562 fprintf (file, "%.8f", d);
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;
956 /*}}}*/
957 /*{{{ Instruction Output Routines */
959 /* Output a double word move.
960 It must be REG<-REG, REG<-MEM, MEM<-REG or REG<-CONST.
961 On the FR30 we are contrained by the fact that it does not
962 support offsetable addresses, and so we have to load the
963 address of the secnd word into the second destination register
964 before we can use it. */
967 fr30_move_double (operands)
968 rtx * operands;
970 rtx src = operands[1];
971 rtx dest = operands[0];
972 enum rtx_code src_code = GET_CODE (src);
973 enum rtx_code dest_code = GET_CODE (dest);
974 enum machine_mode mode = GET_MODE (dest);
975 rtx val;
977 start_sequence ();
979 if (dest_code == REG)
981 if (src_code == REG)
983 int reverse = (REGNO (dest) == REGNO (src) + 1);
985 /* We normally copy the low-numbered register first. However, if
986 the first register of operand 0 is the same as the second register
987 of operand 1, we must copy in the opposite order. */
988 emit_insn (gen_rtx_SET (VOIDmode,
989 operand_subword (dest, reverse, TRUE, mode),
990 operand_subword (src, reverse, TRUE, mode)));
992 emit_insn (gen_rtx_SET (VOIDmode,
993 operand_subword (dest, !reverse, TRUE, mode),
994 operand_subword (src, !reverse, TRUE, mode)));
996 else if (src_code == MEM)
998 rtx addr = XEXP (src, 0);
999 int dregno = REGNO (dest);
1000 rtx dest0;
1001 rtx dest1;
1002 rtx new_mem;
1004 /* If the high-address word is used in the address, we
1005 must load it last. Otherwise, load it first. */
1006 int reverse = (refers_to_regno_p (dregno, dregno + 1, addr, 0) != 0);
1008 if (GET_CODE (addr) != REG)
1009 abort ();
1011 dest0 = operand_subword (dest, reverse, TRUE, mode);
1012 dest1 = operand_subword (dest, !reverse, TRUE, mode);
1014 if (reverse)
1016 emit_insn (gen_rtx_SET (VOIDmode, dest1,
1017 adjust_address (src, SImode, 0)));
1018 emit_insn (gen_rtx_SET (SImode, dest0,
1019 gen_rtx_REG (SImode, REGNO (addr))));
1020 emit_insn (gen_rtx_SET (SImode, dest0,
1021 plus_constant (dest0, UNITS_PER_WORD)));
1023 new_mem = gen_rtx_MEM (SImode, dest0);
1024 MEM_COPY_ATTRIBUTES (new_mem, src);
1026 emit_insn (gen_rtx_SET (VOIDmode, dest0, new_mem));
1028 else
1030 emit_insn (gen_rtx_SET (VOIDmode, dest0,
1031 adjust_address (src, SImode, 0)));
1032 emit_insn (gen_rtx_SET (SImode, dest1,
1033 gen_rtx_REG (SImode, REGNO (addr))));
1034 emit_insn (gen_rtx_SET (SImode, dest1,
1035 plus_constant (dest1, UNITS_PER_WORD)));
1037 new_mem = gen_rtx_MEM (SImode, dest1);
1038 MEM_COPY_ATTRIBUTES (new_mem, src);
1040 emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem));
1043 else if (src_code == CONST_INT || src_code == CONST_DOUBLE)
1045 rtx words[2];
1046 split_double (src, &words[0], &words[1]);
1047 emit_insn (gen_rtx_SET (VOIDmode,
1048 operand_subword (dest, 0, TRUE, mode),
1049 words[0]));
1051 emit_insn (gen_rtx_SET (VOIDmode,
1052 operand_subword (dest, 1, TRUE, mode),
1053 words[1]));
1056 else if (src_code == REG && dest_code == MEM)
1058 rtx addr = XEXP (dest, 0);
1059 rtx src0;
1060 rtx src1;
1062 if (GET_CODE (addr) != REG)
1063 abort ();
1065 src0 = operand_subword (src, 0, TRUE, mode);
1066 src1 = operand_subword (src, 1, TRUE, mode);
1068 emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, 0),
1069 src0));
1071 if (REGNO (addr) == STACK_POINTER_REGNUM
1072 || REGNO (addr) == FRAME_POINTER_REGNUM)
1073 emit_insn (gen_rtx_SET (VOIDmode,
1074 adjust_address (dest, SImode, UNITS_PER_WORD),
1075 src1));
1076 else
1078 rtx new_mem;
1080 /* We need a scratch register to hold the value of 'address + 4'.
1081 We ought to allow gcc to find one for us, but for now, just
1082 push one of the source registers. */
1083 emit_insn (gen_movsi_push (src0));
1084 emit_insn (gen_movsi_internal (src0, addr));
1085 emit_insn (gen_addsi_small_int (src0, src0, GEN_INT (UNITS_PER_WORD)));
1087 new_mem = gen_rtx_MEM (SImode, src0);
1088 MEM_COPY_ATTRIBUTES (new_mem, dest);
1090 emit_insn (gen_rtx_SET (VOIDmode, new_mem, src1));
1091 emit_insn (gen_movsi_pop (src0));
1094 else
1095 /* This should have been prevented by the constraints on movdi_insn. */
1096 abort ();
1098 val = gen_sequence ();
1099 end_sequence ();
1101 return val;