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)
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. */
26 #include "coretypes.h"
30 #include "hard-reg-set.h"
32 #include "insn-config.h"
33 #include "conditions.h"
34 #include "insn-attr.h"
45 #include "target-def.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 favor 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 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)
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. */
156 fr30_compute_frame_size (from_reg, to_reg)
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;
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;
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;
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)
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. */
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;
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. */
221 fr30_expand_prologue ()
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)
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;
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)
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
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;
301 RTX_FRAME_RELATED_P (part) = 1;
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;
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. */
349 fr30_expand_epilogue ()
353 /* Perform the inversion operations of the prologue. */
354 if (! current_frame_info.initialised)
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
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)));
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. */
408 fr30_setup_incoming_varargs (arg_regs_used_so_far, int_mode, type, pretend_size)
409 CUMULATIVE_ARGS arg_regs_used_so_far;
411 tree type ATTRIBUTE_UNUSED;
414 enum machine_mode mode = (enum machine_mode)int_mode;
418 /* All BLKmode values are passed by reference. */
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);
428 size = FR30_NUM_ARG_REGS - arg_regs_used_so_far;
433 * pretend_size = (size * UNITS_PER_WORD);
437 /*{{{ Printing operands */
439 /* Print a memory address as an operand to reference that memory location. */
442 fr30_print_operand_address (stream, address)
446 switch (GET_CODE (address))
449 output_addr_const (stream, address);
453 fprintf (stderr, "code = %x\n", GET_CODE (address));
455 output_operand_lossage ("fr30_print_operand_address: unhandled address");
460 /* Print an operand. */
463 fr30_print_operand (file, x, code)
473 /* Output a :D if this instruction is delayed. */
474 if (dbr_sequence_length () != 0)
479 /* Compute the register name of the second register in a hi/lo
481 if (GET_CODE (x) != REG)
482 output_operand_lossage ("fr30_print_operand: unrecognized %%p code");
484 fprintf (file, "r%d", REGNO (x) + 1);
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;
502 output_operand_lossage ("fr30_print_operand: unrecognized %%b code");
508 /* Convert GCC's comparison operators into the complimentary FR30
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;
523 output_operand_lossage ("fr30_print_operand: unrecognized %%B code");
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");
540 fprintf (file, "%d", val);
545 if (GET_CODE (x) != CONST_INT
548 output_operand_lossage ("fr30_print_operand: invalid %%x code");
550 fprintf (file, "%d", INTVAL (x) - 16);
554 if (GET_CODE (x) != CONST_DOUBLE)
555 output_operand_lossage ("fr30_print_operand: invalid %%F code");
560 real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x),
571 fprintf (stderr, "unknown code = %x\n", code);
572 output_operand_lossage ("fr30_print_operand: unknown code");
576 switch (GET_CODE (x))
579 fputs (reg_names [REGNO (x)], file);
585 switch (GET_CODE (x0))
588 if ((unsigned) REGNO (x0) >= ARRAY_SIZE (reg_names))
590 fprintf (file, "@%s", reg_names [REGNO (x0)]);
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:");
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:");
610 output_operand_lossage ("fr30_print_operand: unhandled MEM");
612 fprintf (file, "@(r14, #%d)", val);
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:");
621 output_operand_lossage ("fr30_print_operand: unhandled MEM");
623 fprintf (file, "@(r15, #%d)", val);
632 fprintf (stderr, "bad MEM code = %x\n", GET_CODE (x0));
634 output_operand_lossage ("fr30_print_operand: unhandled MEM");
640 /* We handle SFmode constants here as output_addr_const doesn't. */
641 if (GET_MODE (x) == SFmode)
646 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
647 REAL_VALUE_TO_TARGET_SINGLE (d, l);
648 fprintf (file, "0x%08lx", l);
652 /* Fall through. Let output_addr_const deal with it. */
654 output_addr_const (file, x);
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)
671 enum machine_mode mode = (enum machine_mode) int_mode;
674 if (MUST_PASS_IN_STACK (mode, type))
677 if (type && mode == BLKmode)
678 size = int_size_in_bytes (type);
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)
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)
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)
715 /* Otherwise return the number of registers that would be used. */
716 return FR30_NUM_ARG_REGS - cum;
720 fr30_pass_by_reference (valist, type)
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);
741 fr30_pass_by_value (valist, type)
745 HOST_WIDE_INT size = int_size_in_bytes (type);
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);
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);
774 /* Implement `va_arg'. */
777 fr30_va_arg (valist, type)
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
790 return fr30_pass_by_value (valist, type);
792 return fr30_pass_by_reference (valist, type);
796 /*{{{ Operand predicates */
799 #define Mmode enum machine_mode
802 /* Returns true if OPERAND is an integer value suitable for use in
803 an ADDSP instruction. */
805 stack_add_operand (operand, mode)
807 Mmode mode ATTRIBUTE_UNUSED;
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)
821 Mmode mode ATTRIBUTE_UNUSED;
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)
834 Mmode mode ATTRIBUTE_UNUSED;
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)
846 Mmode mode ATTRIBUTE_UNUSED;
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)
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)
870 if (register_operand (op, mode))
873 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
876 if (GET_CODE (op) == SUBREG)
877 op = SUBREG_REG (op);
879 switch (GET_CODE (op))
886 return memory_address_p (DImode, XEXP (op, 0));
893 /* Returns TRUE if OP is a DImode register or MEM. */
895 nonimmediate_di_operand (op, mode)
899 if (register_operand (op, mode))
902 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
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));
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)
924 unsigned int prev_regno = 0;
926 while (num_operands --)
928 if (GET_CODE (operands [num_operands]) != REG)
931 if (REGNO (operands [num_operands]) < prev_regno)
934 prev_regno = REGNO (operands [num_operands]);
939 unsigned int prev_regno = CONDITION_CODE_REGNUM;
941 while (num_operands --)
943 if (GET_CODE (operands [num_operands]) != REG)
946 if (REGNO (operands [num_operands]) > prev_regno)
949 prev_regno = REGNO (operands [num_operands]);
957 fr30_const_double_is_zero (operand)
962 if (operand == NULL || GET_CODE (operand) != CONST_DOUBLE)
965 REAL_VALUE_FROM_CONST_DOUBLE (d, operand);
967 return REAL_VALUES_EQUAL (d, dconst0);
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)
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);
993 if (dest_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);
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)
1025 dest0 = operand_subword (dest, reverse, TRUE, mode);
1026 dest1 = operand_subword (dest, !reverse, TRUE, mode);
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));
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)
1060 split_double (src, &words[0], &words[1]);
1061 emit_insn (gen_rtx_SET (VOIDmode,
1062 operand_subword (dest, 0, TRUE, mode),
1065 emit_insn (gen_rtx_SET (VOIDmode,
1066 operand_subword (dest, 1, TRUE, mode),
1070 else if (src_code == REG && dest_code == MEM)
1072 rtx addr = XEXP (dest, 0);
1076 if (GET_CODE (addr) != REG)
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),
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),
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));
1109 /* This should have been prevented by the constraints on movdi_insn. */
1118 /* Local Variables: */
1119 /* folded-file: t */