+2004-08-14 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips-protos.h (mips_symbolic_constant_p)
+ (mips_atomic_symbolic_constant_p, mips_stack_address_p)
+ (mips_small_data_pattern_p): Declare.
+ * config/mips/mips.h (CONST_GP_P): Moved from mips.c.
+ (PREDICATE_CODES, SPECIAL_MODE_PREDICATES): Delete.
+ * config/mips/mips.c (mips_symbolic_constant_p): Make global.
+ (mips_atomic_symbolic_constant_p, mips_stack_address_p): New functions.
+ (uns_arith_operand, const_arith_operand, arith_operand, sle_operand)
+ (sleu_operand, small_int, reg_or_0_operand, const_float_1_operand)
+ (reg_or_const_float_1_operand, hilo_operand, extend_operator)
+ (macc_msac_operand, equality_op, cmp_op, trap_cmp_op)
+ (pc_or_label_operand, call_insn_operand, move_operand)
+ (consttable_operand, symbolic_operand, general_symbolic_operand)
+ (global_got_operand, local_got_operand, stack_operand)
+ (fp_register_operand, lo_operand, fcc_register_operand): Delete.
+ (mips_small_data_pattern_1): Renamed from small_data_pattern_1.
+ (mips_small_data_pattern_p): Replace previous small_data_pattern
+ predicate. Turn into a bool () (rtx) function.
+ * config/mips/predicates.md: New file.
+ * config/mips/mips.md: Include it. Use the target-independent
+ comparison_operator instead of cmp_op. Rename trap_cmp_op to
+ trap_comparison_operator and equality_op to equality_operator.
+ Replace uses of small_int with the equivalent const_arith_operand.
+ Rename reg_or_const_float_1_operand to reg_or_1_operand. Rename
+ const_float_1_operand to const_1_operand. Rename fcc_register_operand
+ to fcc_reload_operand.
+ * config/mips/sb1.md: Rename fp_register_operand to fpr_operand.
+
2004-08-14 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
PR libstdc++/17005 partial fix.
};
#define NUM_SYMBOL_TYPES (SYMBOL_64_LOW + 1)
+extern bool mips_symbolic_constant_p (rtx, enum mips_symbol_type *);
+extern bool mips_atomic_symbolic_constant_p (rtx);
extern int mips_regno_mode_ok_for_base_p (int, enum machine_mode, int);
+extern bool mips_stack_address_p (rtx, enum machine_mode);
extern int mips_address_insns (rtx, enum machine_mode);
extern int mips_const_insns (rtx);
extern int mips_fetch_insns (rtx);
extern void mips_declare_object_name (FILE *, const char *, tree);
extern void mips_finish_declare_object (FILE *, tree, int, int);
+extern bool mips_small_data_pattern_p (rtx);
extern rtx mips_rewrite_small_data (rtx);
extern HOST_WIDE_INT compute_frame_size (HOST_WIDE_INT);
extern HOST_WIDE_INT mips_initial_elimination_offset (int, int);
#define UNSPEC_ADDRESS_TYPE(X) \
((enum mips_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST))
-/* True if X is (const (unspec [(const_int 0)] UNSPEC_GP)). This is used
- to initialize the mips16 gp pseudo register. */
-#define CONST_GP_P(X) \
- (GET_CODE (X) == CONST \
- && GET_CODE (XEXP (X, 0)) == UNSPEC \
- && XINT (XEXP (X, 0), 1) == UNSPEC_GP)
-
/* The maximum distance between the top of the stack frame and the
value $sp has when we save & restore registers.
static enum mips_symbol_type mips_classify_symbol (rtx);
static void mips_split_const (rtx, rtx *, HOST_WIDE_INT *);
static bool mips_offset_within_object_p (rtx, HOST_WIDE_INT);
-static bool mips_symbolic_constant_p (rtx, enum mips_symbol_type *);
static bool mips_valid_base_register_p (rtx, enum machine_mode, int);
static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode);
static bool mips_classify_address (struct mips_address_info *, rtx,
static void mips_file_start (void);
static void mips_file_end (void);
static bool mips_rewrite_small_data_p (rtx);
-static int small_data_pattern_1 (rtx *, void *);
+static int mips_small_data_pattern_1 (rtx *, void *);
static int mips_rewrite_small_data_1 (rtx *, void *);
static bool mips_function_has_gp_insn (void);
static unsigned int mips_global_pointer (void);
the same way as a bare symbol. If it is, store the type of the
symbol in *SYMBOL_TYPE. */
-static bool
+bool
mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
{
HOST_WIDE_INT offset;
}
+/* Return true if X is a symbolic constant whose value is not split
+ into separate relocations. */
+
+bool
+mips_atomic_symbolic_constant_p (rtx x)
+{
+ enum mips_symbol_type type;
+ return mips_symbolic_constant_p (x, &type) && !mips_split_p[type];
+}
+
+
/* This function is used to implement REG_MODE_OK_FOR_BASE_P. */
int
abort ();
}
+/* Return true if X is a legitimate $sp-based address for mode MDOE. */
+
+bool
+mips_stack_address_p (rtx x, enum machine_mode mode)
+{
+ struct mips_address_info addr;
+
+ return (mips_classify_address (&addr, x, mode, false)
+ && addr.type == ADDRESS_REG
+ && addr.reg == stack_pointer_rtx);
+}
/* Return true if a value at OFFSET bytes from BASE can be accessed
using an unextended mips16 instruction. MODE is the mode of the
count++;
return count;
}
-
-
-/* Return truth value of whether OP can be used as an operands
- where a register or 16 bit unsigned integer is needed. */
-
-int
-uns_arith_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (op))
- return 1;
-
- return register_operand (op, mode);
-}
-
-
-/* True if OP can be treated as a signed 16-bit constant. */
-
-int
-const_arith_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return GET_CODE (op) == CONST_INT && SMALL_INT (op);
-}
-
-
-/* Return true if OP is a register operand or a signed 16-bit constant. */
-
-int
-arith_operand (rtx op, enum machine_mode mode)
-{
- return const_arith_operand (op, mode) || register_operand (op, mode);
-}
-
-/* Return true if OP can be used as the second argument to an LE operation. */
-
-int
-sle_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return GET_CODE (op) == CONST_INT && SMALL_OPERAND (INTVAL (op) + 1);
-}
-
-/* Likewise LEU. */
-
-int
-sleu_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && INTVAL (op) + 1 != 0
- && SMALL_OPERAND (INTVAL (op) + 1));
-}
-
-/* Return truth value of whether OP is an integer which fits in 16 bits. */
-
-int
-small_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
-}
-
-/* Return truth value of whether OP is a register or the constant 0.
- Do not accept 0 in mips16 mode since $0 is not one of the core 8
- registers. */
-
-int
-reg_or_0_operand (rtx op, enum machine_mode mode)
-{
- switch (GET_CODE (op))
- {
- case CONST_INT:
- if (TARGET_MIPS16)
- return 0;
- return INTVAL (op) == 0;
-
- case CONST_DOUBLE:
- if (TARGET_MIPS16)
- return 0;
- return op == CONST0_RTX (mode);
-
- default:
- return register_operand (op, mode);
- }
-}
-
-/* Accept a register or the floating point constant 1 in the
- appropriate mode. */
-
-int
-reg_or_const_float_1_operand (rtx op, enum machine_mode mode)
-{
- return const_float_1_operand (op, mode) || register_operand (op, mode);
-}
-
-/* Accept the floating point constant 1 in the appropriate mode. */
-
-int
-const_float_1_operand (rtx op, enum machine_mode mode)
-{
- REAL_VALUE_TYPE d;
-
- if (GET_CODE (op) != CONST_DOUBLE
- || mode != GET_MODE (op)
- || (mode != DFmode && mode != SFmode))
- return 0;
-
- REAL_VALUE_FROM_CONST_DOUBLE (d, op);
-
- return REAL_VALUES_EQUAL (d, dconst1);
-}
-
-/* Return true if OP is either the HI or LO register. */
-
-int
-hilo_operand (rtx op, enum machine_mode mode)
-{
- return ((mode == VOIDmode || mode == GET_MODE (op))
- && REG_P (op) && MD_REG_P (REGNO (op)));
-}
-
-/* Return true if OP is an extension operator. */
-
-int
-extend_operator (rtx op, enum machine_mode mode)
-{
- return ((mode == VOIDmode || mode == GET_MODE (op))
- && (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND));
-}
-
-/* Return true if X is the right hand side of a "macc" or "msac" instruction.
- This predicate is intended for use in peephole optimizations. */
-
-int
-macc_msac_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (ISA_HAS_MACC && GET_CODE (x) == PLUS && REG_P (XEXP (x, 1)))
- x = XEXP (x, 0);
- else if (ISA_HAS_MSAC && GET_CODE (x) == MINUS && REG_P (XEXP (x, 0)))
- x = XEXP (x, 1);
- else
- return false;
-
- return GET_CODE (x) == MULT && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1));
-}
-
-/* Return nonzero if the code of this rtx pattern is EQ or NE. */
-
-int
-equality_op (rtx op, enum machine_mode mode)
-{
- if (mode != GET_MODE (op))
- return 0;
-
- return GET_CODE (op) == EQ || GET_CODE (op) == NE;
-}
-
-/* Return nonzero if the code is a relational operations (EQ, LE, etc.) */
-
-int
-cmp_op (rtx op, enum machine_mode mode)
-{
- if (mode != GET_MODE (op))
- return 0;
-
- return COMPARISON_P (op);
-}
-
-/* Return nonzero if the code is a relational operation suitable for a
- conditional trap instruction (only EQ, NE, LT, LTU, GE, GEU).
- We need this in the insn that expands `trap_if' in order to prevent
- combine from erroneously altering the condition. */
-
-int
-trap_cmp_op (rtx op, enum machine_mode mode)
-{
- if (mode != GET_MODE (op))
- return 0;
-
- switch (GET_CODE (op))
- {
- case EQ:
- case NE:
- case LT:
- case LTU:
- case GE:
- case GEU:
- return 1;
-
- default:
- return 0;
- }
-}
-
-/* Return nonzero if the operand is either the PC or a label_ref. */
-
-int
-pc_or_label_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (op == pc_rtx)
- return 1;
-
- if (GET_CODE (op) == LABEL_REF)
- return 1;
-
- return 0;
-}
-
-/* Test for a valid call address. */
-
-int
-call_insn_operand (rtx op, enum machine_mode mode)
-{
- enum mips_symbol_type symbol_type;
-
- if (mips_symbolic_constant_p (op, &symbol_type))
- switch (symbol_type)
- {
- case SYMBOL_GENERAL:
- /* If -mlong-calls, force all calls to use register addressing. */
- return !TARGET_LONG_CALLS;
-
- case SYMBOL_GOT_GLOBAL:
- /* Without explicit relocs, there is no special syntax for
- loading the address of a call destination into a register.
- Using "la $25,foo; jal $25" would prevent the lazy binding
- of "foo", so keep the address of global symbols with the
- jal macro. */
- return !TARGET_EXPLICIT_RELOCS;
-
- default:
- return false;
- }
- return register_operand (op, mode);
-}
-
-
-/* Return nonzero if OP is valid as a source operand for a move
- instruction. */
-
-int
-move_operand (rtx op, enum machine_mode mode)
-{
- enum mips_symbol_type symbol_type;
-
- if (!general_operand (op, mode))
- return false;
-
- switch (GET_CODE (op))
- {
- case CONST_INT:
- /* When generating mips16 code, LEGITIMATE_CONSTANT_P rejects
- CONST_INTs that can't be loaded using simple insns. */
- if (TARGET_MIPS16)
- return true;
-
- /* When generating 32-bit code, allow DImode move_operands to
- match arbitrary constants. We split them after reload. */
- if (!TARGET_64BIT && mode == DImode)
- return true;
-
- /* Otherwise check whether the constant can be loaded in a single
- instruction. */
- return LUI_INT (op) || SMALL_INT (op) || SMALL_INT_UNSIGNED (op);
-
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- if (CONST_GP_P (op))
- return true;
-
- return (mips_symbolic_constant_p (op, &symbol_type)
- && !mips_split_p[symbol_type]);
-
- default:
- return true;
- }
-}
-
-
-/* Accept any operand that can appear in a mips16 constant table
- instruction. We can't use any of the standard operand functions
- because for these instructions we accept values that are not
- accepted by LEGITIMATE_CONSTANT, such as arbitrary SYMBOL_REFs. */
-
-int
-consttable_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return CONSTANT_P (op);
-}
-
-/* Return 1 if OP is a symbolic operand, i.e. a symbol_ref or a label_ref,
- possibly with an offset. */
-
-int
-symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum mips_symbol_type symbol_type;
-
- return mips_symbolic_constant_p (op, &symbol_type);
-}
-
-
-/* Return true if OP is a symbolic constant of type SYMBOL_GENERAL. */
-
-int
-general_symbolic_operand (rtx op, enum machine_mode mode)
-{
- enum mips_symbol_type symbol_type;
-
- return ((mode == VOIDmode || mode == GET_MODE (op))
- && mips_symbolic_constant_p (op, &symbol_type)
- && symbol_type == SYMBOL_GENERAL);
-}
-
-
-/* Return true if we're generating PIC and OP is a global symbol. */
-
-int
-global_got_operand (rtx op, enum machine_mode mode)
-{
- enum mips_symbol_type symbol_type;
-
- return ((mode == VOIDmode || mode == GET_MODE (op))
- && mips_symbolic_constant_p (op, &symbol_type)
- && symbol_type == SYMBOL_GOT_GLOBAL);
-}
-
-
-/* Likewise for local symbols. */
-
-int
-local_got_operand (rtx op, enum machine_mode mode)
-{
- enum mips_symbol_type symbol_type;
-
- return ((mode == VOIDmode || mode == GET_MODE (op))
- && mips_symbolic_constant_p (op, &symbol_type)
- && symbol_type == SYMBOL_GOT_LOCAL);
-}
-
-
-/* Return true if OP is a memory reference that uses the stack pointer
- as a base register. */
-
-int
-stack_operand (rtx op, enum machine_mode mode)
-{
- struct mips_address_info addr;
-
- return ((mode == VOIDmode || mode == GET_MODE (op))
- && GET_CODE (op) == MEM
- && mips_classify_address (&addr, XEXP (op, 0), GET_MODE (op), false)
- && addr.type == ADDRESS_REG
- && addr.reg == stack_pointer_rtx);
-}
-
-/* Helper function for DFA schedulers. Return true if OP is a floating
- point register. */
-
-int
-fp_register_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return REG_P (op) && FP_REG_P (REGNO (op));
-}
-
-/* Helper function for DFA schedulers. Return true if OP is a LO reg. */
-
-int
-lo_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return REG_P (op) && REGNO (op) == LO_REGNUM;
-}
\f
-
/* This function is used to implement GO_IF_LEGITIMATE_ADDRESS. It
returns a nonzero value if X is a legitimate address for a memory
operand of the indicated MODE. STRICT is nonzero if this function
return TARGET_SIBCALLS;
}
\f
-/* Return true if operand OP is a condition code register.
- Only for use during or after reload. */
-
-int
-fcc_register_operand (rtx op, enum machine_mode mode)
-{
- return ((mode == VOIDmode || mode == GET_MODE (op))
- && (reload_in_progress || reload_completed)
- && (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
- && ST_REG_P (true_regnum (op)));
-}
-
/* Emit code to move general operand SRC into condition-code
register DEST. SCRATCH is a scratch TFmode float register.
The sequence is:
}
-/* A for_each_rtx callback for small_data_pattern. */
+/* A for_each_rtx callback for mips_small_data_pattern_p. */
static int
-small_data_pattern_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
+mips_small_data_pattern_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
{
if (GET_CODE (*loc) == LO_SUM)
return -1;
/* Return true if OP refers to small data symbols directly, not through
a LO_SUM. */
-int
-small_data_pattern (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+bool
+mips_small_data_pattern_p (rtx op)
{
- return (GET_CODE (op) != SEQUENCE
- && for_each_rtx (&op, small_data_pattern_1, 0));
+ return for_each_rtx (&op, mips_small_data_pattern_1, 0);
}
\f
/* A for_each_rtx callback, used by mips_rewrite_small_data. */
#define FP_REG_RTX_P(X) (GET_CODE (X) == REG && FP_REG_P (REGNO (X)))
+/* True if X is (const (unspec [(const_int 0)] UNSPEC_GP)). This is used
+ to initialize the mips16 gp pseudo register. */
+#define CONST_GP_P(X) \
+ (GET_CODE (X) == CONST \
+ && GET_CODE (XEXP (X, 0)) == UNSPEC \
+ && XINT (XEXP (X, 0), 1) == UNSPEC_GP)
+
/* Return coprocessor number from register number. */
#define COPNUM_AS_CHAR_FROM_REGNUM(REGNO) \
be updated with the correct length of the insn. */
#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
((LENGTH) = mips_adjust_insn_length ((INSN), (LENGTH)))
-
-\f
-/* Optionally define this if you have added predicates to
- `MACHINE.c'. This macro is called within an initializer of an
- array of structures. The first field in the structure is the
- name of a predicate and the second field is an array of rtl
- codes. For each predicate, list all rtl codes that can be in
- expressions matched by the predicate. The list should have a
- trailing comma. Here is an example of two entries in the list
- for a typical RISC machine:
-
- #define PREDICATE_CODES \
- {"gen_reg_rtx_operand", {SUBREG, REG}}, \
- {"reg_or_short_cint_operand", {SUBREG, REG, CONST_INT}},
-
- Defining this macro does not affect the generated code (however,
- incorrect definitions that omit an rtl code that may be matched
- by the predicate can cause the compiler to malfunction).
- Instead, it allows the table built by `genrecog' to be more
- compact and efficient, thus speeding up the compiler. The most
- important predicates to include in the list specified by this
- macro are thoses used in the most insn patterns. */
-
-#define PREDICATE_CODES \
- {"uns_arith_operand", { REG, CONST_INT, SUBREG }}, \
- {"symbolic_operand", { CONST, SYMBOL_REF, LABEL_REF }}, \
- {"general_symbolic_operand", { CONST, SYMBOL_REF, LABEL_REF }}, \
- {"global_got_operand", { CONST, SYMBOL_REF, LABEL_REF }}, \
- {"local_got_operand", { CONST, SYMBOL_REF, LABEL_REF }}, \
- {"const_arith_operand", { CONST_INT }}, \
- {"small_data_pattern", { SET, PARALLEL, UNSPEC, \
- UNSPEC_VOLATILE }}, \
- {"arith_operand", { REG, CONST_INT, CONST, SUBREG }}, \
- {"reg_or_0_operand", { REG, CONST_INT, CONST_DOUBLE, SUBREG }}, \
- {"sle_operand", { CONST_INT }}, \
- {"sleu_operand", { CONST_INT }}, \
- {"small_int", { CONST_INT }}, \
- {"const_float_1_operand", { CONST_DOUBLE }}, \
- {"reg_or_const_float_1_operand", { CONST_DOUBLE, REG}}, \
- {"equality_op", { EQ, NE }}, \
- {"cmp_op", { EQ, NE, GT, GE, GTU, GEU, LT, LE, \
- LTU, LEU }}, \
- {"trap_cmp_op", { EQ, NE, GE, GEU, LT, LTU }}, \
- {"pc_or_label_operand", { PC, LABEL_REF }}, \
- {"call_insn_operand", { CONST, SYMBOL_REF, LABEL_REF, REG }}, \
- {"move_operand", { CONST_INT, CONST_DOUBLE, CONST, \
- SYMBOL_REF, LABEL_REF, SUBREG, \
- REG, MEM}}, \
- {"stack_operand", { MEM }}, \
- {"consttable_operand", { LABEL_REF, SYMBOL_REF, CONST_INT, \
- CONST_DOUBLE, CONST }}, \
- {"fcc_register_operand", { REG, SUBREG }}, \
- {"hilo_operand", { REG }}, \
- {"macc_msac_operand", { PLUS, MINUS }}, \
- {"extend_operator", { ZERO_EXTEND, SIGN_EXTEND }},
-
-/* A list of predicates that do special things with modes, and so
- should not elicit warnings for VOIDmode match_operand. */
-
-#define SPECIAL_MODE_PREDICATES \
- "pc_or_label_operand",
\f
/* Control the assembler format that we output. */
(UNSPEC_ADDRESS_FIRST 100)
(FAKE_CALL_REGNO 79)])
+
+(include "predicates.md")
\f
;; ....................
;;
[(set_attr "type" "trap")])
(define_expand "conditional_trap"
- [(trap_if (match_operator 0 "cmp_op"
+ [(trap_if (match_operator 0 "comparison_operator"
[(match_dup 2) (match_dup 3)])
(match_operand 1 "const_int_operand"))]
"ISA_HAS_COND_TRAP"
})
(define_insn ""
- [(trap_if (match_operator 0 "trap_cmp_op"
+ [(trap_if (match_operator 0 "trap_comparison_operator"
[(match_operand:SI 1 "reg_or_0_operand" "dJ")
(match_operand:SI 2 "arith_operand" "dI")])
(const_int 0))]
[(set_attr "type" "trap")])
(define_insn ""
- [(trap_if (match_operator 0 "trap_cmp_op"
+ [(trap_if (match_operator 0 "trap_comparison_operator"
[(match_operand:DI 1 "reg_or_0_operand" "dJ")
(match_operand:DI 2 "arith_operand" "dI")])
(const_int 0))]
(define_insn ""
[(set (reg:SI 29)
(plus:SI (reg:SI 29)
- (match_operand:SI 0 "small_int" "I")))]
+ (match_operand:SI 0 "const_arith_operand" "")))]
"TARGET_MIPS16"
"addu\t%$,%$,%0"
[(set_attr "type" "arith")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
(plus:SI (reg:SI 29)
- (match_operand:SI 1 "small_int" "I")))]
+ (match_operand:SI 1 "const_arith_operand" "")))]
"TARGET_MIPS16"
"addu\t%0,%$,%1"
[(set_attr "type" "arith")
(define_insn ""
[(set (reg:DI 29)
(plus:DI (reg:DI 29)
- (match_operand:DI 0 "small_int" "I")))]
+ (match_operand:DI 0 "const_arith_operand" "")))]
"TARGET_MIPS16 && TARGET_64BIT"
"daddu\t%$,%$,%0"
[(set_attr "type" "arith")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(plus:DI (reg:DI 29)
- (match_operand:DI 1 "small_int" "I")))]
+ (match_operand:DI 1 "const_arith_operand" "")))]
"TARGET_MIPS16 && TARGET_64BIT"
"daddu\t%0,%$,%1"
[(set_attr "type" "arith")
(define_expand "divdf3"
[(set (match_operand:DF 0 "register_operand")
- (div:DF (match_operand:DF 1 "reg_or_const_float_1_operand")
+ (div:DF (match_operand:DF 1 "reg_or_1_operand")
(match_operand:DF 2 "register_operand")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
{
- if (const_float_1_operand (operands[1], DFmode))
+ if (const_1_operand (operands[1], DFmode))
if (!(ISA_HAS_FP4 && flag_unsafe_math_optimizations))
operands[1] = force_reg (DFmode, operands[1]);
})
;; precision is OK (i.e., flag_unsafe_math_optimizations is set).
(define_expand "divsf3"
[(set (match_operand:SF 0 "register_operand")
- (div:SF (match_operand:SF 1 "reg_or_const_float_1_operand")
+ (div:SF (match_operand:SF 1 "reg_or_1_operand")
(match_operand:SF 2 "register_operand")))]
"TARGET_HARD_FLOAT && (!TARGET_FIX_SB1 || flag_unsafe_math_optimizations)"
{
- if (const_float_1_operand (operands[1], SFmode))
+ if (const_1_operand (operands[1], SFmode))
if (!(ISA_HAS_FP4 && flag_unsafe_math_optimizations))
operands[1] = force_reg (SFmode, operands[1]);
})
;; "divdf3" comment for details).
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f")
- (div:DF (match_operand:DF 1 "const_float_1_operand" "")
+ (div:DF (match_operand:DF 1 "const_1_operand" "")
(match_operand:DF 2 "register_operand" "f")))]
"ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_unsafe_math_optimizations"
{
;; "divdf3" comment for details).
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=f")
- (div:SF (match_operand:SF 1 "const_float_1_operand" "")
+ (div:SF (match_operand:SF 1 "const_1_operand" "")
(match_operand:SF 2 "register_operand" "f")))]
"ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_unsafe_math_optimizations"
{
;; "divdf3" comment for details).
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f")
- (div:DF (match_operand:DF 1 "const_float_1_operand" "")
+ (div:DF (match_operand:DF 1 "const_1_operand" "")
(sqrt:DF (match_operand:DF 2 "register_operand" "f"))))]
"ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_unsafe_math_optimizations"
{
;; "divdf3" comment for details).
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=f")
- (div:SF (match_operand:SF 1 "const_float_1_operand" "")
+ (div:SF (match_operand:SF 1 "const_1_operand" "")
(sqrt:SF (match_operand:SF 2 "register_operand" "f"))))]
"ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_unsafe_math_optimizations"
{
;; "divdf3" comment for details).
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f")
- (sqrt:DF (div:DF (match_operand:DF 1 "const_float_1_operand" "")
+ (sqrt:DF (div:DF (match_operand:DF 1 "const_1_operand" "")
(match_operand:DF 2 "register_operand" "f"))))]
"ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_unsafe_math_optimizations"
{
;; "divdf3" comment for details).
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=f")
- (sqrt:SF (div:SF (match_operand:SF 1 "const_float_1_operand" "")
+ (sqrt:SF (div:SF (match_operand:SF 1 "const_1_operand" "")
(match_operand:SF 2 "register_operand" "f"))))]
"ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_unsafe_math_optimizations"
{
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
- (truncate:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "small_int" "I"))))]
+ (truncate:SI
+ (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "const_arith_operand" ""))))]
"TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) >= 32"
"dsra\t%0,%1,%2"
[(set_attr "type" "shift")
;; into a GPR takes a single movcc, moving elsewhere takes
;; two. We can leave these cases to the generic reload code.
(define_expand "reload_incc"
- [(set (match_operand:CC 0 "fcc_register_operand" "=z")
+ [(set (match_operand:CC 0 "fcc_reload_operand" "=z")
(match_operand:CC 1 "general_operand" ""))
(clobber (match_operand:TF 2 "register_operand" "=&f"))]
"ISA_HAS_8CC && TARGET_HARD_FLOAT"
})
(define_expand "reload_outcc"
- [(set (match_operand:CC 0 "fcc_register_operand" "=z")
+ [(set (match_operand:CC 0 "fcc_reload_operand" "=z")
(match_operand:CC 1 "register_operand" ""))
(clobber (match_operand:TF 2 "register_operand" "=&f"))]
"ISA_HAS_8CC && TARGET_HARD_FLOAT"
(define_insn "branch_fp"
[(set (pc)
(if_then_else
- (match_operator:CC 0 "cmp_op"
+ (match_operator:CC 0 "comparison_operator"
[(match_operand:CC 2 "register_operand" "z")
(const_int 0)])
(label_ref (match_operand 1 "" ""))
(define_insn "branch_fp_inverted"
[(set (pc)
(if_then_else
- (match_operator:CC 0 "cmp_op"
+ (match_operator:CC 0 "comparison_operator"
[(match_operand:CC 2 "register_operand" "z")
(const_int 0)])
(pc)
(define_insn "branch_zero"
[(set (pc)
(if_then_else
- (match_operator:SI 0 "cmp_op"
+ (match_operator:SI 0 "comparison_operator"
[(match_operand:SI 2 "register_operand" "d")
(const_int 0)])
(label_ref (match_operand 1 "" ""))
(define_insn "branch_zero_inverted"
[(set (pc)
(if_then_else
- (match_operator:SI 0 "cmp_op"
+ (match_operator:SI 0 "comparison_operator"
[(match_operand:SI 2 "register_operand" "d")
(const_int 0)])
(pc)
(define_insn "branch_zero_di"
[(set (pc)
(if_then_else
- (match_operator:DI 0 "cmp_op"
+ (match_operator:DI 0 "comparison_operator"
[(match_operand:DI 2 "register_operand" "d")
(const_int 0)])
(label_ref (match_operand 1 "" ""))
(define_insn "branch_zero_di_inverted"
[(set (pc)
(if_then_else
- (match_operator:DI 0 "cmp_op"
+ (match_operator:DI 0 "comparison_operator"
[(match_operand:DI 2 "register_operand" "d")
(const_int 0)])
(pc)
(define_insn "branch_equality"
[(set (pc)
(if_then_else
- (match_operator:SI 0 "equality_op"
+ (match_operator:SI 0 "equality_operator"
[(match_operand:SI 2 "register_operand" "d")
(match_operand:SI 3 "register_operand" "d")])
(label_ref (match_operand 1 "" ""))
(define_insn "branch_equality_di"
[(set (pc)
(if_then_else
- (match_operator:DI 0 "equality_op"
+ (match_operator:DI 0 "equality_operator"
[(match_operand:DI 2 "register_operand" "d")
(match_operand:DI 3 "register_operand" "d")])
(label_ref (match_operand 1 "" ""))
(define_insn "branch_equality_inverted"
[(set (pc)
(if_then_else
- (match_operator:SI 0 "equality_op"
+ (match_operator:SI 0 "equality_operator"
[(match_operand:SI 2 "register_operand" "d")
(match_operand:SI 3 "register_operand" "d")])
(pc)
(define_insn "branch_equality_di_inverted"
[(set (pc)
(if_then_else
- (match_operator:DI 0 "equality_op"
+ (match_operator:DI 0 "equality_operator"
[(match_operand:DI 2 "register_operand" "d")
(match_operand:DI 3 "register_operand" "d")])
(pc)
(define_insn ""
[(set (pc)
- (if_then_else (match_operator:SI 0 "equality_op"
- [(match_operand:SI 1 "register_operand" "d,t")
- (const_int 0)])
+ (if_then_else
+ (match_operator:SI 0 "equality_operator"
+ [(match_operand:SI 1 "register_operand" "d,t")
+ (const_int 0)])
(match_operand 2 "pc_or_label_operand" "")
(match_operand 3 "pc_or_label_operand" "")))]
"TARGET_MIPS16"
(define_insn ""
[(set (pc)
- (if_then_else (match_operator:DI 0 "equality_op"
- [(match_operand:DI 1 "register_operand" "d,t")
- (const_int 0)])
+ (if_then_else
+ (match_operator:DI 0 "equality_operator"
+ [(match_operand:DI 1 "register_operand" "d,t")
+ (const_int 0)])
(match_operand 2 "pc_or_label_operand" "")
(match_operand 3 "pc_or_label_operand" "")))]
"TARGET_MIPS16"
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d,d")
(if_then_else:SI
- (match_operator 4 "equality_op"
+ (match_operator 4 "equality_operator"
[(match_operand:SI 1 "register_operand" "d,d")
(const_int 0)])
(match_operand:SI 2 "reg_or_0_operand" "dJ,0")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d,d")
(if_then_else:SI
- (match_operator 4 "equality_op"
+ (match_operator 4 "equality_operator"
[(match_operand:DI 1 "register_operand" "d,d")
(const_int 0)])
(match_operand:SI 2 "reg_or_0_operand" "dJ,0")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d,d")
(if_then_else:SI
- (match_operator 3 "equality_op" [(match_operand:CC 4
- "register_operand"
- "z,z")
- (const_int 0)])
+ (match_operator 3 "equality_operator"
+ [(match_operand:CC 4 "register_operand" "z,z")
+ (const_int 0)])
(match_operand:SI 1 "reg_or_0_operand" "dJ,0")
(match_operand:SI 2 "reg_or_0_operand" "0,dJ")))]
"ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT"
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d,d")
(if_then_else:DI
- (match_operator 4 "equality_op"
+ (match_operator 4 "equality_operator"
[(match_operand:SI 1 "register_operand" "d,d")
(const_int 0)])
(match_operand:DI 2 "reg_or_0_operand" "dJ,0")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d,d")
(if_then_else:DI
- (match_operator 4 "equality_op"
+ (match_operator 4 "equality_operator"
[(match_operand:DI 1 "register_operand" "d,d")
(const_int 0)])
(match_operand:DI 2 "reg_or_0_operand" "dJ,0")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d,d")
(if_then_else:DI
- (match_operator 3 "equality_op" [(match_operand:CC 4
- "register_operand"
- "z,z")
- (const_int 0)])
+ (match_operator 3 "equality_operator"
+ [(match_operand:CC 4 "register_operand" "z,z")
+ (const_int 0)])
(match_operand:DI 1 "reg_or_0_operand" "dJ,0")
(match_operand:DI 2 "reg_or_0_operand" "0,dJ")))]
"ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT && TARGET_64BIT"
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=f,f")
(if_then_else:SF
- (match_operator 4 "equality_op"
+ (match_operator 4 "equality_operator"
[(match_operand:SI 1 "register_operand" "d,d")
(const_int 0)])
(match_operand:SF 2 "register_operand" "f,0")
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=f,f")
(if_then_else:SF
- (match_operator 4 "equality_op"
+ (match_operator 4 "equality_operator"
[(match_operand:DI 1 "register_operand" "d,d")
(const_int 0)])
(match_operand:SF 2 "register_operand" "f,0")
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=f,f")
(if_then_else:SF
- (match_operator 3 "equality_op" [(match_operand:CC 4
- "register_operand"
- "z,z")
- (const_int 0)])
+ (match_operator 3 "equality_operator"
+ [(match_operand:CC 4 "register_operand" "z,z")
+ (const_int 0)])
(match_operand:SF 1 "register_operand" "f,0")
(match_operand:SF 2 "register_operand" "0,f")))]
"ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT"
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f,f")
(if_then_else:DF
- (match_operator 4 "equality_op"
+ (match_operator 4 "equality_operator"
[(match_operand:SI 1 "register_operand" "d,d")
(const_int 0)])
(match_operand:DF 2 "register_operand" "f,0")
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f,f")
(if_then_else:DF
- (match_operator 4 "equality_op"
+ (match_operator 4 "equality_operator"
[(match_operand:DI 1 "register_operand" "d,d")
(const_int 0)])
(match_operand:DF 2 "register_operand" "f,0")
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f,f")
(if_then_else:DF
- (match_operator 3 "equality_op" [(match_operand:CC 4
- "register_operand"
- "z,z")
- (const_int 0)])
+ (match_operator 3 "equality_operator"
+ [(match_operand:CC 4 "register_operand" "z,z")
+ (const_int 0)])
(match_operand:DF 1 "register_operand" "f,0")
(match_operand:DF 2 "register_operand" "0,f")))]
"ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
--- /dev/null
+;; Predicate definitions for MIPS.
+;; Copyright (C) 2004 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+(define_predicate "const_uns_arith_operand"
+ (and (match_code "const_int")
+ (match_test "SMALL_OPERAND_UNSIGNED (INTVAL (op))")))
+
+(define_predicate "uns_arith_operand"
+ (ior (match_operand 0 "const_uns_arith_operand")
+ (match_operand 0 "register_operand")))
+
+(define_predicate "const_arith_operand"
+ (and (match_code "const_int")
+ (match_test "SMALL_OPERAND (INTVAL (op))")))
+
+(define_predicate "arith_operand"
+ (ior (match_operand 0 "const_arith_operand")
+ (match_operand 0 "register_operand")))
+
+(define_predicate "sle_operand"
+ (and (match_code "const_int")
+ (match_test "SMALL_OPERAND (INTVAL (op) + 1)")))
+
+(define_predicate "sleu_operand"
+ (and (match_operand 0 "sle_operand")
+ (match_test "INTVAL (op) + 1 != 0")))
+
+(define_predicate "const_0_operand"
+ (and (match_code "const_int,const_double")
+ (match_test "op == CONST0_RTX (GET_MODE (op))")))
+
+(define_predicate "reg_or_0_operand"
+ (ior (and (match_operand 0 "const_0_operand")
+ (match_test "!TARGET_MIPS16"))
+ (match_operand 0 "register_operand")))
+
+(define_predicate "const_1_operand"
+ (and (match_code "const_int,const_double")
+ (match_test "op == CONST1_RTX (GET_MODE (op))")))
+
+(define_predicate "reg_or_1_operand"
+ (ior (match_operand 0 "const_1_operand")
+ (match_operand 0 "register_operand")))
+
+(define_predicate "fpr_operand"
+ (and (match_code "reg")
+ (match_test "FP_REG_P (REGNO (op))")))
+
+(define_predicate "hilo_operand"
+ (and (match_code "reg")
+ (match_test "MD_REG_P (REGNO (op))")))
+
+(define_predicate "lo_operand"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == LO_REGNUM")))
+
+(define_predicate "fcc_reload_operand"
+ (and (match_code "reg,subreg")
+ (match_test "ST_REG_P (true_regnum (op))")))
+
+(define_special_predicate "pc_or_label_operand"
+ (match_code "pc,label_ref"))
+
+(define_predicate "const_call_insn_operand"
+ (match_code "const,symbol_ref,label_ref")
+{
+ enum mips_symbol_type symbol_type;
+
+ if (!mips_symbolic_constant_p (op, &symbol_type))
+ return false;
+
+ switch (symbol_type)
+ {
+ case SYMBOL_GENERAL:
+ /* If -mlong-calls, force all calls to use register addressing. */
+ return !TARGET_LONG_CALLS;
+
+ case SYMBOL_GOT_GLOBAL:
+ /* Without explicit relocs, there is no special syntax for
+ loading the address of a call destination into a register.
+ Using "la $25,foo; jal $25" would prevent the lazy binding
+ of "foo", so keep the address of global symbols with the
+ jal macro. */
+ return !TARGET_EXPLICIT_RELOCS;
+
+ default:
+ return false;
+ }
+})
+
+(define_predicate "call_insn_operand"
+ (ior (match_operand 0 "const_call_insn_operand")
+ (match_operand 0 "register_operand")))
+
+(define_predicate "move_operand"
+ (match_operand 0 "general_operand")
+{
+ switch (GET_CODE (op))
+ {
+ case CONST_INT:
+ /* When generating mips16 code, LEGITIMATE_CONSTANT_P rejects
+ CONST_INTs that can't be loaded using simple insns. */
+ if (TARGET_MIPS16)
+ return true;
+
+ /* When generating 32-bit code, allow DImode move_operands to
+ match arbitrary constants. We split them after reload. */
+ if (!TARGET_64BIT && mode == DImode)
+ return true;
+
+ /* Otherwise check whether the constant can be loaded in a single
+ instruction. */
+ return LUI_INT (op) || SMALL_INT (op) || SMALL_INT_UNSIGNED (op);
+
+ case CONST:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return CONST_GP_P (op) || mips_atomic_symbolic_constant_p (op);
+
+ default:
+ return true;
+ }
+})
+
+(define_predicate "consttable_operand"
+ (match_test "CONSTANT_P (op)"))
+
+(define_predicate "symbolic_operand"
+ (match_code "const,symbol_ref,label_ref")
+{
+ enum mips_symbol_type type;
+ return mips_symbolic_constant_p (op, &type);
+})
+
+(define_predicate "general_symbolic_operand"
+ (match_code "const,symbol_ref,label_ref")
+{
+ enum mips_symbol_type type;
+ return mips_symbolic_constant_p (op, &type) && type == SYMBOL_GENERAL;
+})
+
+(define_predicate "global_got_operand"
+ (match_code "const,symbol_ref,label_ref")
+{
+ enum mips_symbol_type type;
+ return mips_symbolic_constant_p (op, &type) && type == SYMBOL_GOT_GLOBAL;
+})
+
+(define_predicate "local_got_operand"
+ (match_code "const,symbol_ref,label_ref")
+{
+ enum mips_symbol_type type;
+ return mips_symbolic_constant_p (op, &type) && type == SYMBOL_GOT_LOCAL;
+})
+
+(define_predicate "stack_operand"
+ (and (match_code "mem")
+ (match_test "mips_stack_address_p (XEXP (op, 0), GET_MODE (op))")))
+
+(define_predicate "macc_msac_operand"
+ (ior (and (match_code "plus") (match_test "ISA_HAS_MACC"))
+ (and (match_code "minus") (match_test "ISA_HAS_MSAC")))
+{
+ rtx mult = XEXP (op, GET_CODE (op) == PLUS ? 0 : 1);
+ rtx accum = XEXP (op, GET_CODE (op) == PLUS ? 1 : 0);
+ return (GET_CODE (mult) == MULT
+ && REG_P (XEXP (mult, 0))
+ && REG_P (XEXP (mult, 1))
+ && REG_P (accum));
+})
+
+
+(define_predicate "equality_operator"
+ (match_code "eq,ne"))
+
+(define_predicate "extend_operator"
+ (match_code "zero_extend,sign_extend"))
+
+(define_predicate "trap_comparison_operator"
+ (match_code "eq,ne,lt,ltu,ge,geu"))
+
+
+(define_predicate "small_data_pattern"
+ (and (match_code "set,parallel,unspec,unspec_volatile")
+ (match_test "mips_small_data_pattern_p (op)")))
(define_insn_reservation "ir_sb1_mtxfer" 5
(and (eq_attr "cpu" "sb1")
(and (eq_attr "type" "xfer")
- (match_operand 0 "fp_register_operand")))
+ (match_operand 0 "fpr_operand")))
"sb1_fp0")
;; mfc1 latency 1 cycle.
(define_insn_reservation "ir_sb1_mfxfer" 1
(and (eq_attr "cpu" "sb1")
(and (eq_attr "type" "xfer")
- (not (match_operand 0 "fp_register_operand"))))
+ (not (match_operand 0 "fpr_operand"))))
"sb1_fp0")
;; ??? Can deliver at most 1 result per every 6 cycles because of issue