diff options
author | Zack Weinberg <zack@gcc.gnu.org> | 2004-08-12 07:49:00 +0000 |
---|---|---|
committer | Zack Weinberg <zack@gcc.gnu.org> | 2004-08-12 07:49:00 +0000 |
commit | e543e219eb1865d4230278c3db3d2bedd60b1de0 (patch) | |
tree | 35550b19b3978c830f6043f43687018fe8198d2d /gcc/config/ia64 | |
parent | b4d49f49bf21837bef59aa30788e2e9bf2ce2e3b (diff) | |
download | gcc-e543e219eb1865d4230278c3db3d2bedd60b1de0.zip gcc-e543e219eb1865d4230278c3db3d2bedd60b1de0.tar.gz gcc-e543e219eb1865d4230278c3db3d2bedd60b1de0.tar.bz2 |
genpreds.c: Add capability to generate predicate bodies as well as function prototypes.
* genpreds.c: Add capability to generate predicate bodies as
well as function prototypes. Write function prototypes for
the generic predicates too.
(process_define_predicate, write_tm_preds_h, write_insn_preds_c)
(write_predicate_subfunction, mark_mode_tests, add_mode_tests)
(write_match_code, write_predicate_expr, write_one_predicate_function)
(parse_option): New functions.
(output_predicate_decls): Delete.
(main): Read the machine description, process DEFINE_PREDICATE or
DEFINE_SPECIAL_PREDICATE patterns, write tm-preds.h or insn-preds.c
as appropriate.
* genrecog.c (struct decision_test): Replace index with
struct pred_data pointer.
(next_index): Remove, unused.
(pred_table, preds, special_mode_pred_table): Delete.
(compute_predicate_codes, process_define_predicate): New functions.
(validate_pattern, add_to_sequence, write_switch): Update for
new data structures.
(main): Handle DEFINE_PREDICATE and DEFINE_SPECIAL_PREDICATE.
Check both error_count and have_error.
* gensupport.c (in_fname, first_predicate): New globals.
(define_pred_queue, define_pred_tail): New RTL-pattern queue.
(predicate_table, last_predicate, old_pred_table)
(old_special_pred_table): New statics.
(hash_struct_pred_data, eq_struct_pred_data, lookup_predicate)
(add_predicate, init_predicate_table): New functions.
(process_rtx): Handle DEFINE_PREDICATE and DEFINE_SPECIAL_PREDICATE.
(init_md_reader_args_cb): Use the global in_fname. No need to zero
it or max_include_len. Call init_predicate_table.
(read_rtx): Run the predicate queue after the attribute queue
but before all the others.
* gensupport.h (in_fname, struct pred_data, first_predicate)
(lookup_predicate, add_predicate, FOR_ALL_PREDICATES): Declare.
* rtl.def (MATCH_CODE, MATCH_TEST, DEFINE_PREDICATE)
(DEFINE_SPECIAL_PREDICATE): New RTL codes.
* dummy-conditions.c: Don't include bconfig.h, system.h,
coretypes.h, tm.h, or system.h. Do include stddef.h.
Duplicate declaration of struct c_test from gensupport.h.
* Makefile.in (OBJS-common): Add insn-preds.o.
(STAGESTUFF, .PRECIOUS): Add insn-preds.c.
(insn-preds.c, insn-preds.o): New rules.
(s-preds): Also generate insn-preds.c.
(dummy-conditions.o, genpreds$(build_exeext), genpreds.o):
Update dependencies.
(print-rtl.o, print-rtl1.o): Correct dependencies.
* recog.h: Delete prototypes of predicate functions.
* doc/md.texi (Predicates): New section with complete
documentation of operand/operator predicates. Remove some
incomplete documentation of predicates from other places.
* doc/tm.texi (Misc): Move SPECIAL_MODE_PREDICATES next to
PREDICATE_CODES; indicate that both are deprecated in favor
of define_predicate/define_special_predicate.
* config/ia64/ia64.c: All predicate function definitions moved
to ia64.md, except
(small_addr_symbolic_operand, tls_symbolic_operand): Delete.
(ia64_expand_load_address, ia64_expand_move):
Check SYMBOL_REF_TLS_MODEL directly, don't use tls_symbolic_operand.
* config/ia64/ia64.md: All predicates now defined here.
(symbolic_operand): Is now a special predicate.
* config/ia64/ia64.h: Declare ia64_section_threshold.
(PREDICATE_CODES): Delete.
From-SVN: r85855
Diffstat (limited to 'gcc/config/ia64')
-rw-r--r-- | gcc/config/ia64/ia64.c | 512 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.h | 51 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.md | 336 |
3 files changed, 343 insertions, 556 deletions
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 66e51ea..ce48d3f 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -418,513 +418,6 @@ static const struct attribute_spec ia64_attribute_table[] = struct gcc_target targetm = TARGET_INITIALIZER; -/* Return 1 if OP is a valid operand for the MEM of a CALL insn. */ - -int -call_operand (rtx op, enum machine_mode mode) -{ - if (mode != GET_MODE (op) && mode != VOIDmode) - return 0; - - return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG - || (GET_CODE (op) == SUBREG && GET_CODE (XEXP (op, 0)) == REG)); -} - -/* Return 1 if OP refers to a symbol in the sdata section. */ - -int -sdata_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - switch (GET_CODE (op)) - { - case CONST: - if (GET_CODE (XEXP (op, 0)) != PLUS - || GET_CODE (XEXP (XEXP (op, 0), 0)) != SYMBOL_REF) - break; - op = XEXP (XEXP (op, 0), 0); - /* FALLTHRU */ - - case SYMBOL_REF: - if (CONSTANT_POOL_ADDRESS_P (op)) - return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold; - else - return SYMBOL_REF_LOCAL_P (op) && SYMBOL_REF_SMALL_P (op); - - default: - break; - } - - return 0; -} - -int -small_addr_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return SYMBOL_REF_SMALL_ADDR_P (op); -} - -/* Return 1 if OP refers to a symbol, and is appropriate for a GOT load. */ - -int -got_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - switch (GET_CODE (op)) - { - case CONST: - /* Accept only (plus (symbol_ref) (const_int)). */ - op = XEXP (op, 0); - if (GET_CODE (op) != PLUS) - return 0; - if (GET_CODE (XEXP (op, 0)) != SYMBOL_REF) - return 0; - op = XEXP (op, 1); - if (GET_CODE (op) != CONST_INT) - return 0; - - /* Ok if we're not using GOT entries at all. */ - if (TARGET_NO_PIC || TARGET_AUTO_PIC) - return 1; - - /* The low 14 bits of the constant have been forced to zero - by ia64_expand_load_address, so that we do not use up so - many GOT entries. Prevent cse from undoing this. */ - return (INTVAL (op) & 0x3fff) == 0; - - case SYMBOL_REF: - /* This sort of load should not be used for things in sdata. */ - return !SYMBOL_REF_SMALL_ADDR_P (op); - - case LABEL_REF: - return 1; - - default: - break; - } - return 0; -} - -/* Return 1 if OP refers to a symbol. */ - -int -symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - switch (GET_CODE (op)) - { - case CONST: - case SYMBOL_REF: - case LABEL_REF: - return 1; - - default: - break; - } - return 0; -} - -/* Return tls_model if OP refers to a TLS symbol. */ - -int -tls_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (op) != SYMBOL_REF) - return 0; - return SYMBOL_REF_TLS_MODEL (op); -} - - -/* Return 1 if OP refers to a function. */ - -int -function_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (op)) - return 1; - else - return 0; -} - -/* Return 1 if OP is a general operand, excluding tls symbolic operands. */ - -int -move_operand (rtx op, enum machine_mode mode) -{ - return general_operand (op, mode) && !tls_symbolic_operand (op, mode); -} - -/* Return 1 if OP is a register operand that is (or could be) a GR reg. */ - -int -gr_register_operand (rtx op, enum machine_mode mode) -{ - if (! register_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (GET_CODE (op) == REG) - { - unsigned int regno = REGNO (op); - if (regno < FIRST_PSEUDO_REGISTER) - return GENERAL_REGNO_P (regno); - } - return 1; -} - -/* Return 1 if OP is a register operand that is (or could be) an FR reg. */ - -int -fr_register_operand (rtx op, enum machine_mode mode) -{ - if (! register_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (GET_CODE (op) == REG) - { - unsigned int regno = REGNO (op); - if (regno < FIRST_PSEUDO_REGISTER) - return FR_REGNO_P (regno); - } - return 1; -} - -/* Return 1 if OP is a register operand that is (or could be) a GR/FR reg. */ - -int -grfr_register_operand (rtx op, enum machine_mode mode) -{ - if (! register_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (GET_CODE (op) == REG) - { - unsigned int regno = REGNO (op); - if (regno < FIRST_PSEUDO_REGISTER) - return GENERAL_REGNO_P (regno) || FR_REGNO_P (regno); - } - return 1; -} - -/* Return 1 if OP is a nonimmediate operand that is (or could be) a GR reg. */ - -int -gr_nonimmediate_operand (rtx op, enum machine_mode mode) -{ - if (! nonimmediate_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (GET_CODE (op) == REG) - { - unsigned int regno = REGNO (op); - if (regno < FIRST_PSEUDO_REGISTER) - return GENERAL_REGNO_P (regno); - } - return 1; -} - -/* Return 1 if OP is a nonimmediate operand that is (or could be) a FR reg. */ - -int -fr_nonimmediate_operand (rtx op, enum machine_mode mode) -{ - if (! nonimmediate_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (GET_CODE (op) == REG) - { - unsigned int regno = REGNO (op); - if (regno < FIRST_PSEUDO_REGISTER) - return FR_REGNO_P (regno); - } - return 1; -} - -/* Return 1 if OP is a nonimmediate operand that is a GR/FR reg. */ - -int -grfr_nonimmediate_operand (rtx op, enum machine_mode mode) -{ - if (! nonimmediate_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (GET_CODE (op) == REG) - { - unsigned int regno = REGNO (op); - if (regno < FIRST_PSEUDO_REGISTER) - return GENERAL_REGNO_P (regno) || FR_REGNO_P (regno); - } - return 1; -} - -/* Return 1 if OP is a GR register operand, or zero. */ - -int -gr_reg_or_0_operand (rtx op, enum machine_mode mode) -{ - return (op == const0_rtx || gr_register_operand (op, mode)); -} - -/* Return 1 if OP is a GR register operand, or a 5 bit immediate operand. */ - -int -gr_reg_or_5bit_operand (rtx op, enum machine_mode mode) -{ - return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) < 32) - || gr_register_operand (op, mode)); -} - -/* Return 1 if OP is a GR register operand, or a 6 bit immediate operand. */ - -int -gr_reg_or_6bit_operand (rtx op, enum machine_mode mode) -{ - return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op))) - || gr_register_operand (op, mode)); -} - -/* Return 1 if OP is a GR register operand, or an 8 bit immediate operand. */ - -int -gr_reg_or_8bit_operand (rtx op, enum machine_mode mode) -{ - return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op))) - || gr_register_operand (op, mode)); -} - -/* Return 1 if OP is a GR/FR register operand, or an 8 bit immediate. */ - -int -grfr_reg_or_8bit_operand (rtx op, enum machine_mode mode) -{ - return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op))) - || grfr_register_operand (op, mode)); -} - -/* Return 1 if OP is a register operand, or an 8 bit adjusted immediate - operand. */ - -int -gr_reg_or_8bit_adjusted_operand (rtx op, enum machine_mode mode) -{ - return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op))) - || gr_register_operand (op, mode)); -} - -/* Return 1 if OP is a register operand, or is valid for both an 8 bit - immediate and an 8 bit adjusted immediate operand. This is necessary - because when we emit a compare, we don't know what the condition will be, - so we need the union of the immediates accepted by GT and LT. */ - -int -gr_reg_or_8bit_and_adjusted_operand (rtx op, enum machine_mode mode) -{ - return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)) - && CONST_OK_FOR_L (INTVAL (op))) - || gr_register_operand (op, mode)); -} - -/* Return 1 if OP is a register operand, or a 14 bit immediate operand. */ - -int -gr_reg_or_14bit_operand (rtx op, enum machine_mode mode) -{ - return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op))) - || gr_register_operand (op, mode)); -} - -/* Return 1 if OP is a register operand, or a 22 bit immediate operand. */ - -int -gr_reg_or_22bit_operand (rtx op, enum machine_mode mode) -{ - return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_J (INTVAL (op))) - || gr_register_operand (op, mode)); -} - -/* Return 1 if OP is a 6 bit immediate operand. */ - -int -shift_count_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op))); -} - -/* Return 1 if OP is a 5 bit immediate operand. */ - -int -shift_32bit_count_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT - && (INTVAL (op) >= 0 && INTVAL (op) < 32)); -} - -/* Return 1 if OP is a 2, 4, 8, or 16 immediate operand. */ - -int -shladd_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT - && (INTVAL (op) == 2 || INTVAL (op) == 4 - || INTVAL (op) == 8 || INTVAL (op) == 16)); -} - -/* Return 1 if OP is a -16, -8, -4, -1, 1, 4, 8, or 16 immediate operand. */ - -int -fetchadd_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - return (GET_CODE (op) == CONST_INT - && (INTVAL (op) == -16 || INTVAL (op) == -8 || - INTVAL (op) == -4 || INTVAL (op) == -1 || - INTVAL (op) == 1 || INTVAL (op) == 4 || - INTVAL (op) == 8 || INTVAL (op) == 16)); -} - -/* Return 1 if OP is a floating-point constant zero, one, or a register. */ - -int -fr_reg_or_fp01_operand (rtx op, enum machine_mode mode) -{ - return ((GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (op)) - || fr_register_operand (op, mode)); -} - -/* Like nonimmediate_operand, but don't allow MEMs that try to use a - POST_MODIFY with a REG as displacement. */ - -int -destination_operand (rtx op, enum machine_mode mode) -{ - if (! nonimmediate_operand (op, mode)) - return 0; - if (GET_CODE (op) == MEM - && GET_CODE (XEXP (op, 0)) == POST_MODIFY - && GET_CODE (XEXP (XEXP (XEXP (op, 0), 1), 1)) == REG) - return 0; - return 1; -} - -/* Like memory_operand, but don't allow post-increments. */ - -int -not_postinc_memory_operand (rtx op, enum machine_mode mode) -{ - return (memory_operand (op, mode) - && GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != RTX_AUTOINC); -} - -/* Return 1 if this is a comparison operator, which accepts a normal 8-bit - signed immediate operand. */ - -int -normal_comparison_operator (register rtx op, enum machine_mode mode) -{ - enum rtx_code code = GET_CODE (op); - return ((mode == VOIDmode || GET_MODE (op) == mode) - && (code == EQ || code == NE - || code == GT || code == LE || code == GTU || code == LEU)); -} - -/* Return 1 if this is a comparison operator, which accepts an adjusted 8-bit - signed immediate operand. */ - -int -adjusted_comparison_operator (register rtx op, enum machine_mode mode) -{ - enum rtx_code code = GET_CODE (op); - return ((mode == VOIDmode || GET_MODE (op) == mode) - && (code == LT || code == GE || code == LTU || code == GEU)); -} - -/* Return 1 if this is a signed inequality operator. */ - -int -signed_inequality_operator (register rtx op, enum machine_mode mode) -{ - enum rtx_code code = GET_CODE (op); - return ((mode == VOIDmode || GET_MODE (op) == mode) - && (code == GE || code == GT - || code == LE || code == LT)); -} - -/* Return 1 if this operator is valid for predication. */ - -int -predicate_operator (register rtx op, enum machine_mode mode) -{ - enum rtx_code code = GET_CODE (op); - return ((GET_MODE (op) == mode || mode == VOIDmode) - && (code == EQ || code == NE)); -} - -/* Return 1 if this operator can be used in a conditional operation. */ - -int -condop_operator (register rtx op, enum machine_mode mode) -{ - enum rtx_code code = GET_CODE (op); - return ((GET_MODE (op) == mode || mode == VOIDmode) - && (code == PLUS || code == MINUS || code == AND - || code == IOR || code == XOR)); -} - -/* Return 1 if this is the ar.lc register. */ - -int -ar_lc_reg_operand (register rtx op, enum machine_mode mode) -{ - return (GET_MODE (op) == DImode - && (mode == DImode || mode == VOIDmode) - && GET_CODE (op) == REG - && REGNO (op) == AR_LC_REGNUM); -} - -/* Return 1 if this is the ar.ccv register. */ - -int -ar_ccv_reg_operand (register rtx op, enum machine_mode mode) -{ - return ((GET_MODE (op) == mode || mode == VOIDmode) - && GET_CODE (op) == REG - && REGNO (op) == AR_CCV_REGNUM); -} - -/* Return 1 if this is the ar.pfs register. */ - -int -ar_pfs_reg_operand (register rtx op, enum machine_mode mode) -{ - return ((GET_MODE (op) == mode || mode == VOIDmode) - && GET_CODE (op) == REG - && REGNO (op) == AR_PFS_REGNUM); -} - -/* Similarly. */ - -int -xfreg_or_fp01_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == SUBREG) - return 0; - return fr_reg_or_fp01_operand (op, mode); -} - -/* Return 1 if OP is valid as a base register in a reg + offset address. */ - -int -basereg_operand (rtx op, enum machine_mode mode) -{ - /* ??? Should I copy the flag_omit_frame_pointer and cse_not_expected - checks from pa.c basereg_operand as well? Seems to be OK without them - in test runs. */ - - return (register_operand (op, mode) && - REG_POINTER ((GET_CODE (op) == SUBREG) ? SUBREG_REG (op) : op)); -} - typedef enum { ADDR_AREA_NORMAL, /* normal address area */ @@ -1099,7 +592,7 @@ ia64_depz_field_mask (rtx rop, rtx rshift) void ia64_expand_load_address (rtx dest, rtx src) { - if (tls_symbolic_operand (src, VOIDmode)) + if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (src)) abort (); if (GET_CODE (dest) != REG) abort (); @@ -1299,7 +792,8 @@ ia64_expand_move (rtx op0, rtx op1) if ((mode == Pmode || mode == ptr_mode) && symbolic_operand (op1, VOIDmode)) { enum tls_model tls_kind; - if ((tls_kind = tls_symbolic_operand (op1, VOIDmode))) + if (GET_CODE (op1) == SYMBOL_REF + && (tls_kind = SYMBOL_REF_TLS_MODEL (op1))) return ia64_expand_tls_address (tls_kind, op0, op1); if (!TARGET_NO_PIC && reload_completed) diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index 96b559b..58304a9 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -146,6 +146,10 @@ extern int target_flags; #define TARGET_DWARF2_ASM (target_flags & MASK_DWARF2_ASM) +/* Variables which are this size or smaller are put in the sdata/sbss + sections. */ +extern unsigned int ia64_section_threshold; + /* If the assembler supports thread-local storage, assume that the system does as well. If a particular target system has an assembler that supports TLS -- but the rest of the system does not @@ -2140,53 +2144,6 @@ do { \ #define SYMBOL_REF_SMALL_ADDR_P(X) \ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_SMALL_ADDR) != 0) -/* Define this if you have defined special-purpose predicates in the file - `MACHINE.c'. For each predicate, list all rtl codes that can be in - expressions matched by the predicate. */ - -#define PREDICATE_CODES \ -{ "call_operand", {SUBREG, REG, SYMBOL_REF}}, \ -{ "got_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \ -{ "sdata_symbolic_operand", {SYMBOL_REF, CONST}}, \ -{ "small_addr_symbolic_operand", {SYMBOL_REF}}, \ -{ "symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \ -{ "tls_symbolic_operand", {SYMBOL_REF}}, \ -{ "function_operand", {SYMBOL_REF}}, \ -{ "destination_operand", {SUBREG, REG, MEM}}, \ -{ "not_postinc_memory_operand", {MEM}}, \ -{ "move_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ - SYMBOL_REF, CONST, LABEL_REF}}, \ -{ "gr_register_operand", {SUBREG, REG}}, \ -{ "fr_register_operand", {SUBREG, REG}}, \ -{ "grfr_register_operand", {SUBREG, REG}}, \ -{ "gr_nonimmediate_operand", {SUBREG, REG, MEM}}, \ -{ "fr_nonimmediate_operand", {SUBREG, REG, MEM}}, \ -{ "grfr_nonimmediate_operand", {SUBREG, REG, MEM}}, \ -{ "gr_reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \ -{ "gr_reg_or_5bit_operand", {SUBREG, REG, CONST_INT}}, \ -{ "gr_reg_or_6bit_operand", {SUBREG, REG, CONST_INT}}, \ -{ "gr_reg_or_8bit_operand", {SUBREG, REG, CONST_INT}}, \ -{ "grfr_reg_or_8bit_operand", {SUBREG, REG, CONST_INT}}, \ -{ "gr_reg_or_8bit_adjusted_operand", {SUBREG, REG, CONST_INT}}, \ -{ "gr_reg_or_8bit_and_adjusted_operand", {SUBREG, REG, CONST_INT}}, \ -{ "gr_reg_or_14bit_operand", {SUBREG, REG, CONST_INT}}, \ -{ "gr_reg_or_22bit_operand", {SUBREG, REG, CONST_INT}}, \ -{ "shift_count_operand", {SUBREG, REG, CONST_INT}}, \ -{ "shift_32bit_count_operand", {SUBREG, REG, CONST_INT}}, \ -{ "shladd_operand", {CONST_INT}}, \ -{ "fetchadd_operand", {CONST_INT}}, \ -{ "fr_reg_or_fp01_operand", {SUBREG, REG, CONST_DOUBLE}}, \ -{ "normal_comparison_operator", {EQ, NE, GT, LE, GTU, LEU}}, \ -{ "adjusted_comparison_operator", {LT, GE, LTU, GEU}}, \ -{ "signed_inequality_operator", {GE, GT, LE, LT}}, \ -{ "predicate_operator", {NE, EQ}}, \ -{ "condop_operator", {PLUS, MINUS, IOR, XOR, AND}}, \ -{ "ar_lc_reg_operand", {REG}}, \ -{ "ar_ccv_reg_operand", {REG}}, \ -{ "ar_pfs_reg_operand", {REG}}, \ -{ "xfreg_or_fp01_operand", {REG, CONST_DOUBLE}}, \ -{ "basereg_operand", {SUBREG, REG}}, - /* An alias for a machine mode name. This is the machine mode that elements of a jump-table should have. */ diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md index 04eda40..31af3bb 100644 --- a/gcc/config/ia64/ia64.md +++ b/gcc/config/ia64/ia64.md @@ -92,6 +92,342 @@ ;; :::::::::::::::::::: ;; :: +;; :: Predicates +;; :: +;; :::::::::::::::::::: + +;; True if OP is a valid operand for the MEM of a CALL insn. +(define_predicate "call_operand" + (ior (match_code "symbol_ref") + (match_operand 0 "register_operand"))) + +;; True if OP refers to any kind of symbol. +;; For roughly the same reasons that pmode_register_operand exists, this +;; predicate ignores its mode argument. +(define_special_predicate "symbolic_operand" + (match_code "symbol_ref,const,label_ref")) + +;; True if OP is a SYMBOL_REF which refers to a function. +(define_predicate "function_operand" + (and (match_code "symbol_ref") + (match_test "SYMBOL_REF_FUNCTION_P (op)"))) + +;; True if OP refers to a symbol, and is appropriate for a GOT load. +(define_predicate "got_symbolic_operand" + (match_operand 0 "symbolic_operand" "") +{ + switch (GET_CODE (op)) + { + case LABEL_REF: + return true; + + case SYMBOL_REF: + /* This sort of load should not be used for things in sdata. */ + return !SYMBOL_REF_SMALL_ADDR_P (op); + + case CONST: + /* Accept only (plus (symbol_ref) (const_int)). */ + op = XEXP (op, 0); + if (GET_CODE (op) != PLUS + || GET_CODE (XEXP (op, 0)) != SYMBOL_REF + || GET_CODE (XEXP (op, 1)) != CONST_INT) + return false; + + /* Ok if we're not using GOT entries at all. */ + if (TARGET_NO_PIC || TARGET_AUTO_PIC) + return true; + + /* The low 14 bits of the constant have been forced to zero + by ia64_expand_load_address, so that we do not use up so + many GOT entries. Prevent cse from undoing this. */ + op = XEXP (op, 1); + return (INTVAL (op) & 0x3fff) == 0; + + default: + abort (); + } +}) + +;; True if OP refers to a symbol in the sdata section. +(define_predicate "sdata_symbolic_operand" + (match_code "symbol_ref,const") +{ + switch (GET_CODE (op)) + { + case CONST: + op = XEXP (op, 0); + if (GET_CODE (op) != PLUS + || GET_CODE (XEXP (op, 0)) != SYMBOL_REF) + return false; + op = XEXP (op, 0); + /* FALLTHRU */ + + case SYMBOL_REF: + if (CONSTANT_POOL_ADDRESS_P (op)) + return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold; + else + return SYMBOL_REF_LOCAL_P (op) && SYMBOL_REF_SMALL_P (op); + + default: + abort (); + } +}) + +;; Like nonimmediate_operand, but don't allow MEMs that try to use a +;; POST_MODIFY with a REG as displacement. +(define_predicate "destination_operand" + (and (match_operand 0 "nonimmediate_operand") + (match_test "GET_CODE (op) != MEM + || GET_CODE (XEXP (op, 0)) != POST_MODIFY + || GET_CODE (XEXP (XEXP (XEXP (op, 0), 1), 1)) != REG"))) + +;; Like memory_operand, but don't allow post-increments. +(define_predicate "not_postinc_memory_operand" + (and (match_operand 0 "memory_operand") + (match_test "GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != RTX_AUTOINC"))) + +;; True if OP is a general operand, excluding tls symbolic operands. +(define_predicate "move_operand" + (and (match_operand 0 "general_operand") + (not (match_test + "GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (op)")))) + +;; True if OP is a register operand that is (or could be) a GR reg. +(define_predicate "gr_register_operand" + (match_operand 0 "register_operand") +{ + unsigned int regno; + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + regno = REGNO (op); + return (regno >= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno)); +}) + +;; True if OP is a register operand that is (or could be) an FR reg. +(define_predicate "fr_register_operand" + (match_operand 0 "register_operand") +{ + unsigned int regno; + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + regno = REGNO (op); + return (regno >= FIRST_PSEUDO_REGISTER || FR_REGNO_P (regno)); +}) + +;; True if OP is a register operand that is (or could be) a GR/FR reg. +(define_predicate "grfr_register_operand" + (match_operand 0 "register_operand") +{ + unsigned int regno; + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + regno = REGNO (op); + return (regno >= FIRST_PSEUDO_REGISTER + || GENERAL_REGNO_P (regno) + || FR_REGNO_P (regno)); +}) + +;; True if OP is a nonimmediate operand that is (or could be) a GR reg. +(define_predicate "gr_nonimmediate_operand" + (match_operand 0 "nonimmediate_operand") +{ + unsigned int regno; + + if (GET_CODE (op) == MEM) + return true; + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + regno = REGNO (op); + return (regno >= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno)); +}) + +;; True if OP is a nonimmediate operand that is (or could be) a FR reg. +(define_predicate "fr_nonimmediate_operand" + (match_operand 0 "nonimmediate_operand") +{ + unsigned int regno; + + if (GET_CODE (op) == MEM) + return true; + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + regno = REGNO (op); + return (regno >= FIRST_PSEUDO_REGISTER || FR_REGNO_P (regno)); +}) + +;; True if OP is a nonimmediate operand that is (or could be) a GR/FR reg. +(define_predicate "grfr_nonimmediate_operand" + (match_operand 0 "nonimmediate_operand") +{ + unsigned int regno; + + if (GET_CODE (op) == MEM) + return true; + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + regno = REGNO (op); + return (regno >= FIRST_PSEUDO_REGISTER + || GENERAL_REGNO_P (regno) + || FR_REGNO_P (regno)); +}) + +;; True if OP is a GR register operand, or zero. +(define_predicate "gr_reg_or_0_operand" + (ior (match_operand 0 "gr_register_operand") + (and (match_code "const_int") + (match_test "op == const0_rtx")))) + +;; True if OP is a GR register operand, or a 5 bit immediate operand. +(define_predicate "gr_reg_or_5bit_operand" + (ior (match_operand 0 "gr_register_operand") + (and (match_code "const_int") + (match_test "INTVAL (op) >= 0 && INTVAL (op) < 32")))) + +;; True if OP is a GR register operand, or a 6 bit immediate operand. +(define_predicate "gr_reg_or_6bit_operand" + (ior (match_operand 0 "gr_register_operand") + (and (match_code "const_int") + (match_test "CONST_OK_FOR_M (INTVAL (op))")))) + +;; True if OP is a GR register operand, or an 8 bit immediate operand. +(define_predicate "gr_reg_or_8bit_operand" + (ior (match_operand 0 "gr_register_operand") + (and (match_code "const_int") + (match_test "CONST_OK_FOR_K (INTVAL (op))")))) + +;; True if OP is a GR/FR register operand, or an 8 bit immediate operand. +(define_predicate "grfr_reg_or_8bit_operand" + (ior (match_operand 0 "grfr_register_operand") + (and (match_code "const_int") + (match_test "CONST_OK_FOR_K (INTVAL (op))")))) + +;; True if OP is a register operand, or an 8 bit adjusted immediate operand. +(define_predicate "gr_reg_or_8bit_adjusted_operand" + (ior (match_operand 0 "gr_register_operand") + (and (match_code "const_int") + (match_test "CONST_OK_FOR_L (INTVAL (op))")))) + +;; True if OP is a register operand, or is valid for both an 8 bit +;; immediate and an 8 bit adjusted immediate operand. This is necessary +;; because when we emit a compare, we don't know what the condition will be, +;; so we need the union of the immediates accepted by GT and LT. +(define_predicate "gr_reg_or_8bit_and_adjusted_operand" + (ior (match_operand 0 "gr_register_operand") + (and (match_code "const_int") + (match_test "CONST_OK_FOR_K (INTVAL (op)) + && CONST_OK_FOR_L (INTVAL (op))")))) + +;; True if OP is a register operand, or a 14 bit immediate operand. +(define_predicate "gr_reg_or_14bit_operand" + (ior (match_operand 0 "gr_register_operand") + (and (match_code "const_int") + (match_test "CONST_OK_FOR_I (INTVAL (op))")))) + +;; True if OP is a register operand, or a 22 bit immediate operand. +(define_predicate "gr_reg_or_22bit_operand" + (ior (match_operand 0 "gr_register_operand") + (and (match_code "const_int") + (match_test "CONST_OK_FOR_J (INTVAL (op))")))) + +;; True if OP is a 6 bit immediate operand. +(define_predicate "shift_count_operand" + (and (match_code "const_int") + (match_test "CONST_OK_FOR_M (INTVAL (op))"))) + +;; True if OP is a 5 bit immediate operand. +(define_predicate "shift_32bit_count_operand" + (and (match_code "const_int") + (match_test "INTVAL (op) >= 0 && INTVAL (op) < 32"))) + +;; True if OP is one of the immediate valuse 2, 4, 8, or 16. +(define_predicate "shladd_operand" + (and (match_code "const_int") + (match_test "INTVAL (op) == 2 || INTVAL (op) == 4 || + INTVAL (op) == 8 || INTVAL (op) == 16"))) + +;; True if OP is one of the immediate values -16, -8, -4, -1, 1, 4, 8, 16. +(define_predicate "fetchadd_operand" + (and (match_code "const_int") + (match_test "INTVAL (op) == -16 || INTVAL (op) == -8 || + INTVAL (op) == -4 || INTVAL (op) == -1 || + INTVAL (op) == 1 || INTVAL (op) == 4 || + INTVAL (op) == 8 || INTVAL (op) == 16"))) + + +;; True if OP is a floating-point constant zero, one, or a register. +(define_predicate "fr_reg_or_fp01_operand" + (ior (match_operand 0 "fr_register_operand") + (and (match_code "const_double") + (match_test "CONST_DOUBLE_OK_FOR_G (op)")))) + +;; Like fr_reg_or_fp01_operand, but don't allow any SUBREGs. +(define_predicate "xfreg_or_fp01_operand" + (and (match_operand 0 "fr_reg_or_fp01_operand") + (not (match_code "subreg")))) + +;; True if this is a comparison operator, which accepts a normal 8-bit +;; signed immediate operand. +(define_predicate "normal_comparison_operator" + (match_code "eq,ne,gt,le,gtu,leu")) + +;; True if this is a comparison operator, which accepts an adjusted 8-bit +;; signed immediate operand. +(define_predicate "adjusted_comparison_operator" + (match_code "lt,ge,ltu,geu")) + +;; True if this is a signed inequality operator. +(define_predicate "signed_inequality_operator" + (match_code "ge,gt,le,lt")) + +;; True if this operator is valid for predication. +(define_predicate "predicate_operator" + (match_code "eq,ne")) + +;; True if this operator can be used in a conditional operation. +(define_predicate "condop_operator" + (match_code "plus,minus,ior,xor,and")) + +;; These three are hardware registers that can only be addressed in +;; DImode. It's not strictly necessary to test mode == DImode here, +;; but it makes decent insurance against someone writing a +;; match_operand wrong. + +;; True if this is the ar.lc register. +(define_predicate "ar_lc_reg_operand" + (and (match_code "reg") + (match_test "mode == DImode && REGNO (op) == AR_LC_REGNUM"))) + +;; True if this is the ar.ccv register. +(define_predicate "ar_ccv_reg_operand" + (and (match_code "reg") + (match_test "mode == DImode && REGNO (op) == AR_CCV_REGNUM"))) + +;; True if this is the ar.pfs register. +(define_predicate "ar_pfs_reg_operand" + (and (match_code "reg") + (match_test "mode == DImode && REGNO (op) == AR_PFS_REGNUM"))) + +;; True if OP is valid as a base register in a reg + offset address. +;; ??? Should I copy the flag_omit_frame_pointer and cse_not_expected +;; checks from pa.c basereg_operand as well? Seems to be OK without them +;; in test runs. +(define_predicate "basereg_operand" + (match_operand 0 "register_operand") +{ + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + return REG_POINTER (op); +}) + + +;; :::::::::::::::::::: +;; :: ;; :: Attributes ;; :: ;; :::::::::::::::::::: |