3 /* FR30 specific functions.
4 Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
5 Contributed by Cygnus Solutions.
7 This file is part of GNU CC.
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING. If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
31 #include "hard-reg-set.h"
33 #include "insn-config.h"
34 #include "conditions.h"
35 #include "insn-flags.h"
37 #include "insn-attr.h"
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
60 +-----------------------+ +-----------------------+ high
62 | local variables, | | local variables, |
63 | reg save area, etc. | | reg save area, etc. |
65 +-----------------------+ +-----------------------+
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 +-----------------------+
76 | register save area | |
78 +-----------------------+ | reg_size
80 +-----------------------+ |
81 FP ->| previous frame ptr | /
82 +-----------------------+
84 | local variables | | var_size
86 +-----------------------+
88 low | room for args to | |
89 memory | other funcs called | | args_size
92 +-----------------------+
94 Note, AP is a fake hard register. It will be eliminated in favour of
95 SP or FP as appropriate.
97 Note, Some or all of the stack sections above may be omitted if they
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 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
123 #define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM))
125 /* Tell prologue and epilogue if register REGNO should be saved / restored.
126 The return address and frame pointer are treated separately.
127 Don't consider them here. */
128 #define MUST_SAVE_REGISTER(regno) \
129 ( (regno) != RETURN_POINTER_REGNUM \
130 && (regno) != FRAME_POINTER_REGNUM \
131 && regs_ever_live [regno] \
132 && ! call_used_regs [regno] )
134 #define MUST_SAVE_FRAME_POINTER (regs_ever_live [FRAME_POINTER_REGNUM] || frame_pointer_needed)
135 #define MUST_SAVE_RETURN_POINTER (regs_ever_live [RETURN_POINTER_REGNUM] || profile_flag)
137 #if UNITS_PER_WORD == 4
138 #define WORD_ALIGN(SIZE) (((SIZE) + 3) & ~3)
141 /* Returns the number of bytes offset between FROM_REG and TO_REG
142 for the current function. As a side effect it fills in the
143 current_frame_info structure, if the data is available. */
145 fr30_compute_frame_size (from_reg, to_reg)
150 unsigned int return_value;
151 unsigned int var_size;
152 unsigned int args_size;
153 unsigned int pretend_size;
154 unsigned int reg_size;
157 var_size = WORD_ALIGN (get_frame_size ());
158 args_size = WORD_ALIGN (current_function_outgoing_args_size);
159 pretend_size = current_function_pretend_args_size;
164 /* Calculate space needed for registers. */
165 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++)
167 if (MUST_SAVE_REGISTER (regno))
169 reg_size += UNITS_PER_WORD;
174 current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER;
175 current_frame_info.save_rp = MUST_SAVE_RETURN_POINTER;
177 reg_size += (current_frame_info.save_fp + current_frame_info.save_rp)
180 /* Save computed information. */
181 current_frame_info.pretend_size = pretend_size;
182 current_frame_info.var_size = var_size;
183 current_frame_info.args_size = args_size;
184 current_frame_info.reg_size = reg_size;
185 current_frame_info.frame_size = args_size + var_size;
186 current_frame_info.total_size = args_size + var_size + reg_size + pretend_size;
187 current_frame_info.gmask = gmask;
188 current_frame_info.initialised = reload_completed;
190 /* Calculate the required distance. */
193 if (to_reg == STACK_POINTER_REGNUM)
194 return_value += args_size + var_size;
196 if (from_reg == ARG_POINTER_REGNUM)
197 return_value += reg_size;
202 /* Called after register allocation to add any instructions needed for the
203 prologue. Using a prologue insn is favored compared to putting all of the
204 instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler
205 to intermix instructions with the saves of the caller saved registers. In
206 some cases, it might be necessary to emit a barrier instruction as the last
207 insn to prevent such scheduling. */
210 fr30_expand_prologue ()
215 if (! current_frame_info.initialised)
216 fr30_compute_frame_size (0, 0);
218 /* This cases shouldn't happen. Catch it now. */
219 if (current_frame_info.total_size == 0
220 && current_frame_info.gmask)
223 /* Allocate space for register arguments if this is a variadic function. */
224 if (current_frame_info.pretend_size)
226 int regs_to_save = current_frame_info.pretend_size / UNITS_PER_WORD;
228 /* Push argument registers into the pretend arg area. */
229 for (regno = FIRST_ARG_REGNUM + FR30_NUM_ARG_REGS; regno --, regs_to_save --;)
231 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
232 RTX_FRAME_RELATED_P (insn) = 1;
236 if (current_frame_info.gmask)
238 /* Save any needed call-saved regs. */
239 for (regno = STACK_POINTER_REGNUM; regno--;)
241 if ((current_frame_info.gmask & (1 << regno)) != 0)
243 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
244 RTX_FRAME_RELATED_P (insn) = 1;
249 /* Save return address if necessary. */
250 if (current_frame_info.save_rp)
252 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode,
253 RETURN_POINTER_REGNUM)));
254 RTX_FRAME_RELATED_P (insn) = 1;
257 /* Save old frame pointer and create new one, if necessary. */
258 if (current_frame_info.save_fp)
260 if (current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
262 int enter_size = current_frame_info.frame_size + UNITS_PER_WORD;
265 insn = emit_insn (gen_enter_func (GEN_INT (enter_size)));
266 RTX_FRAME_RELATED_P (insn) = 1;
268 pattern = PATTERN (insn);
270 /* Also mark all 3 subexpressions as RTX_FRAME_RELATED_P. */
271 if (GET_CODE (pattern) == PARALLEL)
274 for (x = XVECLEN (pattern, 0); x--;)
276 rtx part = XVECEXP (pattern, 0, x);
278 /* One of the insns in the ENTER pattern updates the
279 frame pointer. If we do not actually need the frame
280 pointer in this function then this is a side effect
281 rather than a desired effect, so we do not mark that
282 insn as being related to the frame set up. Doing this
283 allows us to compile the crash66.C test file in the
285 if (! frame_pointer_needed
286 && GET_CODE (part) == SET
287 && REGNO (SET_DEST (part)) == HARD_FRAME_POINTER_REGNUM)
288 RTX_FRAME_RELATED_P (part) = 0;
290 RTX_FRAME_RELATED_P (part) = 1;
296 insn = emit_insn (gen_movsi_push (frame_pointer_rtx));
297 RTX_FRAME_RELATED_P (insn) = 1;
299 if (frame_pointer_needed)
301 insn = emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
302 RTX_FRAME_RELATED_P (insn) = 1;
307 /* Allocate the stack frame. */
308 if (current_frame_info.frame_size == 0)
309 ; /* Nothing to do. */
310 else if (current_frame_info.save_fp
311 && current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
312 ; /* Nothing to do. */
313 else if (current_frame_info.frame_size <= 512)
315 insn = emit_insn (gen_add_to_stack (GEN_INT (- current_frame_info.frame_size)));
316 RTX_FRAME_RELATED_P (insn) = 1;
320 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
321 insn = emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
322 RTX_FRAME_RELATED_P (insn) = 1;
323 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
324 RTX_FRAME_RELATED_P (insn) = 1;
327 if (profile_flag || profile_block_flag)
328 emit_insn (gen_blockage ());
331 /* Called after register allocation to add any instructions needed for the
332 epilogue. Using a epilogue insn is favored compared to putting all of the
333 instructions in the FUNCTION_EPILOGUE macro, since it allows the scheduler
334 to intermix instructions with the restores of the caller saved registers.
335 In some cases, it might be necessary to emit a barrier instruction as the
336 first insn to prevent such scheduling. */
338 fr30_expand_epilogue ()
342 /* Perform the inversion operations of the prologue. */
343 if (! current_frame_info.initialised)
346 /* Pop local variables and arguments off the stack.
347 If frame_pointer_needed is TRUE then the frame pointer register
348 has actually been used as a frame pointer, and we can recover
349 the stack pointer from it, otherwise we must unwind the stack
351 if (current_frame_info.frame_size > 0)
353 if (current_frame_info.save_fp && frame_pointer_needed)
355 emit_insn (gen_leave_func ());
356 current_frame_info.save_fp = 0;
358 else if (current_frame_info.frame_size <= 508)
359 emit_insn (gen_add_to_stack
360 (GEN_INT (current_frame_info.frame_size)));
363 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
364 emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
365 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
369 if (current_frame_info.save_fp)
370 emit_insn (gen_movsi_pop (frame_pointer_rtx));
372 /* Pop all the registers that were pushed. */
373 if (current_frame_info.save_rp)
374 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, RETURN_POINTER_REGNUM)));
376 for (regno = 0; regno < STACK_POINTER_REGNUM; regno ++)
377 if (current_frame_info.gmask & (1 << regno))
378 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno)));
380 if (current_frame_info.pretend_size)
381 emit_insn (gen_add_to_stack (GEN_INT (current_frame_info.pretend_size)));
383 /* Reset state info for each function. */
384 current_frame_info = zero_frame_info;
386 emit_jump_insn (gen_return_from_func ());
389 /* Do any needed setup for a variadic function. We must create a register
390 parameter block, and then copy any anonymous arguments, plus the last
391 named argument, from registers into memory. * copying actually done in
392 fr30_expand_prologue().
394 ARG_REGS_USED_SO_FAR has *not* been updated for the last named argument
395 which has type TYPE and mode MODE, and we rely on this fact. */
397 fr30_setup_incoming_varargs (arg_regs_used_so_far, int_mode, type, pretend_size)
398 CUMULATIVE_ARGS arg_regs_used_so_far;
400 tree type ATTRIBUTE_UNUSED;
403 enum machine_mode mode = (enum machine_mode)int_mode;
407 /* All BLKmode values are passed by reference. */
411 #if STRICT_ARGUMENT_NAMING
412 /* We must treat `__builtin_va_alist' as an anonymous arg.
413 But otherwise if STRICT_ARGUMENT_NAMING is true then the
414 last named arg must not be treated as an anonymous arg. */
415 if (! current_function_varargs)
416 arg_regs_used_so_far += fr30_num_arg_regs (int_mode, type);
419 size = FR30_NUM_ARG_REGS - arg_regs_used_so_far;
424 * pretend_size = (size * UNITS_PER_WORD);
428 /*{{{ Printing operands */
430 /* Print a memory address as an operand to reference that memory location. */
433 fr30_print_operand_address (stream, address)
437 switch (GET_CODE (address))
440 output_addr_const (stream, address);
444 fprintf (stderr, "code = %x\n", GET_CODE (address));
446 output_operand_lossage ("fr30_print_operand_address: unhandled address");
451 /* Print an operand. */
454 fr30_print_operand (file, x, code)
464 /* Output a :D if this instruction is delayed. */
465 if (dbr_sequence_length () != 0)
470 /* Compute the register name of the second register in a hi/lo
472 if (GET_CODE (x) != REG)
473 output_operand_lossage ("fr30_print_operand: unrecognised %p code");
475 fprintf (file, "r%d", REGNO (x) + 1);
479 /* Convert GCC's comparison operators into FR30 comparison codes. */
480 switch (GET_CODE (x))
482 case EQ: fprintf (file, "eq"); break;
483 case NE: fprintf (file, "ne"); break;
484 case LT: fprintf (file, "lt"); break;
485 case LE: fprintf (file, "le"); break;
486 case GT: fprintf (file, "gt"); break;
487 case GE: fprintf (file, "ge"); break;
488 case LTU: fprintf (file, "c"); break;
489 case LEU: fprintf (file, "ls"); break;
490 case GTU: fprintf (file, "hi"); break;
491 case GEU: fprintf (file, "nc"); break;
493 output_operand_lossage ("fr30_print_operand: unrecognised %b code");
499 /* Convert GCC's comparison operators into the complimentary FR30
501 switch (GET_CODE (x))
503 case EQ: fprintf (file, "ne"); break;
504 case NE: fprintf (file, "eq"); break;
505 case LT: fprintf (file, "ge"); break;
506 case LE: fprintf (file, "gt"); break;
507 case GT: fprintf (file, "le"); break;
508 case GE: fprintf (file, "lt"); break;
509 case LTU: fprintf (file, "nc"); break;
510 case LEU: fprintf (file, "hi"); break;
511 case GTU: fprintf (file, "ls"); break;
512 case GEU: fprintf (file, "c"); break;
514 output_operand_lossage ("fr30_print_operand: unrecognised %B code");
520 /* Print a signed byte value as an unsigned value. */
521 if (GET_CODE (x) != CONST_INT)
522 output_operand_lossage ("fr30_print_operand: invalid operand to %A code");
531 fprintf (file, "%d", val);
536 if (GET_CODE (x) != CONST_INT
539 output_operand_lossage ("fr30_print_operand: invalid %x code");
541 fprintf (file, "%d", INTVAL (x) - 16);
545 if (GET_CODE (x) != CONST_DOUBLE)
546 output_operand_lossage ("fr30_print_operand: invalid %F code");
551 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
552 fprintf (file, "%.8f", d);
561 fprintf (stderr, "unknown code = %x\n", code);
562 output_operand_lossage ("fr30_print_operand: unknown code");
566 switch (GET_CODE (x))
569 fputs (reg_names [REGNO (x)], file);
575 switch (GET_CODE (x0))
578 if ((unsigned) REGNO (x0) >= (sizeof (reg_names) / sizeof (reg_names[0])))
580 fprintf (file, "@%s", reg_names [REGNO (x0)]);
584 if (GET_CODE (XEXP (x0, 0)) != REG
585 || REGNO (XEXP (x0, 0)) < FRAME_POINTER_REGNUM
586 || REGNO (XEXP (x0, 0)) > STACK_POINTER_REGNUM
587 || GET_CODE (XEXP (x0, 1)) != CONST_INT)
589 fprintf (stderr, "bad INDEXed address:");
591 output_operand_lossage ("fr30_print_operand: unhandled MEM");
593 else if (REGNO (XEXP (x0, 0)) == FRAME_POINTER_REGNUM)
595 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
596 if (val < -(1 << 9) || val > ((1 << 9) - 4))
598 fprintf (stderr, "frame INDEX out of range:");
600 output_operand_lossage ("fr30_print_operand: unhandled MEM");
602 fprintf (file, "@(r14, #%d)", val);
606 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
607 if (val < 0 || val > ((1 << 6) - 4))
609 fprintf (stderr, "stack INDEX out of range:");
611 output_operand_lossage ("fr30_print_operand: unhandled MEM");
613 fprintf (file, "@(r15, #%d)", val);
622 fprintf (stderr, "bad MEM code = %x\n", GET_CODE (x0));
624 output_operand_lossage ("fr30_print_operand: unhandled MEM");
630 /* We handle SFmode constants here as output_addr_const doesn't. */
631 if (GET_MODE (x) == SFmode)
636 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
637 REAL_VALUE_TO_TARGET_SINGLE (d, l);
638 fprintf (file, "0x%08lx", l);
642 /* Fall through. Let output_addr_const deal with it. */
644 output_addr_const (file, x);
652 /*{{{ Function arguments */
654 /* Compute the number of word sized registers needed to hold a
655 function argument of mode INT_MODE and tree type TYPE. */
657 fr30_num_arg_regs (int_mode, type)
661 enum machine_mode mode = (enum machine_mode) int_mode;
664 if (MUST_PASS_IN_STACK (mode, type))
667 if (type && mode == BLKmode)
668 size = int_size_in_bytes (type);
670 size = GET_MODE_SIZE (mode);
672 return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
675 /* Implements the FUNCTION_ARG_PARTIAL_NREGS macro.
676 Returns the number of argument registers required to hold *part* of
677 a parameter of machine mode MODE and tree type TYPE (which may be
678 NULL if the type is not known). If the argument fits entirly in
679 the argument registers, or entirely on the stack, then 0 is returned.
680 CUM is the number of argument registers already used by earlier
681 parameters to the function. */
684 fr30_function_arg_partial_nregs (cum, int_mode, type, named)
690 /* Unnamed arguments, ie those that are prototyped as ...
691 are always passed on the stack.
692 Also check here to see if all the argument registers are full. */
693 if (named == 0 || cum >= FR30_NUM_ARG_REGS)
696 /* Work out how many argument registers would be needed if this
697 parameter were to be passed entirely in registers. If there
698 are sufficient argument registers available (or if no registers
699 are needed because the parameter must be passed on the stack)
700 then return zero, as this parameter does not require partial
701 register, partial stack stack space. */
702 if (cum + fr30_num_arg_regs (int_mode, type) <= FR30_NUM_ARG_REGS)
705 /* Otherwise return the number of registers that would be used. */
706 return FR30_NUM_ARG_REGS - cum;
710 fr30_pass_by_reference (valist, type)
718 type_ptr = build_pointer_type (type);
719 type_ptr_ptr = build_pointer_type (type_ptr);
721 t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (UNITS_PER_WORD, 0));
722 TREE_SIDE_EFFECTS (t) = 1;
723 t = build1 (NOP_EXPR, type_ptr_ptr, t);
724 TREE_SIDE_EFFECTS (t) = 1;
725 t = build1 (INDIRECT_REF, type_ptr, t);
727 return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
731 fr30_pass_by_value (valist, type)
735 HOST_WIDE_INT size = int_size_in_bytes (type);
740 if ((size % UNITS_PER_WORD) == 0)
742 t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (size, 0));
743 TREE_SIDE_EFFECTS (t) = 1;
745 return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
748 rsize = (size + UNITS_PER_WORD - 1) & - UNITS_PER_WORD;
750 /* Care for bigendian correction on the aligned address. */
751 t = build (PLUS_EXPR, ptr_type_node, valist, build_int_2 (rsize - size, 0));
752 addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
753 addr_rtx = copy_to_reg (addr_rtx);
756 t = build (PLUS_EXPR, va_list_type_node, valist, build_int_2 (rsize, 0));
757 t = build (MODIFY_EXPR, va_list_type_node, valist, t);
758 TREE_SIDE_EFFECTS (t) = 1;
759 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
764 /* Implement `va_arg'. */
767 fr30_va_arg (valist, type)
773 if (AGGREGATE_TYPE_P (type))
774 return fr30_pass_by_reference (valist, type);
776 size = int_size_in_bytes (type);
778 if ((size % sizeof (int)) == 0
780 return fr30_pass_by_value (valist, type);
782 return fr30_pass_by_reference (valist, type);
786 /*{{{ Operand predicates */
789 #define Mmode enum machine_mode
792 /* Returns true if OPERAND is an integer value suitable for use in
793 an ADDSP instruction. */
795 stack_add_operand (operand, mode)
797 Mmode mode ATTRIBUTE_UNUSED;
800 (GET_CODE (operand) == CONST_INT
801 && INTVAL (operand) >= -512
802 && INTVAL (operand) <= 508
803 && ((INTVAL (operand) & 3) == 0));
806 /* Returns true if OPERAND is an integer value suitable for use in
807 an ADD por ADD2 instruction, or if it is a register. */
809 add_immediate_operand (operand, mode)
811 Mmode mode ATTRIBUTE_UNUSED;
814 (GET_CODE (operand) == REG
815 || (GET_CODE (operand) == CONST_INT
816 && INTVAL (operand) >= -16
817 && INTVAL (operand) <= 15));
820 /* Returns true if OPERAND is hard register in the range 8 - 15. */
822 high_register_operand (operand, mode)
824 Mmode mode ATTRIBUTE_UNUSED;
827 (GET_CODE (operand) == REG
828 && REGNO (operand) <= 15
829 && REGNO (operand) >= 8);
832 /* Returns true if OPERAND is hard register in the range 0 - 7. */
834 low_register_operand (operand, mode)
836 Mmode mode ATTRIBUTE_UNUSED;
839 (GET_CODE (operand) == REG
840 && REGNO (operand) <= 7);
843 /* Returns true if OPERAND is suitable for use in a CALL insn. */
845 call_operand (operand, mode)
847 Mmode mode ATTRIBUTE_UNUSED;
849 return (GET_CODE (operand) == MEM
850 && (GET_CODE (XEXP (operand, 0)) == SYMBOL_REF
851 || GET_CODE (XEXP (operand, 0)) == REG));
854 /* Returns TRUE if OP is a valid operand of a DImode operation. */
856 di_operand (op, mode)
860 if (register_operand (op, mode))
863 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
866 if (GET_CODE (op) == SUBREG)
867 op = SUBREG_REG (op);
869 switch (GET_CODE (op))
876 return memory_address_p (DImode, XEXP (op, 0));
883 /* Returns TRUE if OP is a DImode register or MEM. */
885 nonimmediate_di_operand (op, mode)
889 if (register_operand (op, mode))
892 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
895 if (GET_CODE (op) == SUBREG)
896 op = SUBREG_REG (op);
898 if (GET_CODE (op) == MEM)
899 return memory_address_p (DImode, XEXP (op, 0));
904 /* Returns true iff all the registers in the operands array
905 are in descending or ascending order. */
907 fr30_check_multiple_regs (operands, num_operands, descending)
914 unsigned int prev_regno = 0;
916 while (num_operands --)
918 if (GET_CODE (operands [num_operands]) != REG)
921 if (REGNO (operands [num_operands]) < prev_regno)
924 prev_regno = REGNO (operands [num_operands]);
929 unsigned int prev_regno = CONDITION_CODE_REGNUM;
931 while (num_operands --)
933 if (GET_CODE (operands [num_operands]) != REG)
936 if (REGNO (operands [num_operands]) > prev_regno)
939 prev_regno = REGNO (operands [num_operands]);
947 /*{{{ Instruction Output Routines */
949 /* Output a double word move.
950 It must be REG<-REG, REG<-MEM, MEM<-REG or REG<-CONST.
951 On the FR30 we are contrained by the fact that it does not
952 support offsetable addresses, and so we have to load the
953 address of the secnd word into the second destination register
954 before we can use it. */
957 fr30_move_double (operands)
960 rtx src = operands[1];
961 rtx dest = operands[0];
962 enum rtx_code src_code = GET_CODE (src);
963 enum rtx_code dest_code = GET_CODE (dest);
964 enum machine_mode mode = GET_MODE (dest);
969 if (dest_code == REG)
973 int reverse = (REGNO (dest) == REGNO (src) + 1);
975 /* We normally copy the low-numbered register first. However, if
976 the first register of operand 0 is the same as the second register
977 of operand 1, we must copy in the opposite order. */
978 emit_insn (gen_rtx_SET (VOIDmode,
979 operand_subword (dest, reverse, TRUE, mode),
980 operand_subword (src, reverse, TRUE, mode)));
982 emit_insn (gen_rtx_SET (VOIDmode,
983 operand_subword (dest, !reverse, TRUE, mode),
984 operand_subword (src, !reverse, TRUE, mode)));
986 else if (src_code == MEM)
988 rtx addr = XEXP (src, 0);
989 int dregno = REGNO (dest);
994 /* If the high-address word is used in the address, we
995 must load it last. Otherwise, load it first. */
996 int reverse = (refers_to_regno_p (dregno, dregno + 1, addr, 0) != 0);
998 if (GET_CODE (addr) != REG)
1001 dest0 = operand_subword (dest, reverse, TRUE, mode);
1002 dest1 = operand_subword (dest, !reverse, TRUE, mode);
1006 emit_insn (gen_rtx_SET (VOIDmode, dest1, change_address (src, SImode, addr)));
1007 emit_insn (gen_rtx_SET (SImode, dest0, gen_rtx_REG (SImode, REGNO (addr))));
1008 emit_insn (gen_rtx_SET (SImode, dest0, plus_constant (dest0, UNITS_PER_WORD)));
1010 new_mem = gen_rtx_MEM (SImode, dest0);
1011 MEM_COPY_ATTRIBUTES (new_mem, src);
1013 emit_insn (gen_rtx_SET (VOIDmode, dest0, new_mem));
1017 emit_insn (gen_rtx_SET (VOIDmode, dest0, change_address (src, SImode, addr)));
1018 emit_insn (gen_rtx_SET (SImode, dest1, gen_rtx_REG (SImode, REGNO (addr))));
1019 emit_insn (gen_rtx_SET (SImode, dest1, plus_constant (dest1, UNITS_PER_WORD)));
1021 new_mem = gen_rtx_MEM (SImode, dest1);
1022 MEM_COPY_ATTRIBUTES (new_mem, src);
1024 emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem));
1027 else if (src_code == CONST_INT || src_code == CONST_DOUBLE)
1030 split_double (src, &words[0], &words[1]);
1031 emit_insn (gen_rtx_SET (VOIDmode,
1032 operand_subword (dest, 0, TRUE, mode),
1035 emit_insn (gen_rtx_SET (VOIDmode,
1036 operand_subword (dest, 1, TRUE, mode),
1040 else if (src_code == REG && dest_code == MEM)
1042 rtx addr = XEXP (dest, 0);
1046 if (GET_CODE (addr) != REG)
1049 src0 = operand_subword (src, 0, TRUE, mode);
1050 src1 = operand_subword (src, 1, TRUE, mode);
1052 emit_insn (gen_rtx_SET (VOIDmode, change_address (dest, SImode, addr), src0));
1054 if (REGNO (addr) == STACK_POINTER_REGNUM)
1055 emit_insn (gen_rtx_SET (VOIDmode, change_address (dest, SImode, plus_constant (stack_pointer_rtx, UNITS_PER_WORD)), src1));
1056 else if (REGNO (addr) == FRAME_POINTER_REGNUM)
1057 emit_insn (gen_rtx_SET (VOIDmode, change_address (dest, SImode, plus_constant (frame_pointer_rtx, UNITS_PER_WORD)), src1));
1062 /* We need a scratch register to hold the value of 'address + 4'.
1063 We ought to allow gcc to find one for us, but for now, just
1064 push one of the source registers. */
1065 emit_insn (gen_movsi_push (src0));
1066 emit_insn (gen_movsi_internal (src0, addr));
1067 emit_insn (gen_addsi_small_int (src0, src0, GEN_INT (UNITS_PER_WORD)));
1069 new_mem = gen_rtx_MEM (SImode, src0);
1070 MEM_COPY_ATTRIBUTES (new_mem, dest);
1072 emit_insn (gen_rtx_SET (VOIDmode, new_mem, src1));
1073 emit_insn (gen_movsi_pop (src0));
1077 /* This should have been prevented by the contraints on movdi_insn. */
1080 val = gen_sequence ();
1088 /* Local Variables: */
1089 /* folded-file: t */