]>
gcc.gnu.org Git - gcc.git/blob - gcc/config/pyr/pyr.c
1 /* Subroutines for insn-output.c for Pyramid 90x, 9000, and MIServer Series.
2 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Some output-actions in pyr.md need these. */
25 #include "hard-reg-set.h"
27 #include "insn-config.h"
28 #include "conditions.h"
29 #include "insn-flags.h"
31 #include "insn-attr.h"
36 * This cannot be defined as a macro on pyramids, because Pyramid Technology's
37 * C compiler dies on (several equivalent definitions of) this macro.
38 * The only way around this cc bug was to make this a function.
39 * While it would be possible to use a macro version for gcc, it seems
40 * more reliable to have a single version of the code.
43 pyr_function_arg(cum
, mode
, type
, named
)
45 enum machine_mode mode
;
48 return (void *)(FUNCTION_ARG_HELPER (cum
, mode
,type
,named
));
51 /* Do the hard part of PARAM_SAFE_FOR_REG_P.
52 * This cannot be defined as a macro on pyramids, because Pyramid Technology's
53 * C compiler dies on (several equivalent definitions of) this macro.
54 * The only way around this cc bug was to make this a function.
57 inner_param_safe_helper (type
)
60 return (INNER_PARAM_SAFE_HELPER(type
));
64 /* Return 1 if OP is a non-indexed operand of mode MODE.
65 This is either a register reference, a memory reference,
66 or a constant. In the case of a memory reference, the address
67 is checked to make sure it isn't indexed.
69 Register and memory references must have mode MODE in order to be valid,
70 but some constants have no machine mode and are valid for any mode.
72 If MODE is VOIDmode, OP is checked for validity for whatever mode
75 The main use of this function is as a predicate in match_operand
76 expressions in the machine description.
78 It is useful to compare this with general_operand(). They should
79 be identical except for one line.
81 This function seems necessary because of the non-orthogonality of
83 For any 2-operand insn, and any combination of operand modes,
84 if indexing is valid for the isn's second operand, it is invalid
85 for the first operand to be indexed. */
87 extern int volatile_ok
;
90 nonindexed_operand (op
, mode
)
92 enum machine_mode mode
;
94 register RTX_CODE code
= GET_CODE (op
);
95 int mode_altering_drug
= 0;
100 /* Don't accept CONST_INT or anything similar
101 if the caller wants something floating. */
102 if (GET_MODE (op
) == VOIDmode
&& mode
!= VOIDmode
103 && GET_MODE_CLASS (mode
) != MODE_INT
)
107 return ((GET_MODE (op
) == VOIDmode
|| GET_MODE (op
) == mode
)
108 && LEGITIMATE_CONSTANT_P (op
));
110 /* Except for certain constants with VOIDmode, already checked for,
111 OP's mode must match MODE if MODE specifies a mode. */
113 if (GET_MODE (op
) != mode
)
116 while (code
== SUBREG
)
118 op
= SUBREG_REG (op
);
119 code
= GET_CODE (op
);
121 /* No longer needed, since (SUBREG (MEM...))
122 will load the MEM into a reload reg in the MEM's own mode. */
123 mode_altering_drug
= 1;
128 if (code
== CONST_DOUBLE
)
129 return LEGITIMATE_CONSTANT_P (op
);
132 register rtx y
= XEXP (op
, 0);
133 if (! volatile_ok
&& MEM_VOLATILE_P (op
))
135 GO_IF_NONINDEXED_ADDRESS (y
, win
);
140 if (mode_altering_drug
)
141 return ! mode_dependent_address_p (XEXP (op
, 0));
145 /* Return non-zero if the rtx OP has an immediate component. An
146 immediate component or additive term equal to zero is rejected
147 due to assembler problems. */
153 if ((CONSTANT_ADDRESS_P (op
)
155 || (GET_CODE (op
) == PLUS
156 && ((CONSTANT_ADDRESS_P (XEXP (op
, 1))
157 && XEXP (op
, 1) != const0_rtx
)
158 || (CONSTANT_ADDRESS_P (XEXP (op
, 0))
159 && XEXP (op
, 0) != const0_rtx
))))
165 /* Return zero if the rtx OP has a (scaled) index. */
171 if (GET_CODE (op
) == PLUS
172 && (GET_CODE (XEXP (op
, 0)) == MULT
173 || (GET_CODE (XEXP (op
, 1)) == MULT
)))
181 /* weird_memory_memory -- return 1 if OP1 and OP2 can be compared (or
182 exchanged with xchw) with one instruction. If the operands need to
183 be swapped, set the global variable SWAP_OPERANDS. This function
184 silently assumes that both OP0 and OP1 are valid memory references.
188 weird_memory_memory (op0
, op1
)
191 RTX_CODE code0
, code1
;
195 code0
= GET_CODE (op0
);
196 code1
= GET_CODE (op1
);
200 if (code1
== REG
|| code1
== SUBREG
)
204 if (code0
== REG
|| code0
== SUBREG
)
209 if (has_direct_base (op0
) && has_direct_base (op1
))
224 signed_comparison (x
, mode
)
226 enum machine_mode mode
;
228 return ! TRULY_UNSIGNED_COMPARE_P (GET_CODE (x
));
231 extern rtx
force_reg ();
232 rtx test_op0
, test_op1
;
233 enum machine_mode test_mode
;
235 /* Sign-extend or zero-extend constant X from FROM_MODE to TO_MODE. */
238 extend_const (x
, extop
, from_mode
, to_mode
)
241 enum machine_mode from_mode
, to_mode
;
245 if (from_mode
== to_mode
)
247 if (GET_CODE (x
) != CONST_INT
)
250 negative
= val
& (1 << (GET_MODE_BITSIZE (from_mode
) - 1));
251 if (GET_MODE_BITSIZE (from_mode
) == HOST_BITS_PER_INT
)
253 if (negative
&& extop
== SIGN_EXTEND
)
254 val
= val
| ((-1) << (GET_MODE_BITSIZE (from_mode
)));
256 val
= val
& ~((-1) << (GET_MODE_BITSIZE (from_mode
)));
257 if (GET_MODE_BITSIZE (to_mode
) == HOST_BITS_PER_INT
)
258 return gen_rtx (CONST_INT
, VOIDmode
, val
);
259 return gen_rtx (CONST_INT
, VOIDmode
,
260 val
& ~((-1) << (GET_MODE_BITSIZE (to_mode
))));
264 ensure_extended (op
, extop
, from_mode
)
267 enum machine_mode from_mode
;
269 if (GET_CODE (op
) == CONST_INT
)
270 return extend_const (op
, extop
, from_mode
, SImode
);
272 return force_reg (SImode
, gen_rtx (extop
, SImode
, op
));
275 /* Emit rtl for a branch, as well as any delayed (integer) compare insns.
276 The compare insn to perform is determined by the global variables
277 test_op0 and test_op1. */
280 extend_and_branch (extop
)
284 RTX_CODE code0
, code1
;
286 op0
= test_op0
, op1
= test_op1
;
290 code0
= GET_CODE (op0
);
292 code1
= GET_CODE (op1
);
293 test_op0
= test_op1
= 0;
297 op0
= ensure_extended (op0
, extop
, test_mode
);
298 emit_insn (gen_rtx (SET
, VOIDmode
, cc0_rtx
, op0
));
302 if (CONSTANT_P (op0
) && CONSTANT_P (op1
))
304 op0
= ensure_extended (op0
, extop
, test_mode
);
305 op1
= ensure_extended (op1
, extop
, test_mode
);
307 else if (extop
== ZERO_EXTEND
&& test_mode
== HImode
)
309 /* Pyramids have no unsigned "cmphi" instructions. We need to
310 zero extend unsigned halfwords into temporary registers. */
311 op0
= ensure_extended (op0
, extop
, test_mode
);
312 op1
= ensure_extended (op1
, extop
, test_mode
);
314 else if (CONSTANT_P (op0
))
316 op0
= ensure_extended (op0
, extop
, test_mode
);
317 op1
= ensure_extended (op1
, extop
, test_mode
);
319 else if (CONSTANT_P (op1
))
321 op1
= ensure_extended (op1
, extop
, test_mode
);
322 op0
= ensure_extended (op0
, extop
, test_mode
);
324 else if ((code0
== REG
|| code0
== SUBREG
)
325 && (code1
== REG
|| code1
== SUBREG
))
327 /* I could do this case without extension, by using the virtual
328 register address (but that would lose for global regs). */
329 op0
= ensure_extended (op0
, extop
, test_mode
);
330 op1
= ensure_extended (op1
, extop
, test_mode
);
332 else if (code0
== MEM
&& code1
== MEM
)
334 /* Load into a reg if the address combination can't be handled
336 if (! weird_memory_memory (op0
, op1
))
337 op0
= force_reg (test_mode
, op0
);
340 emit_insn (gen_rtx (SET
, VOIDmode
, cc0_rtx
,
341 gen_rtx (COMPARE
, VOIDmode
, op0
, op1
)));
345 /* Return non-zero if the two single-word moves with operands[0]
346 and operands[1] for the first single-word move, and operands[2]
347 and operands[3] for the second single-word move, is possible to
348 combine to a double word move.
350 The criterion is whether the operands are in consecutive memory cells,
354 movdi_possible (operands
)
357 int cnst_diff0
, cnst_diff1
;
358 RTX_CODE code0
= GET_CODE (operands
[0]);
359 RTX_CODE code1
= GET_CODE (operands
[1]);
361 /* Don't dare to combine (possibly overlapping) memory -> memory moves. */
362 /* It would be possible to detect the cases where we dare, by using
363 constant_diff (operands[0], operands[1])!!! */
364 if (code0
== MEM
&& code1
== MEM
)
367 cnst_diff0
= consecutive_operands (operands
[0], operands
[2]);
371 cnst_diff1
= consecutive_operands (operands
[1], operands
[3]);
375 if (cnst_diff0
& cnst_diff1
)
377 /* The source and destination operands are consecutive. */
379 /* If the first move writes into the source of the second move,
380 we cannot combine. */
382 && reg_overlap_mentioned_p (operands
[0], operands
[3]))
384 && subreg_overlap_mentioned_p (operands
[0], operands
[3])))
388 /* operands[0],[1] has higher addresses than operands[2],[3]. */
391 /* operands[0],[1] has lower addresses than operands[2],[3]. */
398 /* Like reg_overlap_mentioned_p, but accepts a subreg rtx instead
402 subreg_overlap_mentioned_p (subreg
, x
)
405 rtx reg
= SUBREG_REG (subreg
);
406 int regno
= REGNO (reg
) + SUBREG_WORD (subreg
);
407 int endregno
= regno
+ HARD_REGNO_NREGS (regno
, GET_MODE (subreg
));
408 return refers_to_regno_p (regno
, endregno
, x
, 0);
411 /* Return 1 if OP0 is a consecutive operand to OP1, 2 if OP1 is a
412 consecutive operand to OP0.
414 This function is used to determine if addresses are consecutive,
415 and therefore possible to combine to fewer instructions. */
418 consecutive_operands (op0
, op1
)
421 RTX_CODE code0
, code1
;
423 int regno_off0
, regno_off1
;
425 code0
= GET_CODE (op0
);
426 code1
= GET_CODE (op1
);
431 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0
))) <= UNITS_PER_WORD
)
433 regno_off0
= SUBREG_WORD (op0
);
434 op0
= SUBREG_REG (op0
);
441 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1
))) <= UNITS_PER_WORD
)
443 regno_off1
= SUBREG_WORD (op1
);
444 op1
= SUBREG_REG (op1
);
454 /* Cannot permit any symbolic constants, even if the consecutive
455 operand is 0, since a movl really performs sign extension. */
456 if (code1
!= CONST_INT
)
458 if ((INTVAL (op0
) == 0 && INTVAL (op1
) == 0)
459 || (INTVAL (op0
) == -1 && INTVAL (op1
) == -1))
461 if ((INTVAL (op0
) == 0 && INTVAL (op1
) > 0)
462 || (INTVAL (op0
) == -1 && INTVAL (op1
) < 0))
464 if ((INTVAL (op1
) == 0 && INTVAL (op0
) > 0)
465 || (INTVAL (op1
) == -1 && INTVAL (op0
) < 0))
470 regno_off0
= REGNO (op0
) + regno_off0
;
471 regno_off1
= REGNO (op1
) + regno_off1
;
473 cnst_diff
= regno_off0
- regno_off1
;
476 /* movl with the highest numbered parameter (local) register as
477 source or destination, doesn't wrap to the lowest numbered local
478 (temporary) register. */
480 if (regno_off0
% 16 != 0)
485 else if (cnst_diff
== -1)
487 if (regno_off1
% 16 != 0)
497 if (GET_CODE (op0
) == CONST
)
499 if (GET_CODE (op1
) == CONST
)
502 cnst_diff
= constant_diff (op0
, op1
);
507 else if (cnst_diff
== -4)
515 /* Return the constant difference of the rtx expressions OP0 and OP1,
516 or 0 if they don't have a constant difference.
518 This function is used to determine if addresses are consecutive,
519 and therefore possible to combine to fewer instructions. */
522 constant_diff (op0
, op1
)
525 RTX_CODE code0
, code1
;
528 code0
= GET_CODE (op0
);
529 code1
= GET_CODE (op1
);
535 if (GET_CODE (XEXP (op0
, 1)) == CONST_INT
536 && rtx_equal_p (op1
, XEXP (op0
, 0)))
537 return INTVAL (XEXP (op0
, 1));
539 else if (code1
== PLUS
)
541 if (GET_CODE (XEXP (op1
, 1)) == CONST_INT
542 && rtx_equal_p (op0
, XEXP (op1
, 0)))
543 return -INTVAL (XEXP (op1
, 1));
548 if (code0
== CONST_INT
)
549 return INTVAL (op0
) - INTVAL (op1
);
553 cnst_diff
= constant_diff (XEXP (op0
, 0), XEXP (op1
, 0));
555 return (rtx_equal_p (XEXP (op0
, 1), XEXP (op1
, 1)))
557 cnst_diff
= constant_diff (XEXP (op0
, 1), XEXP (op1
, 1));
559 return (rtx_equal_p (XEXP (op0
, 0), XEXP (op1
, 0)))
567 already_sign_extended (insn
, from_mode
, op
)
569 enum machine_mode from_mode
;
572 rtx xinsn
, xdest
, xsrc
;
576 insn
= PREV_INSN (insn
);
579 if (GET_CODE (insn
) == NOTE
|| GET_CODE (insn
) == JUMP_INSN
)
581 if (GET_CODE (insn
) == CALL_INSN
&& ! call_used_regs
[REGNO (op
)])
583 if (GET_CODE (insn
) != INSN
)
585 xinsn
= PATTERN (insn
);
587 if (GET_CODE (xinsn
) != SET
)
590 xdest
= SET_DEST (xinsn
);
591 xsrc
= SET_SRC (xinsn
);
593 if (GET_CODE (xdest
) == SUBREG
)
596 if ( ! REG_P (xdest
))
599 if (REGNO (op
) == REGNO (xdest
)
600 && ((GET_CODE (xsrc
) == SIGN_EXTEND
601 && GET_MODE (XEXP (xsrc
, 0)) == from_mode
)
602 || (GET_CODE (xsrc
) == MEM
603 && GET_MODE (xsrc
) == from_mode
)))
606 /* The register is modified by another operation. */
607 if (reg_overlap_mentioned_p (xdest
, op
))
613 output_move_double (operands
)
616 if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
618 if (GET_MODE_CLASS (GET_MODE (operands
[1])) == MODE_INT
)
620 /* In an integer, the low-order word is in CONST_DOUBLE_LOW. */
621 rtx const_op
= operands
[1];
622 if ((CONST_DOUBLE_HIGH (const_op
) == 0
623 && CONST_DOUBLE_LOW (const_op
) >= 0)
624 || (CONST_DOUBLE_HIGH (const_op
) == -1
625 && CONST_DOUBLE_LOW (const_op
) < 0))
627 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
,
628 CONST_DOUBLE_LOW (const_op
));
631 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
,
632 CONST_DOUBLE_HIGH (const_op
));
633 output_asm_insn ("movw %1,%0", operands
);
634 operands
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 1);
635 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
,
636 CONST_DOUBLE_LOW (const_op
));
641 /* In a real, the low-address word is in CONST_DOUBLE_LOW. */
642 rtx const_op
= operands
[1];
643 if ((CONST_DOUBLE_LOW (const_op
) == 0
644 && CONST_DOUBLE_HIGH (const_op
) >= 0)
645 || (CONST_DOUBLE_LOW (const_op
) == -1
646 && CONST_DOUBLE_HIGH (const_op
) < 0))
648 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
,
649 CONST_DOUBLE_HIGH (const_op
));
652 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
,
653 CONST_DOUBLE_LOW (const_op
));
654 output_asm_insn ("movw %1,%0", operands
);
655 operands
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 1);
656 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
,
657 CONST_DOUBLE_HIGH (const_op
));
665 /* Output a shift insns, after having reduced integer arguments to
666 avoid as warnings. */
669 output_shift (pattern
, op2
, mod
)
674 if (GET_CODE (op2
) == CONST_INT
)
676 int cnt
= INTVAL (op2
) % mod
;
679 cc_status
= cc_prev_status
;
682 op2
= gen_rtx (CONST_INT
, VOIDmode
, cnt
);
687 /* Return non-zero if the code of this rtx pattern is a relop. */
692 enum machine_mode mode
;
694 switch (GET_CODE (op
))
712 notice_update_cc (EXP
, INSN
)
715 switch (GET_CODE (EXP
))
718 switch (GET_CODE (SET_DEST (EXP
)))
723 cc_status
.value1
= 0;
724 cc_status
.value2
= SET_SRC (EXP
);
731 switch (GET_CODE (SET_SRC (EXP
)))
736 if (GET_MODE (SET_SRC (EXP
)) == QImode
737 || GET_MODE (SET_SRC (EXP
)) == HImode
)
740 cc_status
.flags
= CC_NO_OVERFLOW
;
741 cc_status
.value1
= SET_DEST (EXP
);
742 cc_status
.value2
= SET_SRC (EXP
);
745 /* else: Fall through. */
753 && reg_overlap_mentioned_p (SET_DEST (EXP
),
755 cc_status
.value1
= 0;
757 && reg_overlap_mentioned_p (SET_DEST (EXP
),
759 cc_status
.value2
= 0;
764 cc_status
.mdep
= CC_VALID_FOR_UNSIGNED
;
765 cc_status
.flags
= CC_NO_OVERFLOW
;
766 cc_status
.value1
= SET_DEST (EXP
);
767 cc_status
.value2
= SET_SRC (EXP
);
771 cc_status
.flags
= CC_NO_OVERFLOW
;
772 cc_status
.value1
= SET_DEST (EXP
);
773 cc_status
.value2
= SET_SRC (EXP
);
779 switch (GET_CODE (SET_SRC (EXP
)))
782 if (GET_MODE (SET_SRC (EXP
)) == QImode
783 || GET_MODE (SET_SRC (EXP
)) == HImode
)
785 cc_status
.flags
= CC_NO_OVERFLOW
;
786 cc_status
.value1
= SET_DEST (EXP
);
787 cc_status
.value2
= SET_SRC (EXP
);
791 /* else: Fall through. */
798 /* Need to forget cc_status about memory positions each
799 time a memory store is made, even if the memory store
800 insns in question doesn't modify the condition codes. */
801 if (cc_status
.value1
&&
802 GET_CODE (cc_status
.value1
) == MEM
)
803 cc_status
.value1
= 0;
804 if (cc_status
.value2
&&
805 GET_CODE (cc_status
.value2
) == MEM
)
806 cc_status
.value2
= 0;
813 cc_status
.flags
= CC_NO_OVERFLOW
;
814 cc_status
.value1
= SET_DEST (EXP
);
815 cc_status
.value2
= SET_SRC (EXP
);
833 /* Do calls preserve the condition codes? (At least forget
834 cc_status expressions if they refer to registers
835 not preserved across calls. Also forget expressions
836 about memory contents.) */
838 && (refers_to_regno_p (PYR_TREG (0), PYR_TREG (15),
840 || GET_CODE (cc_status
.value1
) == MEM
))
841 cc_status
.value1
= 0;
843 && (refers_to_regno_p (PYR_TREG (0), PYR_TREG (15),
845 || GET_CODE (cc_status
.value2
) == MEM
))
846 cc_status
.value2
= 0;
855 forget_cc_if_dependent (op
)
858 cc_status
= cc_prev_status
;
859 if (cc_status
.value1
&& reg_overlap_mentioned_p (op
, cc_status
.value1
))
860 cc_status
.value1
= 0;
861 if (cc_status
.value2
&& reg_overlap_mentioned_p (op
, cc_status
.value2
))
862 cc_status
.value2
= 0;
This page took 0.076059 seconds and 5 git commands to generate.