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. */
29 #include <sys/param.h> /* so that MIn and MAX are defined before machmode.h */
33 #include "hard-reg-set.h"
35 #include "insn-config.h"
36 #include "conditions.h"
37 #include "insn-flags.h"
39 #include "insn-attr.h"
47 #include "fr30-protos.h"
50 /*{{{ Function Prologues & Epilogues */
52 /* Define the information needed to generate branch and scc insns. This is
53 stored from the compare operation. */
55 struct rtx_def * fr30_compare_op0;
56 struct rtx_def * fr30_compare_op1;
58 /* The FR30 stack looks like this:
60 Before call After call
62 +-----------------------+ +-----------------------+ high
64 | local variables, | | local variables, |
65 | reg save area, etc. | | reg save area, etc. |
67 +-----------------------+ +-----------------------+
69 | args to the func that | | args to this func. |
70 | is being called that | | |
71 SP ->| do not fit in regs | | |
72 +-----------------------+ +-----------------------+
73 | args that used to be | \
74 | in regs; only created | | pretend_size
75 AP-> | for vararg funcs | /
76 +-----------------------+
78 | register save area | |
80 +-----------------------+ | reg_size
82 +-----------------------+ |
83 FP ->| previous frame ptr | /
84 +-----------------------+
86 | local variables | | var_size
88 +-----------------------+
90 low | room for args to | |
91 memory | other funcs called | | args_size
94 +-----------------------+
96 Note, AP is a fake hard register. It will be eliminated in favour of
97 SP or FP as appropriate.
99 Note, Some or all of the stack sections above may be omitted if they
102 /* Structure to be filled in by fr30_compute_frame_size() with register
103 save masks, and offsets for the current function. */
104 struct fr30_frame_info
106 unsigned int total_size; /* # Bytes that the entire frame takes up. */
107 unsigned int pretend_size; /* # Bytes we push and pretend caller did. */
108 unsigned int args_size; /* # Bytes that outgoing arguments take up. */
109 unsigned int reg_size; /* # Bytes needed to store regs. */
110 unsigned int var_size; /* # Bytes that variables take up. */
111 unsigned int frame_size; /* # Bytes in current frame. */
112 unsigned int gmask; /* Mask of saved registers. */
113 unsigned int save_fp; /* Nonzero if frame pointer must be saved. */
114 unsigned int save_rp; /* Nonzero if return popinter must be saved. */
115 int initialised; /* Nonzero if frame size already calculated. */
118 /* Current frame information calculated by fr30_compute_frame_size(). */
119 static struct fr30_frame_info current_frame_info;
121 /* Zero structure to initialize current_frame_info. */
122 static struct fr30_frame_info zero_frame_info;
124 #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)
143 /* Returns the number of bytes offset between FROM_REG and TO_REG
144 for the current function. As a side effect it fills in the
145 current_frame_info structure, if the data is available. */
147 fr30_compute_frame_size (from_reg, to_reg)
152 unsigned int return_value;
153 unsigned int var_size;
154 unsigned int args_size;
155 unsigned int pretend_size;
156 unsigned int reg_size;
159 var_size = WORD_ALIGN (get_frame_size ());
160 args_size = WORD_ALIGN (current_function_outgoing_args_size);
161 pretend_size = current_function_pretend_args_size;
166 /* Calculate space needed for registers. */
167 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++)
169 if (MUST_SAVE_REGISTER (regno))
171 reg_size += UNITS_PER_WORD;
176 current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER;
177 current_frame_info.save_rp = MUST_SAVE_RETURN_POINTER;
179 reg_size += (current_frame_info.save_fp + current_frame_info.save_rp)
182 /* Save computed information. */
183 current_frame_info.pretend_size = pretend_size;
184 current_frame_info.var_size = var_size;
185 current_frame_info.args_size = args_size;
186 current_frame_info.reg_size = reg_size;
187 current_frame_info.frame_size = args_size + var_size;
188 current_frame_info.total_size = args_size + var_size + reg_size + pretend_size;
189 current_frame_info.gmask = gmask;
190 current_frame_info.initialised = reload_completed;
192 /* Calculate the required distance. */
195 if (to_reg == STACK_POINTER_REGNUM)
196 return_value += args_size + var_size;
198 if (from_reg == ARG_POINTER_REGNUM)
199 return_value += reg_size;
204 /* Called after register allocation to add any instructions needed for the
205 prologue. Using a prologue insn is favored compared to putting all of the
206 instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler
207 to intermix instructions with the saves of the caller saved registers. In
208 some cases, it might be necessary to emit a barrier instruction as the last
209 insn to prevent such scheduling. */
212 fr30_expand_prologue ()
217 if (! current_frame_info.initialised)
218 fr30_compute_frame_size (0, 0);
220 /* This cases shouldn't happen. Catch it now. */
221 if (current_frame_info.total_size == 0
222 && current_frame_info.gmask)
225 /* Allocate space for register arguments if this is a variadic function. */
226 if (current_frame_info.pretend_size)
228 int regs_to_save = current_frame_info.pretend_size / UNITS_PER_WORD;
230 /* Push argument registers into the pretend arg area. */
231 for (regno = FIRST_ARG_REGNUM + FR30_NUM_ARG_REGS; regno --, regs_to_save --;)
233 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
234 RTX_FRAME_RELATED_P (insn) = 1;
238 if (current_frame_info.gmask)
240 /* Save any needed call-saved regs. */
241 for (regno = STACK_POINTER_REGNUM; regno--;)
243 if ((current_frame_info.gmask & (1 << regno)) != 0)
245 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
246 RTX_FRAME_RELATED_P (insn) = 1;
251 /* Save return address if necessary. */
252 if (current_frame_info.save_rp)
254 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode,
255 RETURN_POINTER_REGNUM)));
256 RTX_FRAME_RELATED_P (insn) = 1;
259 /* Save old frame pointer and create new one, if necessary. */
260 if (current_frame_info.save_fp)
262 if (current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
264 int enter_size = current_frame_info.frame_size + UNITS_PER_WORD;
267 insn = emit_insn (gen_enter_func (GEN_INT (enter_size)));
268 RTX_FRAME_RELATED_P (insn) = 1;
270 pattern = PATTERN (insn);
272 /* Also mark all 3 subexpressions as RTX_FRAME_RELATED_P. */
273 if (GET_CODE (pattern) == PARALLEL)
276 for (x = XVECLEN (pattern, 0); x--;)
278 rtx part = XVECEXP (pattern, 0, x);
280 /* One of the insns in the ENTER pattern updates the
281 frame pointer. If we do not actually need the frame
282 pointer in this function then this is a side effect
283 rather than a desired effect, so we do not mark that
284 insn as being related to the frame set up. Doing this
285 allows us to compile the crash66.C test file in the
287 if (! frame_pointer_needed
288 && GET_CODE (part) == SET
289 && REGNO (SET_DEST (part)) == HARD_FRAME_POINTER_REGNUM)
290 RTX_FRAME_RELATED_P (part) = 0;
292 RTX_FRAME_RELATED_P (part) = 1;
298 insn = emit_insn (gen_movsi_push (frame_pointer_rtx));
299 RTX_FRAME_RELATED_P (insn) = 1;
301 if (frame_pointer_needed)
303 insn = emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
304 RTX_FRAME_RELATED_P (insn) = 1;
309 /* Allocate the stack frame. */
310 if (current_frame_info.frame_size == 0)
311 ; /* Nothing to do. */
312 else if (current_frame_info.save_fp
313 && current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
314 ; /* Nothing to do. */
315 else if (current_frame_info.frame_size <= 512)
317 insn = emit_insn (gen_add_to_stack (GEN_INT (- current_frame_info.frame_size)));
318 RTX_FRAME_RELATED_P (insn) = 1;
322 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
323 insn = emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
324 RTX_FRAME_RELATED_P (insn) = 1;
325 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
326 RTX_FRAME_RELATED_P (insn) = 1;
329 if (profile_flag || profile_block_flag)
330 emit_insn (gen_blockage ());
333 /* Called after register allocation to add any instructions needed for the
334 epilogue. Using a epilogue insn is favored compared to putting all of the
335 instructions in the FUNCTION_EPILOGUE macro, since it allows the scheduler
336 to intermix instructions with the restores of the caller saved registers.
337 In some cases, it might be necessary to emit a barrier instruction as the
338 first insn to prevent such scheduling. */
340 fr30_expand_epilogue ()
344 /* Perform the inversion operations of the prologue. */
345 if (! current_frame_info.initialised)
348 /* Pop local variables and arguments off the stack.
349 If frame_pointer_needed is TRUE then the frame pointer register
350 has actually been used as a frame pointer, and we can recover
351 the stack pointer from it, otherwise we must unwind the stack
353 if (current_frame_info.frame_size > 0)
355 if (current_frame_info.save_fp && frame_pointer_needed)
357 emit_insn (gen_leave_func ());
358 current_frame_info.save_fp = 0;
360 else if (current_frame_info.frame_size <= 508)
361 emit_insn (gen_add_to_stack
362 (GEN_INT (current_frame_info.frame_size)));
365 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
366 emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
367 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
371 if (current_frame_info.save_fp)
372 emit_insn (gen_movsi_pop (frame_pointer_rtx));
374 /* Pop all the registers that were pushed. */
375 if (current_frame_info.save_rp)
376 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, RETURN_POINTER_REGNUM)));
378 for (regno = 0; regno < STACK_POINTER_REGNUM; regno ++)
379 if (current_frame_info.gmask & (1 << regno))
380 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno)));
382 if (current_frame_info.pretend_size)
383 emit_insn (gen_add_to_stack (GEN_INT (current_frame_info.pretend_size)));
385 /* Reset state info for each function. */
386 current_frame_info = zero_frame_info;
388 emit_jump_insn (gen_return_from_func ());
391 /* Do any needed setup for a variadic function. We must create a register
392 parameter block, and then copy any anonymous arguments, plus the last
393 named argument, from registers into memory. * copying actually done in
394 fr30_expand_prologue().
396 ARG_REGS_USED_SO_FAR has *not* been updated for the last named argument
397 which has type TYPE and mode MODE, and we rely on this fact. */
399 fr30_setup_incoming_varargs (arg_regs_used_so_far, int_mode, type, pretend_size)
400 CUMULATIVE_ARGS arg_regs_used_so_far;
402 tree type ATTRIBUTE_UNUSED;
405 enum machine_mode mode = (enum machine_mode)int_mode;
409 /* All BLKmode values are passed by reference. */
413 #if STRICT_ARGUMENT_NAMING
414 /* We must treat `__builtin_va_alist' as an anonymous arg.
415 But otherwise if STRICT_ARGUMENT_NAMING is true then the
416 last named arg must not be treated as an anonymous arg. */
417 if (! current_function_varargs)
418 arg_regs_used_so_far += fr30_num_arg_regs (int_mode, type);
421 size = FR30_NUM_ARG_REGS - arg_regs_used_so_far;
426 * pretend_size = (size * UNITS_PER_WORD);
430 /*{{{ Printing operands */
432 /* Print a memory address as an operand to reference that memory location. */
435 fr30_print_operand_address (stream, address)
439 switch (GET_CODE (address))
442 output_addr_const (stream, address);
446 fprintf (stderr, "code = %x\n", GET_CODE (address));
448 output_operand_lossage ("fr30_print_operand_address: unhandled address");
453 /* Print an operand. */
456 fr30_print_operand (file, x, code)
466 /* Output a :D if this instruction is delayed. */
467 if (dbr_sequence_length () != 0)
472 /* Compute the register name of the second register in a hi/lo
474 if (GET_CODE (x) != REG)
475 output_operand_lossage ("fr30_print_operand: unrecognised %p code");
477 fprintf (file, "r%d", REGNO (x) + 1);
481 /* Convert GCC's comparison operators into FR30 comparison codes. */
482 switch (GET_CODE (x))
484 case EQ: fprintf (file, "eq"); break;
485 case NE: fprintf (file, "ne"); break;
486 case LT: fprintf (file, "lt"); break;
487 case LE: fprintf (file, "le"); break;
488 case GT: fprintf (file, "gt"); break;
489 case GE: fprintf (file, "ge"); break;
490 case LTU: fprintf (file, "c"); break;
491 case LEU: fprintf (file, "ls"); break;
492 case GTU: fprintf (file, "hi"); break;
493 case GEU: fprintf (file, "nc"); break;
495 output_operand_lossage ("fr30_print_operand: unrecognised %b code");
501 /* Convert GCC's comparison operators into the complimentary FR30
503 switch (GET_CODE (x))
505 case EQ: fprintf (file, "ne"); break;
506 case NE: fprintf (file, "eq"); break;
507 case LT: fprintf (file, "ge"); break;
508 case LE: fprintf (file, "gt"); break;
509 case GT: fprintf (file, "le"); break;
510 case GE: fprintf (file, "lt"); break;
511 case LTU: fprintf (file, "nc"); break;
512 case LEU: fprintf (file, "hi"); break;
513 case GTU: fprintf (file, "ls"); break;
514 case GEU: fprintf (file, "c"); break;
516 output_operand_lossage ("fr30_print_operand: unrecognised %B code");
522 /* Print a signed byte value as an unsigned value. */
523 if (GET_CODE (x) != CONST_INT)
524 output_operand_lossage ("fr30_print_operand: invalid operand to %A code");
533 fprintf (file, "%d", val);
538 if (GET_CODE (x) != CONST_INT
541 output_operand_lossage ("fr30_print_operand: invalid %x code");
543 fprintf (file, "%d", INTVAL (x) - 16);
547 if (GET_CODE (x) != CONST_DOUBLE)
548 output_operand_lossage ("fr30_print_operand: invalid %F code");
553 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
554 fprintf (file, "%.8f", d);
563 fprintf (stderr, "unknown code = %x\n", code);
564 output_operand_lossage ("fr30_print_operand: unknown code");
568 switch (GET_CODE (x))
571 fputs (reg_names [REGNO (x)], file);
577 switch (GET_CODE (x0))
580 if ((unsigned) REGNO (x0) >= (sizeof (reg_names) / sizeof (reg_names[0])))
582 fprintf (file, "@%s", reg_names [REGNO (x0)]);
586 if (GET_CODE (XEXP (x0, 0)) != REG
587 || REGNO (XEXP (x0, 0)) < FRAME_POINTER_REGNUM
588 || REGNO (XEXP (x0, 0)) > STACK_POINTER_REGNUM
589 || GET_CODE (XEXP (x0, 1)) != CONST_INT)
591 fprintf (stderr, "bad INDEXed address:");
593 output_operand_lossage ("fr30_print_operand: unhandled MEM");
595 else if (REGNO (XEXP (x0, 0)) == FRAME_POINTER_REGNUM)
597 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
598 if (val < -(1 << 9) || val > ((1 << 9) - 4))
600 fprintf (stderr, "frame INDEX out of range:");
602 output_operand_lossage ("fr30_print_operand: unhandled MEM");
604 fprintf (file, "@(r14, #%d)", val);
608 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
609 if (val < 0 || val > ((1 << 6) - 4))
611 fprintf (stderr, "stack INDEX out of range:");
613 output_operand_lossage ("fr30_print_operand: unhandled MEM");
615 fprintf (file, "@(r15, #%d)", val);
624 fprintf (stderr, "bad MEM code = %x\n", GET_CODE (x0));
626 output_operand_lossage ("fr30_print_operand: unhandled MEM");
632 /* We handle SFmode constants here as output_addr_const doesn't. */
633 if (GET_MODE (x) == SFmode)
638 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
639 REAL_VALUE_TO_TARGET_SINGLE (d, l);
640 fprintf (file, "0x%08lx", l);
644 /* Fall through. Let output_addr_const deal with it. */
646 output_addr_const (file, x);
654 /*{{{ Function arguments */
656 /* Compute the number of word sized registers needed to hold a
657 function argument of mode INT_MODE and tree type TYPE. */
659 fr30_num_arg_regs (int_mode, type)
663 enum machine_mode mode = (enum machine_mode) int_mode;
666 if (MUST_PASS_IN_STACK (mode, type))
669 if (type && mode == BLKmode)
670 size = int_size_in_bytes (type);
672 size = GET_MODE_SIZE (mode);
674 return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
677 /* Implements the FUNCTION_ARG_PARTIAL_NREGS macro.
678 Returns the number of argument registers required to hold *part* of
679 a parameter of machine mode MODE and tree type TYPE (which may be
680 NULL if the type is not known). If the argument fits entirly in
681 the argument registers, or entirely on the stack, then 0 is returned.
682 CUM is the number of argument registers already used by earlier
683 parameters to the function. */
686 fr30_function_arg_partial_nregs (cum, int_mode, type, named)
692 /* Unnamed arguments, ie those that are prototyped as ...
693 are always passed on the stack.
694 Also check here to see if all the argument registers are full. */
695 if (named == 0 || cum >= FR30_NUM_ARG_REGS)
698 /* Work out how many argument registers would be needed if this
699 parameter were to be passed entirely in registers. If there
700 are sufficient argument registers available (or if no registers
701 are needed because the parameter must be passed on the stack)
702 then return zero, as this parameter does not require partial
703 register, partial stack stack space. */
704 if (cum + fr30_num_arg_regs (int_mode, type) <= FR30_NUM_ARG_REGS)
707 /* Otherwise return the number of registers that would be used. */
708 return FR30_NUM_ARG_REGS - cum;
712 fr30_pass_by_reference (valist, type)
720 type_ptr = build_pointer_type (type);
721 type_ptr_ptr = build_pointer_type (type_ptr);
723 t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (UNITS_PER_WORD, 0));
724 TREE_SIDE_EFFECTS (t) = 1;
725 t = build1 (NOP_EXPR, type_ptr_ptr, t);
726 TREE_SIDE_EFFECTS (t) = 1;
727 t = build1 (INDIRECT_REF, type_ptr, t);
729 return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
733 fr30_pass_by_value (valist, type)
737 HOST_WIDE_INT size = int_size_in_bytes (type);
742 if ((size % UNITS_PER_WORD) == 0)
744 t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (size, 0));
745 TREE_SIDE_EFFECTS (t) = 1;
747 return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
750 rsize = (size + UNITS_PER_WORD - 1) & - UNITS_PER_WORD;
752 /* Care for bigendian correction on the aligned address. */
753 t = build (PLUS_EXPR, ptr_type_node, valist, build_int_2 (rsize - size, 0));
754 addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
755 addr_rtx = copy_to_reg (addr_rtx);
758 t = build (PLUS_EXPR, va_list_type_node, valist, build_int_2 (rsize, 0));
759 t = build (MODIFY_EXPR, va_list_type_node, valist, t);
760 TREE_SIDE_EFFECTS (t) = 1;
761 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
766 /* Implement `va_arg'. */
769 fr30_va_arg (valist, type)
775 if (AGGREGATE_TYPE_P (type))
776 return fr30_pass_by_reference (valist, type);
778 size = int_size_in_bytes (type);
780 if ((size % sizeof (int)) == 0
782 return fr30_pass_by_value (valist, type);
784 return fr30_pass_by_reference (valist, type);
788 /*{{{ Operand predicates */
791 #define Mmode enum machine_mode
794 /* Returns true if OPERAND is an integer value suitable for use in
795 an ADDSP instruction. */
797 stack_add_operand (operand, mode)
799 Mmode mode ATTRIBUTE_UNUSED;
802 (GET_CODE (operand) == CONST_INT
803 && INTVAL (operand) >= -512
804 && INTVAL (operand) <= 508
805 && ((INTVAL (operand) & 3) == 0));
808 /* Returns true if OPERAND is an integer value suitable for use in
809 an ADD por ADD2 instruction, or if it is a register. */
811 add_immediate_operand (operand, mode)
813 Mmode mode ATTRIBUTE_UNUSED;
816 (GET_CODE (operand) == REG
817 || (GET_CODE (operand) == CONST_INT
818 && INTVAL (operand) >= -16
819 && INTVAL (operand) <= 15));
822 /* Returns true if OPERAND is hard register in the range 8 - 15. */
824 high_register_operand (operand, mode)
826 Mmode mode ATTRIBUTE_UNUSED;
829 (GET_CODE (operand) == REG
830 && REGNO (operand) <= 15
831 && REGNO (operand) >= 8);
834 /* Returns true if OPERAND is hard register in the range 0 - 7. */
836 low_register_operand (operand, mode)
838 Mmode mode ATTRIBUTE_UNUSED;
841 (GET_CODE (operand) == REG
842 && REGNO (operand) <= 7
843 && REGNO (operand) >= 0);
846 /* Returns true if OPERAND is suitable for use in a CALL insn. */
848 call_operand (operand, mode)
850 Mmode mode ATTRIBUTE_UNUSED;
852 return (GET_CODE (operand) == MEM
853 && (GET_CODE (XEXP (operand, 0)) == SYMBOL_REF
854 || GET_CODE (XEXP (operand, 0)) == REG));
857 /* Returns true iff all the registers in the operands array
858 are in descending or ascending order. */
860 fr30_check_multiple_regs (operands, num_operands, descending)
869 while (num_operands--)
871 if (GET_CODE (operands [num_operands]) != REG)
874 if (REGNO (operands [num_operands]) < prev_regno)
877 prev_regno = REGNO (operands [num_operands]);
882 int prev_regno = CONDITION_CODE_REGNUM;
884 while (num_operands--)
886 if (GET_CODE (operands [num_operands]) != REG)
889 if (REGNO (operands [num_operands]) > prev_regno)
892 prev_regno = REGNO (operands [num_operands]);
901 /* Local Variables: */