aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog65
-rw-r--r--gcc/config/s390/constraints.md43
-rw-r--r--gcc/config/s390/predicates.md16
-rw-r--r--gcc/config/s390/s390-protos.h10
-rw-r--r--gcc/config/s390/s390.c375
-rw-r--r--gcc/config/s390/s390.h32
-rw-r--r--gcc/config/s390/s390.md769
7 files changed, 1119 insertions, 191 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a538ccd..a64b0b0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,70 @@
2008-05-28 Andreas Krebbel <krebbel1@de.ibm.com>
+ * config/s390/constraints.md ('b', 'C', 'D', 'e'): New constraint
+ letters defined.
+
+ * config/s390/s390.c (s390_compare_and_branch_condition_mask,
+ s390_contiguous_bitmask_p, s390_symref_operand_p,
+ s390_check_symref_alignment, s390_reload_larl_operand,
+ s390_reload_symref_address): New functions.
+ (s390_branch_condition_mnemonic): Support compare and branch
+ instructions.
+ (s390_mem_constraint): Avoid symrefs to accepted by the 'T'
+ and 'W' constraints.
+ (s390_secondary_reload): Add secondary reloads for unaligned
+ symbol refs or symbol refs to floating point or QI/TI mode
+ integer values.
+ (legitimate_address_p): Accept symbol references as addresses.
+ (s390_expand_insv): Use rotate and insert selected bits
+ instruction for insv when building for z10.
+ (print_operand_address): Handle symbol ref addresses.
+ (print_operand): Output modifier 'c' added for signed byte
+ values.
+ (s390_encode_section_info): Mark symbol refs with
+ SYMBOL_FLAG_NOT_NATURALLY_ALIGNED if appropriate.
+
+ * config/s390/s390.md (SIL,RRS,RIS): New instruction formats added.
+ (length attribute): RRF, RRR have 4 byte length.
+ (FPALL, INTALL): New mode iterators added.
+ (*tstdi_sign, *cmpdi_ccs_sign, *cmpsi_ccs_sign,
+ *cmp<mode>_ccs, *cmpdi_ccu_zero, *cmpdi_ccu, *cmpsi_ccu, *cmphi_ccu,
+ *movdi_64, *movsi_zarch, *movhi, movmem<mode>, *movmem_short,
+ *extendsidi2, *extendhidi2_extimm, *extendhisi2_extimm,
+ *zero_extendsidi2, adddi3, *adddi3_31z, *adddi3_31, addsi3,
+ *add<mode>3, *add<mode>3_carry1_cc, *add<mode>3_carry2_cc,
+ *add<mode>3_cc, *add<mode>3_imm_cc, *muldi3_sign, muldi3,
+ *mulsi3_sign, mulsi3, mulsidi3): Patterns enhanced with z10
+ instructions.
+ (*cmphi_ccs_z10, *cmpdi_ccs_signhi_rl, *cmpsi_ccu_zerohi_rlsi,
+ *cmp<GPR:mode>_ccu_zerohi_rldi, *cmp_and_br_signed_<mode>,
+ *cmp_and_br_unsigned_<mode>, reload<INTALL:mode><P:mode>_tomem_z10,
+ reload<INTALL:mode><P:mode>_toreg_z10,
+ reload<FPALL:mode><P:mode>_tomem_z10,
+ reload<FPALL:mode><P:mode>_toreg_z10,
+ reload<P:mode>_larl_odd_addend_z10, *execute_rl, *insv<mode>_z10,
+ *insv<mode>_z10_noshift, *insv<mode>_or_z10_noshift,
+ *zero_extendhi<mode>2_z10, *cmp_and_trap_signed_int<mode>,
+ *cmp_and_trap_unsigned_int<mode>, prefetch): New pattern or expander
+ definition.
+ (movmem, clrmem, cmpmem): New splitters added.
+
+ * config/s390/predicates.md (larl_operand): Use
+ SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1 replaced with
+ SYMBOL_REF_ALIGN1_P.
+ (s390_signed_integer_comparison,
+ s390_unsigned_integer_comparison): New predicates.
+
+ * config/s390/s390-protos.h (s390_check_symref_alignment,
+ s390_contiguous_bitmask_p, s390_reload_larl_operand,
+ s390_reload_symref_address,
+ s390_compare_and_branch_condition_mask): Prototypes added.
+
+ * config/s390/s390.h (TARGET_MEM_CONSTRAINT,
+ SYMBOL_REF_ALIGN1_P, SYMBOL_FLAG_NOT_NATURALLY_ALIGNED,
+ SYMBOL_REF_NOT_NATURALLY_ALIGNED_P): Macro definition added.
+
+2008-05-28 Andreas Krebbel <krebbel1@de.ibm.com>
+
* config/s390/s390.c (z10_cost): New cost function for z10.
(s390_handle_arch_option, override_options): Support
-march=z10 switch.
diff --git a/gcc/config/s390/constraints.md b/gcc/config/s390/constraints.md
index 92fd325..ad95308 100644
--- a/gcc/config/s390/constraints.md
+++ b/gcc/config/s390/constraints.md
@@ -1,5 +1,5 @@
;; Constraints definitions belonging to the gcc backend for IBM S/390.
-;; Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
;; Written by Wolfgang Gellerich, using code and information found in
;; files s390.md, s390.h, and s390.c.
;;
@@ -24,10 +24,14 @@
;; Special constraints for s/390 machine description:
;;
;; a -- Any address register from 1 to 15.
+;; b -- Memory operand whose address is a symbol reference or a symbol
+;; reference + constant which can be proven to be naturally aligned.
;; c -- Condition code register 33.
;; d -- Any register from 0 to 15.
;; f -- Floating point registers.
;; t -- Access registers 36 and 37.
+;; C -- A signed 8-bit constant (-128..127)
+;; D -- An unsigned 16-bit constant (0..65535)
;; G -- Const double zero operand
;; I -- An 8-bit constant (0..255).
;; J -- A 12-bit constant (0..4095).
@@ -102,6 +106,19 @@
;; General constraints for constants.
;;
+(define_constraint "C"
+ "@internal
+ An 8-bit signed immediate constant (-128..127)"
+ (and (match_code "const_int")
+ (match_test "ival >= -128 && ival <= 127")))
+
+
+(define_constraint "D"
+ "An unsigned 16-bit constant (0..65535)"
+ (and (match_code "const_int")
+ (match_test "ival >= 0 && ival <= 65535")))
+
+
(define_constraint "G"
"@internal
Const double zero operand"
@@ -127,7 +144,6 @@
(match_test "ival >= -32768 && ival <= 32767")))
-
(define_constraint "L"
"Value appropriate as displacement.
(0..4095) for short displacement
@@ -355,7 +371,6 @@
(match_test "s390_mem_constraint (\"Q\", op)"))
-
(define_memory_constraint "R"
"Memory reference with index register and short displacement"
(match_test "s390_mem_constraint (\"R\", op)"))
@@ -371,6 +386,27 @@
(match_test "s390_mem_constraint (\"T\", op)"))
+(define_memory_constraint "b"
+ "Memory reference whose address is a naturally aligned symbol reference."
+ (match_test "MEM_P (op)
+ && s390_check_symref_alignment (XEXP (op, 0),
+ GET_MODE_SIZE (GET_MODE (op)))"))
+
+(define_memory_constraint "e"
+ "Matches all memory references available on the current architecture
+level. This constraint will never be used and using it in an inline
+assembly is *always* a bug since there is no instruction accepting all
+those addresses. It just serves as a placeholder for a generic memory
+constraint."
+ (match_test "legitimate_address_p (GET_MODE (op), op, 1)"))
+
+; This defines 'm' as normal memory constraint. This is only possible
+; since the standard memory constraint is re-defined in s390.h using
+; the TARGET_MEM_CONSTRAINT macro.
+(define_memory_constraint "m"
+ "Matches the most general memory address for pre-z10 machines."
+ (match_test "s390_mem_constraint (\"R\", op)
+ || s390_mem_constraint (\"T\", op)"))
(define_memory_constraint "AQ"
"@internal
@@ -425,7 +461,6 @@
(match_test "s390_mem_constraint (\"BT\", op)"))
-
(define_address_constraint "U"
"Pointer with short displacement"
(match_test "s390_mem_constraint (\"U\", op)"))
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index 50bf0c1..ca5d175 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -1,5 +1,5 @@
;; Predicate definitions for S/390 and zSeries.
-;; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
;; Ulrich Weigand (uweigand@de.ibm.com).
;;
@@ -110,7 +110,7 @@
if (GET_CODE (op) == LABEL_REF)
return true;
if (GET_CODE (op) == SYMBOL_REF)
- return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
+ return (!SYMBOL_REF_ALIGN1_P (op)
&& SYMBOL_REF_TLS_MODEL (op) == 0
&& (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
@@ -172,6 +172,18 @@
return (s390_branch_condition_mask (op) >= 0);
})
+(define_predicate "s390_signed_integer_comparison"
+ (match_code "eq, ne, lt, gt, le, ge")
+{
+ return (s390_compare_and_branch_condition_mask (op) >= 0);
+})
+
+(define_predicate "s390_unsigned_integer_comparison"
+ (match_code "eq, ne, ltu, gtu, leu, geu")
+{
+ return (s390_compare_and_branch_condition_mask (op) >= 0);
+})
+
;; Return nonzero if OP is a valid comparison operator
;; for an ALC condition.
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 7e329f2..76f73f9 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -1,5 +1,7 @@
/* Definitions of target machine for GNU compiler, for IBM S/390.
- Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008 Free
+ Software Foundation, Inc.
+
Contributed by Hartmut Penner (hpenner@de.ibm.com)
This file is part of GCC.
@@ -27,7 +29,7 @@ extern int s390_mem_constraint (const char *str, rtx op);
extern int s390_O_constraint_str (const char c, HOST_WIDE_INT value);
extern int s390_N_constraint_str (const char *str, HOST_WIDE_INT value);
extern int s390_float_const_zero_p (rtx value);
-
+extern bool s390_check_symref_alignment (rtx addr, HOST_WIDE_INT alignment);
/* Declare functions in s390.c. */
@@ -51,6 +53,7 @@ extern int s390_const_ok_for_constraint_p (HOST_WIDE_INT, int, const char *);
extern int s390_const_double_ok_for_constraint_p (rtx, int, const char *);
extern int s390_single_part (rtx, enum machine_mode, enum machine_mode, int);
extern unsigned HOST_WIDE_INT s390_extract_part (rtx, enum machine_mode, int);
+extern bool s390_contiguous_bitmask_p (unsigned HOST_WIDE_INT, int, int *, int *);
extern bool s390_split_ok_p (rtx, rtx, enum machine_mode, int);
extern bool s390_overlap_p (rtx, rtx, HOST_WIDE_INT);
extern bool s390_offset_p (rtx, rtx, rtx);
@@ -80,6 +83,8 @@ extern enum reg_class s390_secondary_input_reload_class (enum reg_class,
extern enum reg_class s390_secondary_output_reload_class (enum reg_class,
enum machine_mode,
rtx);
+extern void s390_reload_larl_operand (rtx , rtx , rtx);
+extern void s390_reload_symref_address (rtx , rtx , rtx , bool);
extern void s390_expand_plus_operand (rtx, rtx, rtx);
extern void emit_symbolic_move (rtx *);
extern void s390_load_address (rtx, rtx);
@@ -113,6 +118,7 @@ extern void s390_emit_tpf_eh_return (rtx);
extern bool s390_legitimate_address_without_index_p (rtx);
extern bool s390_decompose_shift_count (rtx, rtx *, HOST_WIDE_INT *);
extern int s390_branch_condition_mask (rtx);
+extern int s390_compare_and_branch_condition_mask (rtx);
#endif /* RTX_CODE */
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 37660a2..5ffbcae 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -1,8 +1,9 @@
/* Subroutines used for code generation on IBM S/390 and zSeries
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007 Free Software Foundation, Inc.
+ 2007, 2008 Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com) and
- Ulrich Weigand (uweigand@de.ibm.com).
+ Ulrich Weigand (uweigand@de.ibm.com) and
+ Andreas Krebbel (Andreas.Krebbel@de.ibm.com).
This file is part of GCC.
@@ -1061,6 +1062,41 @@ s390_branch_condition_mask (rtx code)
}
}
+
+/* Return branch condition mask to implement a compare and branch
+ specified by CODE. Return -1 for invalid comparisons. */
+
+int
+s390_compare_and_branch_condition_mask (rtx code)
+{
+ const int CC0 = 1 << 3;
+ const int CC1 = 1 << 2;
+ const int CC2 = 1 << 1;
+
+ switch (GET_CODE (code))
+ {
+ case EQ:
+ return CC0;
+ case NE:
+ return CC1 | CC2;
+ case LT:
+ case LTU:
+ return CC1;
+ case GT:
+ case GTU:
+ return CC2;
+ case LE:
+ case LEU:
+ return CC0 | CC1;
+ case GE:
+ case GEU:
+ return CC0 | CC2;
+ default:
+ gcc_unreachable ();
+ }
+ return -1;
+}
+
/* If INV is false, return assembler mnemonic string to implement
a branch specified by CODE. If INV is true, return mnemonic
for the corresponding inverted branch. */
@@ -1068,6 +1104,8 @@ s390_branch_condition_mask (rtx code)
static const char *
s390_branch_condition_mnemonic (rtx code, int inv)
{
+ int mask;
+
static const char *const mnemonic[16] =
{
NULL, "o", "h", "nle",
@@ -1076,7 +1114,13 @@ s390_branch_condition_mnemonic (rtx code, int inv)
"le", "nh", "no", NULL
};
- int mask = s390_branch_condition_mask (code);
+ if (GET_CODE (XEXP (code, 0)) == REG
+ && REGNO (XEXP (code, 0)) == CC_REGNUM
+ && XEXP (code, 1) == const0_rtx)
+ mask = s390_branch_condition_mask (code);
+ else
+ mask = s390_compare_and_branch_condition_mask (code);
+
gcc_assert (mask >= 0);
if (inv)
@@ -1153,6 +1197,67 @@ s390_single_part (rtx op,
return part == -1 ? -1 : n_parts - 1 - part;
}
+/* Return true if IN contains a contiguous bitfield in the lower SIZE
+ bits and no other bits are set in IN. POS and LENGTH can be used
+ to obtain the start position and the length of the bitfield.
+
+ POS gives the position of the first bit of the bitfield counting
+ from the lowest order bit starting with zero. In order to use this
+ value for S/390 instructions this has to be converted to "bits big
+ endian" style. */
+
+bool
+s390_contiguous_bitmask_p (unsigned HOST_WIDE_INT in, int size,
+ int *pos, int *length)
+{
+ int tmp_pos = 0;
+ int tmp_length = 0;
+ int i;
+ unsigned HOST_WIDE_INT mask = 1ULL;
+ bool contiguous = false;
+
+ for (i = 0; i < size; mask <<= 1, i++)
+ {
+ if (contiguous)
+ {
+ if (mask & in)
+ tmp_length++;
+ else
+ break;
+ }
+ else
+ {
+ if (mask & in)
+ {
+ contiguous = true;
+ tmp_length++;
+ }
+ else
+ tmp_pos++;
+ }
+ }
+
+ if (!tmp_length)
+ return false;
+
+ /* Calculate a mask for all bits beyond the contiguous bits. */
+ mask = (-1LL & ~(((1ULL << (tmp_length + tmp_pos - 1)) << 1) - 1));
+
+ if (mask & in)
+ return false;
+
+ if (tmp_length + tmp_pos - 1 > size)
+ return false;
+
+ if (length)
+ *length = tmp_length;
+
+ if (pos)
+ *pos = tmp_pos;
+
+ return true;
+}
+
/* Check whether we can (and want to) split a double-word
move in mode MODE from SRC to DST into two single-word
moves, moving the subword FIRST_SUBWORD first. */
@@ -2034,10 +2139,9 @@ s390_mem_constraint (const char *str, rtx op)
return 0;
if (GET_CODE (op) != MEM)
return 0;
- /* Any invalid address here will be fixed up by reload,
- so accept it for the most generic constraint. */
- if (s390_decompose_address (XEXP (op, 0), &addr)
- && s390_short_displacement (addr.disp))
+ if (!s390_decompose_address (XEXP (op, 0), &addr))
+ return 0;
+ if (s390_short_displacement (addr.disp))
return 0;
break;
@@ -2054,10 +2158,9 @@ s390_mem_constraint (const char *str, rtx op)
case 'W':
if (!TARGET_LONG_DISPLACEMENT)
return 0;
- /* Any invalid address here will be fixed up by reload,
- so accept it for the most generic constraint. */
- if (s390_decompose_address (op, &addr)
- && s390_short_displacement (addr.disp))
+ if (!s390_decompose_address (op, &addr))
+ return 0;
+ if (s390_short_displacement (addr.disp))
return 0;
break;
@@ -2693,6 +2796,132 @@ s390_preferred_reload_class (rtx op, enum reg_class class)
return class;
}
+/* Return true if ADDR is of kind symbol_ref or symbol_ref + const_int
+ and return these parts in SYMREF and ADDEND. You can pass NULL in
+ SYMREF and/or ADDEND if you are not interested in these values. */
+
+static bool
+s390_symref_operand_p (rtx addr, rtx *symref, HOST_WIDE_INT *addend)
+{
+ HOST_WIDE_INT tmpaddend = 0;
+
+ if (GET_CODE (addr) == CONST)
+ addr = XEXP (addr, 0);
+
+ if (GET_CODE (addr) == PLUS)
+ {
+ if (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
+ && CONST_INT_P (XEXP (addr, 1)))
+ {
+ tmpaddend = INTVAL (XEXP (addr, 1));
+ addr = XEXP (addr, 0);
+ }
+ else
+ return false;
+ }
+ else
+ if (GET_CODE (addr) != SYMBOL_REF)
+ return false;
+
+ if (symref)
+ *symref = addr;
+ if (addend)
+ *addend = tmpaddend;
+
+ return true;
+}
+
+/* Return true if ADDR is SYMBOL_REF + addend with addend being a
+ multiple of ALIGNMENT and the SYMBOL_REF being naturally
+ aligned. */
+
+bool
+s390_check_symref_alignment (rtx addr, HOST_WIDE_INT alignment)
+{
+ HOST_WIDE_INT addend;
+ rtx symref;
+
+ if (!s390_symref_operand_p (addr, &symref, &addend))
+ return false;
+
+ return (!SYMBOL_REF_NOT_NATURALLY_ALIGNED_P (symref)
+ && !(addend & (alignment - 1)));
+}
+
+/* ADDR is moved into REG using larl. If ADDR isn't a valid larl
+ operand SCRATCH is used to reload the even part of the address and
+ adding one. */
+
+void
+s390_reload_larl_operand (rtx reg, rtx addr, rtx scratch)
+{
+ HOST_WIDE_INT addend;
+ rtx symref;
+
+ if (!s390_symref_operand_p (addr, &symref, &addend))
+ gcc_unreachable ();
+
+ if (!(addend & 1))
+ /* Easy case. The addend is even so larl will do fine. */
+ emit_move_insn (reg, addr);
+ else
+ {
+ /* We can leave the scratch register untouched if the target
+ register is a valid base register. */
+ if (REGNO (reg) < FIRST_PSEUDO_REGISTER
+ && REGNO_REG_CLASS (REGNO (reg)) == ADDR_REGS)
+ scratch = reg;
+
+ gcc_assert (REGNO (scratch) < FIRST_PSEUDO_REGISTER);
+ gcc_assert (REGNO_REG_CLASS (REGNO (scratch)) == ADDR_REGS);
+
+ if (addend != 1)
+ emit_move_insn (scratch,
+ gen_rtx_CONST (Pmode,
+ gen_rtx_PLUS (Pmode, symref,
+ GEN_INT (addend - 1))));
+ else
+ emit_move_insn (scratch, symref);
+
+ /* Increment the address using la in order to avoid clobbering cc. */
+ emit_move_insn (reg, gen_rtx_PLUS (Pmode, scratch, const1_rtx));
+ }
+}
+
+/* Generate what is necessary to move between REG and MEM using
+ SCRATCH. The direction is given by TOMEM. */
+
+void
+s390_reload_symref_address (rtx reg, rtx mem, rtx scratch, bool tomem)
+{
+ /* Reload might have pulled a constant out of the literal pool.
+ Force it back in. */
+ if (CONST_INT_P (mem) || GET_CODE (mem) == CONST_DOUBLE
+ || GET_CODE (mem) == CONST)
+ mem = force_const_mem (GET_MODE (reg), mem);
+
+ gcc_assert (MEM_P (mem));
+
+ /* For a load from memory we can leave the scratch register
+ untouched if the target register is a valid base register. */
+ if (!tomem
+ && REGNO (reg) < FIRST_PSEUDO_REGISTER
+ && REGNO_REG_CLASS (REGNO (reg)) == ADDR_REGS
+ && GET_MODE (reg) == GET_MODE (scratch))
+ scratch = reg;
+
+ /* Load address into scratch register. Since we can't have a
+ secondary reload for a secondary reload we have to cover the case
+ where larl would need a secondary reload here as well. */
+ s390_reload_larl_operand (scratch, XEXP (mem, 0), scratch);
+
+ /* Now we can use a standard load/store to do the move. */
+ if (tomem)
+ emit_move_insn (replace_equiv_address (mem, scratch), reg);
+ else
+ emit_move_insn (reg, replace_equiv_address (mem, scratch));
+}
+
/* Inform reload about cases where moving X with a mode MODE to a register in
CLASS requires an extra scratch or immediate register. Return the class
needed for the immediate register. */
@@ -2705,6 +2934,60 @@ s390_secondary_reload (bool in_p, rtx x, enum reg_class class,
if (reg_classes_intersect_p (CC_REGS, class))
return GENERAL_REGS;
+ if (TARGET_Z10)
+ {
+ /* On z10 several optimizer steps may generate larl operands with
+ an odd addend. */
+ if (in_p
+ && s390_symref_operand_p (x, NULL, NULL)
+ && mode == Pmode
+ && !s390_check_symref_alignment (x, 2))
+ sri->icode = ((mode == DImode) ? CODE_FOR_reloaddi_larl_odd_addend_z10
+ : CODE_FOR_reloadsi_larl_odd_addend_z10);
+
+ /* On z10 we need a scratch register when moving QI, TI or floating
+ point mode values from or to a memory location with a SYMBOL_REF
+ or if the symref addend of a SI or DI move is not aligned to the
+ width of the access. */
+ if (MEM_P (x)
+ && s390_symref_operand_p (XEXP (x, 0), NULL, NULL)
+ && (mode == QImode || mode == TImode || FLOAT_MODE_P (mode)
+ || (!TARGET_64BIT && mode == DImode)
+ || ((mode == HImode || mode == SImode || mode == DImode)
+ && (!s390_check_symref_alignment (XEXP (x, 0),
+ GET_MODE_SIZE (mode))))))
+ {
+#define __SECONDARY_RELOAD_CASE(M,m) \
+ case M##mode: \
+ if (TARGET_64BIT) \
+ sri->icode = in_p ? CODE_FOR_reload##m##di_toreg_z10 : \
+ CODE_FOR_reload##m##di_tomem_z10; \
+ else \
+ sri->icode = in_p ? CODE_FOR_reload##m##si_toreg_z10 : \
+ CODE_FOR_reload##m##si_tomem_z10; \
+ break;
+
+ switch (GET_MODE (x))
+ {
+ __SECONDARY_RELOAD_CASE (QI, qi);
+ __SECONDARY_RELOAD_CASE (HI, hi);
+ __SECONDARY_RELOAD_CASE (SI, si);
+ __SECONDARY_RELOAD_CASE (DI, di);
+ __SECONDARY_RELOAD_CASE (TI, ti);
+ __SECONDARY_RELOAD_CASE (SF, sf);
+ __SECONDARY_RELOAD_CASE (DF, df);
+ __SECONDARY_RELOAD_CASE (TF, tf);
+ __SECONDARY_RELOAD_CASE (SD, sd);
+ __SECONDARY_RELOAD_CASE (DD, dd);
+ __SECONDARY_RELOAD_CASE (TD, td);
+
+ default:
+ gcc_unreachable ();
+ }
+#undef __SECONDARY_RELOAD_CASE
+ }
+ }
+
/* We need a scratch register when loading a PLUS expression which
is not a legitimate operand of the LOAD ADDRESS instruction. */
if (in_p && s390_plus_operand (x, mode))
@@ -2811,10 +3094,16 @@ s390_expand_plus_operand (rtx target, rtx src,
STRICT specifies whether strict register checking applies. */
bool
-legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
- rtx addr, int strict)
+legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
{
struct s390_address ad;
+
+ if (TARGET_Z10
+ && larl_operand (addr, VOIDmode)
+ && (mode == VOIDmode
+ || s390_check_symref_alignment (addr, GET_MODE_SIZE (mode))))
+ return true;
+
if (!s390_decompose_address (addr, &ad))
return false;
@@ -4052,14 +4341,31 @@ s390_expand_addcc (enum rtx_code cmp_code, rtx cmp_op0, rtx cmp_op1,
return false;
}
-/* Expand code for the insv template. Return true if successful, false else. */
+/* Expand code for the insv template. Return true if successful. */
-bool
+bool
s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
{
int bitsize = INTVAL (op1);
int bitpos = INTVAL (op2);
+ /* On z10 we can use the risbg instruction to implement insv. */
+ if (TARGET_Z10
+ && ((GET_MODE (dest) == DImode && GET_MODE (src) == DImode)
+ || (GET_MODE (dest) == SImode && GET_MODE (src) == SImode)))
+ {
+ rtx op;
+ rtx clobber;
+
+ op = gen_rtx_SET (GET_MODE(src),
+ gen_rtx_ZERO_EXTRACT (GET_MODE (dest), dest, op1, op2),
+ src);
+ clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clobber)));
+
+ return true;
+ }
+
/* We need byte alignment. */
if (bitsize % BITS_PER_UNIT)
return false;
@@ -4596,6 +4902,13 @@ print_operand_address (FILE *file, rtx addr)
{
struct s390_address ad;
+ if (s390_symref_operand_p (addr, NULL, NULL))
+ {
+ gcc_assert (TARGET_Z10);
+ output_addr_const (file, addr);
+ return;
+ }
+
if (!s390_decompose_address (addr, &ad)
|| (ad.base && !REGNO_OK_FOR_BASE_P (REGNO (ad.base)))
|| (ad.indx && !REGNO_OK_FOR_INDEX_P (REGNO (ad.indx))))
@@ -4629,6 +4942,7 @@ print_operand_address (FILE *file, rtx addr)
'Y': print shift count operand.
'b': print integer X as if it's an unsigned byte.
+ 'c': print integer X as if it's an signed byte.
'x': print integer X as if it's an unsigned halfword.
'h': print integer X as if it's a signed halfword.
'i': print the first nonzero HImode part of X.
@@ -4774,6 +5088,8 @@ print_operand (FILE *file, rtx x, int code)
case CONST_INT:
if (code == 'b')
fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xff);
+ else if (code == 'c')
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((INTVAL (x) & 0xff) ^ 0x80) - 0x80);
else if (code == 'x')
fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xffff);
else if (code == 'h')
@@ -8563,11 +8879,30 @@ s390_encode_section_info (tree decl, rtx rtl, int first)
{
default_encode_section_info (decl, rtl, first);
- /* If a variable has a forced alignment to < 2 bytes, mark it with
- SYMBOL_FLAG_ALIGN1 to prevent it from being used as LARL operand. */
- if (TREE_CODE (decl) == VAR_DECL
- && DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) < 16)
- SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_ALIGN1;
+ if (TREE_CODE (decl) == VAR_DECL)
+ {
+ /* If a variable has a forced alignment to < 2 bytes, mark it
+ with SYMBOL_FLAG_ALIGN1 to prevent it from being used as LARL
+ operand. */
+ if (DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) < 16)
+ SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_ALIGN1;
+ if (!DECL_SIZE (decl)
+ || !DECL_ALIGN (decl)
+ || !host_integerp (DECL_SIZE (decl), 0)
+ || (DECL_ALIGN (decl) <= 64
+ && DECL_ALIGN (decl) != tree_low_cst (DECL_SIZE (decl), 0)))
+ SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_NOT_NATURALLY_ALIGNED;
+ }
+
+ /* Literal pool references don't have a decl so they are handled
+ differently here. We rely on the information in the MEM_ALIGN
+ entry to decide upon natural alignment. */
+ if (MEM_P (rtl)
+ && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF
+ && TREE_CONSTANT_POOL_ADDRESS_P (XEXP (rtl, 0))
+ && (MEM_ALIGN (rtl) == 0
+ || MEM_ALIGN (rtl) < GET_MODE_BITSIZE (GET_MODE (rtl))))
+ SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_NOT_NATURALLY_ALIGNED;
}
/* Output thunk to FILE that implements a C++ virtual function call (with
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index 819154f..79286d5a 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -1,8 +1,9 @@
/* Definitions of target machine for GNU compiler, for IBM S/390
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007 Free Software Foundation, Inc.
+ 2007, 2008 Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com) and
Ulrich Weigand (uweigand@de.ibm.com).
+ Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
This file is part of GCC.
@@ -62,6 +63,10 @@ extern enum processor_flags s390_tune_flags;
extern enum processor_type s390_arch;
extern enum processor_flags s390_arch_flags;
+/* These flags indicate that the generated code should run on a cpu
+ providing the respective hardware facility regardless of the
+ current cpu mode (ESA or z/Architecture). */
+
#define TARGET_CPU_IEEE_FLOAT \
(s390_arch_flags & PF_IEEE_FLOAT)
#define TARGET_CPU_ZARCH \
@@ -75,6 +80,10 @@ extern enum processor_flags s390_arch_flags;
#define TARGET_CPU_Z10 \
(s390_arch_flags & PF_Z10)
+/* These flags indicate that the generated code should run on a cpu
+ providing the respective hardware facility when run in
+ z/Architecture mode. */
+
#define TARGET_LONG_DISPLACEMENT \
(TARGET_ZARCH && TARGET_CPU_LONG_DISPLACEMENT)
#define TARGET_EXTIMM \
@@ -491,11 +500,14 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
#define PREFERRED_RELOAD_CLASS(X, CLASS) \
s390_preferred_reload_class ((X), (CLASS))
-/* We need secondary memory to move data between GPRs and FPRs. */
+/* We need secondary memory to move data between GPRs and FPRs. With
+ DFP the ldgr lgdr instructions are available. But these
+ instructions do not handle GPR pairs so it is not possible for 31
+ bit. */
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
((CLASS1) != (CLASS2) \
&& ((CLASS1) == FP_REGS || (CLASS2) == FP_REGS) \
- && (!TARGET_DFP || GET_MODE_SIZE (MODE) != 8))
+ && (!TARGET_DFP || !TARGET_64BIT || GET_MODE_SIZE (MODE) != 8))
/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on 64bit
because the movsi and movsf patterns don't handle r/f moves. */
@@ -693,6 +705,13 @@ CUMULATIVE_ARGS;
/* Maximum number of registers that can appear in a valid memory address. */
#define MAX_REGS_PER_ADDRESS 2
+/* This definition replaces the formerly used 'm' constraint with a
+different constraint letter in order to avoid changing semantics of
+the 'm' constraint when accepting new address formats in
+legitimate_address_p. The constraint letter defined here must not be
+used in insn definitions or inline assemblies. */
+#define TARGET_MEM_CONSTRAINT 'e'
+
/* S/390 has no mode dependent addresses. */
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
@@ -959,7 +978,12 @@ do { \
#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 64, 1)
/* Machine-specific symbol_ref flags. */
-#define SYMBOL_FLAG_ALIGN1 (SYMBOL_FLAG_MACH_DEP << 0)
+#define SYMBOL_FLAG_ALIGN1 (SYMBOL_FLAG_MACH_DEP << 0)
+#define SYMBOL_REF_ALIGN1_P(X) \
+ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_ALIGN1))
+#define SYMBOL_FLAG_NOT_NATURALLY_ALIGNED (SYMBOL_FLAG_MACH_DEP << 1)
+#define SYMBOL_REF_NOT_NATURALLY_ALIGNED_P(X) \
+ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_NOT_NATURALLY_ALIGNED))
/* Check whether integer displacement is in range. */
#define DISP_IN_RANGE(d) \
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 54f4e0e..f97e756 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -1,8 +1,9 @@
;;- Machine description for GNU compiler -- S/390 / zSeries version.
-;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
;; Free Software Foundation, Inc.
;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
-;; Ulrich Weigand (uweigand@de.ibm.com).
+;; Ulrich Weigand (uweigand@de.ibm.com) and
+;; Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
;; This file is part of GCC.
@@ -38,6 +39,7 @@
;; %Y: print shift count operand.
;;
;; %b: print integer X as if it's an unsigned byte.
+;; %c: print integer X as if it's an signed byte.
;; %x: print integer X as if it's an unsigned halfword.
;; %h: print integer X as if it's a signed halfword.
;; %i: print the first nonzero HImode part of X.
@@ -189,7 +191,7 @@
;; Used to determine defaults for length and other attribute values.
(define_attr "op_type"
- "NN,E,RR,RRE,RX,RS,RSI,RI,SI,S,SS,SSE,RXE,RSE,RIL,RIE,RXY,RSY,SIY,RRF,RRR"
+ "NN,E,RR,RRE,RX,RS,RSI,RI,SI,S,SS,SSE,RXE,RSE,RIL,RIE,RXY,RSY,SIY,RRF,RRR,SIL,RRS,RIS"
(const_string "NN"))
;; Instruction type attribute used for scheduling.
@@ -218,8 +220,8 @@
;; Length in bytes.
(define_attr "length" ""
- (cond [(eq_attr "op_type" "E,RR") (const_int 2)
- (eq_attr "op_type" "RX,RI,RRE,RS,RSI,S,SI") (const_int 4)]
+ (cond [(eq_attr "op_type" "E,RR") (const_int 2)
+ (eq_attr "op_type" "RX,RI,RRE,RS,RSI,S,SI,RRF,RRR") (const_int 4)]
(const_int 6)))
@@ -286,6 +288,7 @@
(define_mode_iterator FP_ALL [TF DF SF (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")
(SD "TARGET_HARD_DFP")])
(define_mode_iterator FP [TF DF SF (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")])
+(define_mode_iterator FPALL [TF DF SF TD DD SD])
(define_mode_iterator BFP [TF DF SF])
(define_mode_iterator DFP [TD DD])
(define_mode_iterator DFP_ALL [TD DD SD])
@@ -315,6 +318,7 @@
;; This mode iterator allows the integer patterns to be defined from the
;; same template.
(define_mode_iterator INT [(DI "TARGET_64BIT") SI HI QI])
+(define_mode_iterator INTALL [TI DI SI HI QI])
;; This iterator allows to unify all 'bCOND' expander patterns.
(define_code_iterator COMPARE [eq ne gt gtu lt ltu ge geu le leu unordered
@@ -457,7 +461,6 @@
;; Maximum unsigned integer that fits in MODE.
(define_mode_attr max_uint [(HI "65535") (QI "255")])
-
;;
;;- Compare instructions.
;;
@@ -543,14 +546,19 @@
(define_insn "*tstdi_sign"
[(set (reg CC_REGNUM)
- (compare (ashiftrt:DI (ashift:DI (subreg:DI (match_operand:SI 0 "register_operand" "d") 0)
- (const_int 32)) (const_int 32))
- (match_operand:DI 1 "const0_operand" "")))
- (set (match_operand:DI 2 "register_operand" "=d")
+ (compare
+ (ashiftrt:DI
+ (ashift:DI
+ (subreg:DI (match_operand:SI 0 "nonimmediate_operand" "d,RT") 0)
+ (const_int 32)) (const_int 32))
+ (match_operand:DI 1 "const0_operand" "")))
+ (set (match_operand:DI 2 "register_operand" "=d,d")
(sign_extend:DI (match_dup 0)))]
"s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
- "ltgfr\t%2,%0"
- [(set_attr "op_type" "RRE")])
+ "ltgfr\t%2,%0
+ ltgf\t%2,%0"
+ [(set_attr "op_type" "RRE,RXY")
+ (set_attr "cpu_facility" "*,z10")])
; ltr, lt, ltgr, ltg
(define_insn "*tst<mode>_extimm"
@@ -726,90 +734,159 @@
(define_insn "*cmpdi_ccs_sign"
[(set (reg CC_REGNUM)
- (compare (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT"))
- (match_operand:DI 0 "register_operand" "d,d")))]
+ (compare (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand"
+ "d,RT,b"))
+ (match_operand:DI 0 "register_operand" "d, d,d")))]
"s390_match_ccmode(insn, CCSRmode) && TARGET_64BIT"
"@
cgfr\t%0,%1
- cgf\t%0,%1"
- [(set_attr "op_type" "RRE,RXY")])
+ cgf\t%0,%1
+ cgfrl\t%0,%1"
+ [(set_attr "op_type" "RRE,RXY,RIL")
+ (set_attr "cpu_facility" "*,*,z10")
+ (set_attr "type" "*,*,larl")])
(define_insn "*cmpsi_ccs_sign"
[(set (reg CC_REGNUM)
- (compare (sign_extend:SI (match_operand:HI 1 "memory_operand" "R,T"))
- (match_operand:SI 0 "register_operand" "d,d")))]
+ (compare (sign_extend:SI (match_operand:HI 1 "memory_operand" "R,T,b"))
+ (match_operand:SI 0 "register_operand" "d,d,d")))]
"s390_match_ccmode(insn, CCSRmode)"
"@
ch\t%0,%1
- chy\t%0,%1"
- [(set_attr "op_type" "RX,RXY")])
+ chy\t%0,%1
+ chrl\t%0,%1"
+ [(set_attr "op_type" "RX,RXY,RIL")
+ (set_attr "cpu_facility" "*,*,z10")
+ (set_attr "type" "*,*,larl")])
+
+(define_insn "*cmphi_ccs_z10"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:HI 0 "s_operand" "Q")
+ (match_operand:HI 1 "immediate_operand" "K")))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_Z10"
+ "chhsi\t%0,%1"
+ [(set_attr "op_type" "SIL")])
+
+(define_insn "*cmpdi_ccs_signhi_rl"
+ [(set (reg CC_REGNUM)
+ (compare (sign_extend:DI (match_operand:HI 1 "memory_operand" "RT,b"))
+ (match_operand:GPR 0 "register_operand" "d,d")))]
+ "s390_match_ccmode(insn, CCSRmode) && TARGET_Z10"
+ "@
+ cgh\t%0,%1
+ cghrl\t%0,%1"
+ [(set_attr "op_type" "RXY,RIL")
+ (set_attr "type" "*,larl")])
-; cr, chi, cfi, c, cy, cgr, cghi, cgfi, cg
+; cr, chi, cfi, c, cy, cgr, cghi, cgfi, cg, chsi, cghsi, crl, cgrl
(define_insn "*cmp<mode>_ccs"
[(set (reg CC_REGNUM)
- (compare (match_operand:GPR 0 "register_operand" "d,d,d,d,d")
- (match_operand:GPR 1 "general_operand" "d,K,Os,R,T")))]
+ (compare (match_operand:GPR 0 "nonimmediate_operand"
+ "d,d,Q, d,d,d,d")
+ (match_operand:GPR 1 "general_operand"
+ "d,K,K,Os,R,T,b")))]
"s390_match_ccmode(insn, CCSmode)"
"@
c<g>r\t%0,%1
c<g>hi\t%0,%h1
+ c<g>hsi\t%0,%h1
c<g>fi\t%0,%1
c<g>\t%0,%1
- c<y>\t%0,%1"
- [(set_attr "op_type" "RR<E>,RI,RIL,RX<Y>,RXY")])
+ c<y>\t%0,%1
+ c<g>rl\t%0,%1"
+ [(set_attr "op_type" "RR<E>,RI,SIL,RIL,RX<Y>,RXY,RIL")
+ (set_attr "cpu_facility" "*,*,z10,extimm,*,*,z10")
+ (set_attr "type" "*,*,*,*,*,*,larl")])
; Compare (unsigned) instructions
+(define_insn "*cmpsi_ccu_zerohi_rlsi"
+ [(set (reg CC_REGNUM)
+ (compare (zero_extend:SI (mem:HI (match_operand:SI 1
+ "larl_operand" "X")))
+ (match_operand:SI 0 "register_operand" "d")))]
+ "s390_match_ccmode(insn, CCURmode) && TARGET_Z10"
+ "clhrl\t%0,%1"
+ [(set_attr "op_type" "RIL")
+ (set_attr "type" "larl")])
+
+; clhrl, clghrl
+(define_insn "*cmp<GPR:mode>_ccu_zerohi_rldi"
+ [(set (reg CC_REGNUM)
+ (compare (zero_extend:GPR (mem:HI (match_operand:DI 1
+ "larl_operand" "X")))
+ (match_operand:GPR 0 "register_operand" "d")))]
+ "s390_match_ccmode(insn, CCURmode) && TARGET_Z10"
+ "cl<g>hrl\t%0,%1"
+ [(set_attr "op_type" "RIL")
+ (set_attr "type" "larl")])
+
(define_insn "*cmpdi_ccu_zero"
[(set (reg CC_REGNUM)
- (compare (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT"))
- (match_operand:DI 0 "register_operand" "d,d")))]
+ (compare (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand"
+ "d,RT,b"))
+ (match_operand:DI 0 "register_operand" "d, d,d")))]
"s390_match_ccmode (insn, CCURmode) && TARGET_64BIT"
"@
clgfr\t%0,%1
- clgf\t%0,%1"
- [(set_attr "op_type" "RRE,RXY")])
+ clgf\t%0,%1
+ clgfrl\t%0,%1"
+ [(set_attr "op_type" "RRE,RXY,RIL")
+ (set_attr "cpu_facility" "*,*,z10")
+ (set_attr "type" "*,*,larl")])
(define_insn "*cmpdi_ccu"
[(set (reg CC_REGNUM)
- (compare (match_operand:DI 0 "nonimmediate_operand" "d,d,d,Q,BQ")
- (match_operand:DI 1 "general_operand" "d,Op,RT,BQ,Q")))]
+ (compare (match_operand:DI 0 "nonimmediate_operand"
+ "d, d,d,Q, d, Q,BQ")
+ (match_operand:DI 1 "general_operand"
+ "d,Op,b,D,RT,BQ,Q")))]
"s390_match_ccmode (insn, CCUmode) && TARGET_64BIT"
"@
clgr\t%0,%1
clgfi\t%0,%1
+ clgrl\t%0,%1
+ clghsi\t%0,%x1
clg\t%0,%1
#
#"
- [(set_attr "op_type" "RRE,RIL,RXY,SS,SS")])
+ [(set_attr "op_type" "RRE,RIL,RIL,SIL,RXY,SS,SS")
+ (set_attr "cpu_facility" "*,extimm,z10,z10,*,*,*")
+ (set_attr "type" "*,*,larl,*,*,*,*")])
(define_insn "*cmpsi_ccu"
[(set (reg CC_REGNUM)
- (compare (match_operand:SI 0 "nonimmediate_operand" "d,d,d,d,Q,BQ")
- (match_operand:SI 1 "general_operand" "d,Os,R,T,BQ,Q")))]
+ (compare (match_operand:SI 0 "nonimmediate_operand" "d, d,d,Q,d,d, Q,BQ")
+ (match_operand:SI 1 "general_operand" "d,Os,b,D,R,T,BQ, Q")))]
"s390_match_ccmode (insn, CCUmode)"
"@
clr\t%0,%1
clfi\t%0,%o1
+ clrl\t%0,%1
+ clfhsi\t%0,%x1
cl\t%0,%1
cly\t%0,%1
#
#"
- [(set_attr "op_type" "RR,RIL,RX,RXY,SS,SS")])
+ [(set_attr "op_type" "RR,RIL,RIL,SIL,RX,RXY,SS,SS")
+ (set_attr "cpu_facility" "*,extimm,z10,z10,*,*,*,*")
+ (set_attr "type" "*,*,larl,*,*,*,*,*")])
(define_insn "*cmphi_ccu"
[(set (reg CC_REGNUM)
- (compare (match_operand:HI 0 "nonimmediate_operand" "d,d,Q,BQ")
- (match_operand:HI 1 "general_operand" "Q,S,BQ,Q")))]
+ (compare (match_operand:HI 0 "nonimmediate_operand" "d,d,Q,Q,BQ")
+ (match_operand:HI 1 "general_operand" "Q,S,D,BQ,Q")))]
"s390_match_ccmode (insn, CCUmode)
&& !register_operand (operands[1], HImode)"
"@
clm\t%0,3,%S1
clmy\t%0,3,%S1
+ clhhsi\t%0,%1
#
#"
- [(set_attr "op_type" "RS,RSY,SS,SS")])
+ [(set_attr "op_type" "RS,RSY,SIL,SS,SS")
+ (set_attr "cpu_facility" "*,*,z10,*,*")])
(define_insn "*cmpqi_ccu"
[(set (reg CC_REGNUM)
@@ -885,6 +962,59 @@
[(set_attr "op_type" "RRE,RXE")
(set_attr "type" "fsimp<bfp>")])
+
+; Compare and Branch instructions
+
+; cij, cgij, crj, cgrj, cfi, cgfi, cr, cgr
+(define_insn "*cmp_and_br_signed_<mode>"
+ [(set (pc)
+ (if_then_else (match_operator 0 "s390_signed_integer_comparison"
+ [(match_operand:GPR 1 "register_operand" "d,d")
+ (match_operand:GPR 2 "nonmemory_operand" "d,C")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_Z10"
+{
+ if (get_attr_length (insn) == 6)
+ return which_alternative ?
+ "c<g>ij%C0\t%1,%c2,%l3" : "c<g>rj%C0\t%1,%2,%l3";
+ else
+ return which_alternative ?
+ "c<g>fi\t%1,%c2\;jg%C0\t%l3" : "c<g>r\t%1,%2\;jg%C0\t%l3";
+}
+ [(set_attr "op_type" "RIE")
+ (set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (pc) (match_dup 3))) (const_int 60000))
+ (const_int 6) (const_int 12)))]) ; 8 byte for cr/jg
+ ; 10 byte for cgr/jg
+
+; clij, clgij, clrj, clgrj, clfi, clgfi, clr, clgr
+(define_insn "*cmp_and_br_unsigned_<mode>"
+ [(set (pc)
+ (if_then_else (match_operator 0 "s390_unsigned_integer_comparison"
+ [(match_operand:GPR 1 "register_operand" "d,d")
+ (match_operand:GPR 2 "nonmemory_operand" "d,I")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_Z10"
+{
+ if (get_attr_length (insn) == 6)
+ return which_alternative ?
+ "cl<g>ij%C0\t%1,%b2,%l3" : "cl<g>rj%C0\t%1,%2,%l3";
+ else
+ return which_alternative ?
+ "cl<g>fi\t%1,%b2\;jg%C0\t%l3" : "cl<g>r\t%1,%2\;jg%C0\t%l3";
+}
+ [(set_attr "op_type" "RIE")
+ (set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (pc) (match_dup 3))) (const_int 60000))
+ (const_int 6) (const_int 12)))]) ; 8 byte for clr/jg
+ ; 10 byte for clgr/jg
+
;;
;;- Move instructions.
;;
@@ -951,6 +1081,60 @@
; Patterns used for secondary reloads
;
+; z10 provides move instructions accepting larl memory operands.
+; Unfortunately there is no such variant for QI, TI and FP mode moves.
+; These patterns are also used for unaligned SI and DI accesses.
+
+(define_expand "reload<INTALL:mode><P:mode>_tomem_z10"
+ [(parallel [(match_operand:INTALL 0 "memory_operand" "")
+ (match_operand:INTALL 1 "register_operand" "=d")
+ (match_operand:P 2 "register_operand" "=&a")])]
+ "TARGET_Z10"
+{
+ s390_reload_symref_address (operands[1], operands[0], operands[2], 1);
+ DONE;
+})
+
+(define_expand "reload<INTALL:mode><P:mode>_toreg_z10"
+ [(parallel [(match_operand:INTALL 0 "register_operand" "=d")
+ (match_operand:INTALL 1 "memory_operand" "")
+ (match_operand:P 2 "register_operand" "=a")])]
+ "TARGET_Z10"
+{
+ s390_reload_symref_address (operands[0], operands[1], operands[2], 0);
+ DONE;
+})
+
+(define_expand "reload<FPALL:mode><P:mode>_tomem_z10"
+ [(parallel [(match_operand:FPALL 0 "memory_operand" "")
+ (match_operand:FPALL 1 "register_operand" "=d")
+ (match_operand:P 2 "register_operand" "=&a")])]
+ "TARGET_Z10"
+{
+ s390_reload_symref_address (operands[1], operands[0], operands[2], 1);
+ DONE;
+})
+
+(define_expand "reload<FPALL:mode><P:mode>_toreg_z10"
+ [(parallel [(match_operand:FPALL 0 "register_operand" "=d")
+ (match_operand:FPALL 1 "memory_operand" "")
+ (match_operand:P 2 "register_operand" "=a")])]
+ "TARGET_Z10"
+{
+ s390_reload_symref_address (operands[0], operands[1], operands[2], 0);
+ DONE;
+})
+
+(define_expand "reload<P:mode>_larl_odd_addend_z10"
+ [(parallel [(match_operand:P 0 "register_operand" "=d")
+ (match_operand:P 1 "larl_operand" "")
+ (match_operand:P 2 "register_operand" "=a")])]
+ "TARGET_Z10"
+{
+ s390_reload_larl_operand (operands[0], operands[1], operands[2]);
+ DONE;
+})
+
; Handles loading a PLUS (load address) expression
(define_expand "reload<mode>_plus"
@@ -1020,11 +1204,11 @@
(define_insn "*movdi_64"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=d,d,d,d,d,d,d,d,f,d,d,d,d,
- RT,!*f,!*f,!*f,!R,!T,d,t,Q,t,?Q")
+ "=d,d,d,d,d,d,d,d,f,d,d,d,d,d,
+ RT,!*f,!*f,!*f,!R,!T,b,Q,d,t,Q,t,?Q")
(match_operand:DI 1 "general_operand"
- "K,N0HD0,N1HD0,N2HD0,N3HD0,Os,N0SD0,N1SD0,d,f,L,d,RT,
- d,*f,R,T,*f,*f,t,d,t,Q,?Q"))]
+ "K,N0HD0,N1HD0,N2HD0,N3HD0,Os,N0SD0,N1SD0,d,f,L,b,d,RT,
+ d,*f,R,T,*f,*f,d,K,t,d,t,Q,?Q"))]
"TARGET_64BIT"
"@
lghi\t%0,%h1
@@ -1038,6 +1222,7 @@
ldgr\t%0,%1
lgdr\t%0,%1
lay\t%0,%a1
+ lgrl\t%0,%1
lgr\t%0,%1
lg\t%0,%1
stg\t%1,%0
@@ -1046,17 +1231,21 @@
ldy\t%0,%1
std\t%1,%0
stdy\t%1,%0
+ stgrl\t%1,%0
+ mvghi\t%0,%1
#
#
stam\t%1,%N1,%S0
lam\t%0,%N0,%S1
#"
- [(set_attr "op_type" "RI,RI,RI,RI,RI,RIL,RIL,RIL,RRE,RRE,RXY,RRE,RXY,RXY,
- RR,RX,RXY,RX,RXY,*,*,RS,RS,SS")
- (set_attr "type" "*,*,*,*,*,*,*,*,floaddf,floaddf,la,lr,load,store,
- floaddf,floaddf,floaddf,fstoredf,fstoredf,*,*,*,*,*")
+ [(set_attr "op_type" "RI,RI,RI,RI,RI,RIL,RIL,RIL,RRE,RRE,RXY,RIL,RRE,RXY,
+ RXY,RR,RX,RXY,RX,RXY,RIL,SIL,*,*,RS,RS,SS")
+ (set_attr "type" "*,*,*,*,*,*,*,*,floaddf,floaddf,la,larl,lr,load,store,
+ floaddf,floaddf,floaddf,fstoredf,fstoredf,larl,*,*,*,
+ *,*,*")
(set_attr "cpu_facility" "*,*,*,*,*,extimm,extimm,extimm,dfp,dfp,longdisp,
- *,*,*,*,*,longdisp,*,longdisp,*,*,*,*,*")])
+ z10,*,*,*,*,*,longdisp,*,longdisp,
+ z10,z10,*,*,*,*,*")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -1092,8 +1281,10 @@
s390_split_access_reg (operands[0], &operands[3], &operands[4]);")
(define_insn "*movdi_31"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,Q,S,d,o,!*f,!*f,!*f,!R,!T,Q")
- (match_operand:DI 1 "general_operand" "Q,S,d,d,dPRT,d,*f,R,T,*f,*f,Q"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand"
+ "=d,d,Q,S,d ,o,!*f,!*f,!*f,!R,!T,Q,d")
+ (match_operand:DI 1 "general_operand"
+ " Q,S,d,d,dPRT,d, *f, R, T,*f,*f,Q,b"))]
"!TARGET_64BIT"
"@
lm\t%0,%N0,%S1
@@ -1107,9 +1298,26 @@
ldy\t%0,%1
std\t%1,%0
stdy\t%1,%0
+ #
#"
- [(set_attr "op_type" "RS,RSY,RS,RSY,*,*,RR,RX,RXY,RX,RXY,SS")
- (set_attr "type" "lm,lm,stm,stm,*,*,floaddf,floaddf,floaddf,fstoredf,fstoredf,*")])
+ [(set_attr "op_type" "RS,RSY,RS,RSY,*,*,RR,RX,RXY,RX,RXY,SS,*")
+ (set_attr "type" "lm,lm,stm,stm,*,*,floaddf,floaddf,floaddf,fstoredf,fstoredf,*,*")
+ (set_attr "cpu_facility" "*,*,*,*,*,*,*,*,*,*,*,*,z10")])
+
+; For a load from a symbol ref we can use one of the target registers
+; together with larl to load the address.
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "memory_operand" ""))]
+ "!TARGET_64BIT && reload_completed && TARGET_Z10
+ && larl_operand (XEXP (operands[1], 0), SImode)"
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 0) (match_dup 1))]
+{
+ operands[2] = operand_subword (operands[0], 1, 0, DImode);
+ operands[3] = XEXP (operands[1], 0);
+ operands[1] = replace_equiv_address (operands[1], operands[2]);
+})
(define_split
[(set (match_operand:DI 0 "nonimmediate_operand" "")
@@ -1227,9 +1435,9 @@
(define_insn "*movsi_zarch"
[(set (match_operand:SI 0 "nonimmediate_operand"
- "=d,d,d,d,d,d,d,d,R,T,!*f,!*f,!*f,!R,!T,d,t,Q,t,?Q")
+ "=d,d,d,d,d,d,d,d,d,R,T,!*f,!*f,!*f,!R,!T,d,t,Q,b,Q,t,?Q")
(match_operand:SI 1 "general_operand"
- "K,N0HS0,N1HS0,Os,L,d,R,T,d,d,*f,R,T,*f,*f,t,d,t,Q,?Q"))]
+ "K,N0HS0,N1HS0,Os,L,b,d,R,T,d,d,*f,R,T,*f,*f,t,d,t,d,K,Q,?Q"))]
"TARGET_ZARCH"
"@
lhi\t%0,%h1
@@ -1237,6 +1445,7 @@
llill\t%0,%i1
iilf\t%0,%o1
lay\t%0,%a1
+ lrl\t%0,%1
lr\t%0,%1
l\t%0,%1
ly\t%0,%1
@@ -1250,12 +1459,16 @@
ear\t%0,%1
sar\t%0,%1
stam\t%1,%1,%S0
+ strl\t%1,%0
+ mvhi\t%0,%1
lam\t%0,%0,%S1
#"
- [(set_attr "op_type" "RI,RI,RI,RIL,RXY,RR,RX,RXY,RX,RXY,
- RR,RX,RXY,RX,RXY,RRE,RRE,RS,RS,SS")
- (set_attr "type" "*,*,*,*,la,lr,load,load,store,store,
- floadsf,floadsf,floadsf,fstoresf,fstoresf,*,*,*,*,*")])
+ [(set_attr "op_type" "RI,RI,RI,RIL,RXY,RIL,RR,RX,RXY,RX,RXY,
+ RR,RX,RXY,RX,RXY,RRE,RRE,RS,RIL,SIL,RS,SS")
+ (set_attr "type" "*,*,*,*,la,larl,lr,load,load,store,store,
+ floadsf,floadsf,floadsf,fstoresf,fstoresf,*,*,*,larl,*,*,*")
+ (set_attr "cpu_facility" "*,*,*,extimm,longdisp,z10,*,*,longdisp,*,longdisp,
+ *,*,longdisp,*,longdisp,*,*,*,z10,z10,*,*")])
(define_insn "*movsi_esa"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,R,!*f,!*f,!R,d,t,Q,t,?Q")
@@ -1381,19 +1594,23 @@
})
(define_insn "*movhi"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,T,?Q")
- (match_operand:HI 1 "general_operand" "d,n,R,T,d,d,?Q"))]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,d,R,T,b,Q,?Q")
+ (match_operand:HI 1 "general_operand" " d,n,R,T,b,d,d,d,K,?Q"))]
""
"@
lr\t%0,%1
lhi\t%0,%h1
lh\t%0,%1
lhy\t%0,%1
+ lhrl\t%0,%1
sth\t%1,%0
sthy\t%1,%0
+ sthrl\t%1,%0
+ mvhhi\t%0,%1
#"
- [(set_attr "op_type" "RR,RI,RX,RXY,RX,RXY,SS")
- (set_attr "type" "lr,*,*,*,store,store,*")])
+ [(set_attr "op_type" "RR,RI,RX,RXY,RIL,RX,RXY,RIL,SIL,SS")
+ (set_attr "type" "lr,*,*,*,larl,store,store,store,*,*")
+ (set_attr "cpu_facility" "*,*,*,*,z10,*,*,z10,z10,*")])
(define_peephole2
[(set (match_operand:HI 0 "register_operand" "")
@@ -2014,6 +2231,17 @@
;; String instructions.
;;
+(define_insn "*execute_rl"
+ [(match_parallel 0 ""
+ [(unspec [(match_operand 1 "register_operand" "a")
+ (match_operand 2 "" "")
+ (match_operand:SI 3 "larl_operand" "X")] UNSPEC_EXECUTE)])]
+ "TARGET_Z10 && GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
+ && GET_MODE_SIZE (GET_MODE (operands[1])) <= UNITS_PER_WORD"
+ "exrl\t%1,%3"
+ [(set_attr "op_type" "RIL")
+ (set_attr "type" "cs")])
+
(define_insn "*execute"
[(match_parallel 0 ""
[(unspec [(match_operand 1 "register_operand" "a")
@@ -2158,9 +2386,9 @@
;
(define_expand "movmem<mode>"
- [(set (match_operand:BLK 0 "memory_operand" "")
- (match_operand:BLK 1 "memory_operand" ""))
- (use (match_operand:GPR 2 "general_operand" ""))
+ [(set (match_operand:BLK 0 "memory_operand" "") ; destination
+ (match_operand:BLK 1 "memory_operand" "")) ; source
+ (use (match_operand:GPR 2 "general_operand" "")) ; count
(match_operand 3 "" "")]
""
"s390_expand_movmem (operands[0], operands[1], operands[2]); DONE;")
@@ -2179,15 +2407,16 @@
"operands[3] = gen_rtx_SCRATCH (Pmode);")
(define_insn "*movmem_short"
- [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q")
- (match_operand:BLK 1 "memory_operand" "Q,Q,Q"))
- (use (match_operand 2 "nonmemory_operand" "n,a,a"))
- (use (match_operand 3 "immediate_operand" "X,R,X"))
- (clobber (match_scratch 4 "=X,X,&a"))]
+ [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q,Q")
+ (match_operand:BLK 1 "memory_operand" "Q,Q,Q,Q"))
+ (use (match_operand 2 "nonmemory_operand" "n,a,a,a"))
+ (use (match_operand 3 "immediate_operand" "X,R,X,X"))
+ (clobber (match_scratch 4 "=X,X,X,&a"))]
"(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
&& GET_MODE (operands[4]) == Pmode"
"#"
- [(set_attr "type" "cs")])
+ [(set_attr "type" "cs")
+ (set_attr "cpu_facility" "*,*,z10,*")])
(define_split
[(set (match_operand:BLK 0 "memory_operand" "")
@@ -2220,6 +2449,20 @@
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand 2 "register_operand" ""))
(use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+ (clobber (scratch))]
+ "TARGET_Z10 && reload_completed"
+ [(parallel
+ [(unspec [(match_dup 2) (const_int 0)
+ (label_ref (match_dup 3))] UNSPEC_EXECUTE)
+ (set (match_dup 0) (match_dup 1))
+ (use (const_int 1))])]
+ "operands[3] = gen_label_rtx ();")
+
+(define_split
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" ""))
+ (use (match_operand 2 "register_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
(clobber (match_operand 3 "register_operand" ""))]
"reload_completed && TARGET_CPU_ZARCH"
[(set (match_dup 3) (label_ref (match_dup 4)))
@@ -2358,16 +2601,17 @@
"operands[2] = gen_rtx_SCRATCH (Pmode);")
(define_insn "*clrmem_short"
- [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q")
+ [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q,Q")
(const_int 0))
- (use (match_operand 1 "nonmemory_operand" "n,a,a"))
- (use (match_operand 2 "immediate_operand" "X,R,X"))
- (clobber (match_scratch 3 "=X,X,&a"))
+ (use (match_operand 1 "nonmemory_operand" "n,a,a,a"))
+ (use (match_operand 2 "immediate_operand" "X,R,X,X"))
+ (clobber (match_scratch 3 "=X,X,X,&a"))
(clobber (reg:CC CC_REGNUM))]
"(GET_MODE (operands[1]) == Pmode || GET_MODE (operands[1]) == VOIDmode)
&& GET_MODE (operands[3]) == Pmode"
"#"
- [(set_attr "type" "cs")])
+ [(set_attr "type" "cs")
+ (set_attr "cpu_facility" "*,*,z10,*")])
(define_split
[(set (match_operand:BLK 0 "memory_operand" "")
@@ -2404,6 +2648,22 @@
(const_int 0))
(use (match_operand 1 "register_operand" ""))
(use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+ (clobber (scratch))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_Z10 && reload_completed"
+ [(parallel
+ [(unspec [(match_dup 1) (const_int 0)
+ (label_ref (match_dup 3))] UNSPEC_EXECUTE)
+ (set (match_dup 0) (const_int 0))
+ (use (const_int 1))
+ (clobber (reg:CC CC_REGNUM))])]
+ "operands[3] = gen_label_rtx ();")
+
+(define_split
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (const_int 0))
+ (use (match_operand 1 "register_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
(clobber (match_operand 2 "register_operand" ""))
(clobber (reg:CC CC_REGNUM))]
"reload_completed && TARGET_CPU_ZARCH"
@@ -2499,15 +2759,16 @@
(define_insn "*cmpmem_short"
[(set (reg:CCU CC_REGNUM)
- (compare:CCU (match_operand:BLK 0 "memory_operand" "Q,Q,Q")
- (match_operand:BLK 1 "memory_operand" "Q,Q,Q")))
- (use (match_operand 2 "nonmemory_operand" "n,a,a"))
- (use (match_operand 3 "immediate_operand" "X,R,X"))
- (clobber (match_scratch 4 "=X,X,&a"))]
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "Q,Q,Q,Q")
+ (match_operand:BLK 1 "memory_operand" "Q,Q,Q,Q")))
+ (use (match_operand 2 "nonmemory_operand" "n,a,a,a"))
+ (use (match_operand 3 "immediate_operand" "X,R,X,X"))
+ (clobber (match_scratch 4 "=X,X,X,&a"))]
"(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
&& GET_MODE (operands[4]) == Pmode"
"#"
- [(set_attr "type" "cs")])
+ [(set_attr "type" "cs")
+ (set_attr "cpu_facility" "*,*,z10,*")])
(define_split
[(set (reg:CCU CC_REGNUM)
@@ -2543,6 +2804,21 @@
(match_operand:BLK 1 "memory_operand" "")))
(use (match_operand 2 "register_operand" ""))
(use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+ (clobber (scratch))]
+ "TARGET_Z10 && reload_completed"
+ [(parallel
+ [(unspec [(match_dup 2) (const_int 0)
+ (label_ref (match_dup 4))] UNSPEC_EXECUTE)
+ (set (reg:CCU CC_REGNUM) (compare:CCU (match_dup 0) (match_dup 1)))
+ (use (const_int 1))])]
+ "operands[4] = gen_label_rtx ();")
+
+(define_split
+ [(set (reg:CCU CC_REGNUM)
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")))
+ (use (match_operand 2 "register_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
(clobber (match_operand 3 "register_operand" ""))]
"reload_completed && TARGET_CPU_ZARCH"
[(set (match_dup 3) (label_ref (match_dup 4)))
@@ -2776,6 +3052,83 @@
FAIL;
})
+(define_insn "*insv<mode>_z10"
+ [(set (zero_extract:GPR (match_operand:GPR 0 "nonimmediate_operand" "+d")
+ (match_operand 1 "const_int_operand" "I")
+ (match_operand 2 "const_int_operand" "I"))
+ (match_operand:GPR 3 "nonimmediate_operand" "d"))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_Z10
+ && (INTVAL (operands[1]) + INTVAL (operands[2])) <=
+ GET_MODE_BITSIZE (<MODE>mode)"
+{
+ int start = INTVAL (operands[2]);
+ int size = INTVAL (operands[1]);
+ int offset = 64 - GET_MODE_BITSIZE (<MODE>mode);
+
+ operands[2] = GEN_INT (offset + start); /* start bit position */
+ operands[1] = GEN_INT (offset + start + size - 1); /* end bit position */
+ operands[4] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) -
+ start - size); /* left shift count */
+
+ return "risbg\t%0,%3,%b2,%b1,%b4";
+}
+ [(set_attr "op_type" "RIE")])
+
+; and op1 with a mask being 1 for the selected bits and 0 for the rest
+; and op3=op0 with a mask being 0 for the selected bits and 1 for the rest
+(define_insn "*insv<mode>_z10_noshift"
+ [(set (match_operand:GPR 0 "nonimmediate_operand" "=d")
+ (ior:GPR (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "d")
+ (match_operand 2 "const_int_operand" "n"))
+ (and:GPR (match_operand:GPR 3 "nonimmediate_operand" "0")
+ (match_operand 4 "const_int_operand" "n"))))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_Z10
+ && s390_contiguous_bitmask_p (INTVAL (operands[2]),
+ GET_MODE_BITSIZE (<MODE>mode), NULL, NULL)
+ && INTVAL (operands[2]) == ~(INTVAL (operands[4]))"
+
+{
+ int start;
+ int size;
+
+ s390_contiguous_bitmask_p (INTVAL (operands[2]),
+ GET_MODE_BITSIZE (<MODE>mode), &start, &size);
+
+ operands[5] = GEN_INT (64 - start - size); /* start bit position */
+ operands[6] = GEN_INT (64 - 1 - start); /* end bit position */
+ operands[7] = const0_rtx; /* left shift count */
+
+ return "risbg\t%0,%1,%b5,%b6,%b7";
+}
+ [(set_attr "op_type" "RIE")])
+
+; and op1 with a mask being 1 for the selected bits and 0 for the rest
+(define_insn "*insv<mode>_or_z10_noshift"
+ [(set (match_operand:GPR 0 "nonimmediate_operand" "=d")
+ (ior:GPR (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "d")
+ (match_operand 2 "const_int_operand" "n"))
+ (match_operand:GPR 3 "nonimmediate_operand" "0")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_Z10
+ && s390_contiguous_bitmask_p (INTVAL (operands[2]),
+ GET_MODE_BITSIZE (<MODE>mode), NULL, NULL)"
+{
+ int start;
+ int size;
+
+ s390_contiguous_bitmask_p (INTVAL (operands[2]),
+ GET_MODE_BITSIZE (<MODE>mode), &start, &size);
+
+ operands[4] = GEN_INT (64 - start - size); /* start bit position */
+ operands[5] = GEN_INT (64 - 1 - start); /* end bit position */
+ operands[6] = const0_rtx; /* left shift count */
+
+ return "rosbg\t%0,%1,%b4,%b5,%b6";
+}
+ [(set_attr "op_type" "RIE")])
+
(define_insn "*insv<mode>_mem_reg"
[(set (zero_extract:P (match_operand:QI 0 "memory_operand" "+Q,S")
(match_operand 1 "const_int_operand" "n,n")
@@ -2871,13 +3224,16 @@
})
(define_insn "*extendsidi2"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT")))]
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+ (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT,b")))]
"TARGET_64BIT"
"@
lgfr\t%0,%1
- lgf\t%0,%1"
- [(set_attr "op_type" "RRE,RXY")])
+ lgf\t%0,%1
+ lgfrl\t%0,%1"
+ [(set_attr "op_type" "RRE,RXY,RIL")
+ (set_attr "type" "*,*,larl")
+ (set_attr "cpu_facility" "*,*,z10")])
;
; extend(hi|qi)(si|di)2 instruction pattern(s).
@@ -2912,13 +3268,16 @@
;
(define_insn "*extendhidi2_extimm"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "d,RT")))]
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+ (sign_extend:DI (match_operand:HI 1 "general_operand" "d,RT,b")))]
"TARGET_64BIT && TARGET_EXTIMM"
"@
lghr\t%0,%1
- lgh\t%0,%1"
- [(set_attr "op_type" "RRE,RXY")])
+ lgh\t%0,%1
+ lghrl\t%0,%1"
+ [(set_attr "op_type" "RRE,RXY,RIL")
+ (set_attr "type" "*,*,larl")
+ (set_attr "cpu_facility" "extimm,extimm,z10")])
(define_insn "*extendhidi2"
[(set (match_operand:DI 0 "register_operand" "=d")
@@ -2932,14 +3291,17 @@
;
(define_insn "*extendhisi2_extimm"
- [(set (match_operand:SI 0 "register_operand" "=d,d,d")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,R,T")))]
+ [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" " d,R,T,b")))]
"TARGET_EXTIMM"
"@
lhr\t%0,%1
lh\t%0,%1
- lhy\t%0,%1"
- [(set_attr "op_type" "RRE,RX,RXY")])
+ lhy\t%0,%1
+ lhrl\t%0,%1"
+ [(set_attr "op_type" "RRE,RX,RXY,RIL")
+ (set_attr "type" "*,*,*,larl")
+ (set_attr "cpu_facility" "extimm,extimm,extimm,z10")])
(define_insn "*extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=d,d")
@@ -3011,13 +3373,16 @@
})
(define_insn "*zero_extendsidi2"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT")))]
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+ (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT,b")))]
"TARGET_64BIT"
"@
llgfr\t%0,%1
- llgf\t%0,%1"
- [(set_attr "op_type" "RRE,RXY")])
+ llgf\t%0,%1
+ llgfrl\t%0,%1"
+ [(set_attr "op_type" "RRE,RXY,RIL")
+ (set_attr "type" "*,*,larl")
+ (set_attr "cpu_facility" "*,*,z10")])
;
; LLGT-type instructions (zero-extend from 31 bit to 64 bit).
@@ -3116,6 +3481,19 @@
}
})
+; llhrl, llghrl
+(define_insn "*zero_extendhi<mode>2_z10"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d,d")
+ (zero_extend:GPR (match_operand:HI 1 "nonimmediate_operand" "d,RT,b")))]
+ "TARGET_Z10"
+ "@
+ ll<g>hr\t%0,%1
+ ll<g>h\t%0,%1
+ ll<g>hrl\t%0,%1"
+ [(set_attr "op_type" "RXY,RRE,RIL")
+ (set_attr "type" "*,*,larl")
+ (set_attr "cpu_facility" "*,*,z10")])
+
; llhr, llcr, llghr, llgcr, llh, llc, llgh, llgc
(define_insn "*zero_extend<HQI:mode><GPR:mode>2_extimm"
[(set (match_operand:GPR 0 "register_operand" "=d,d")
@@ -3628,7 +4006,7 @@
(define_expand "adddi3"
[(parallel
- [(set (match_operand:DI 0 "register_operand" "")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
(plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
(match_operand:DI 2 "general_operand" "")))
(clobber (reg:CC CC_REGNUM))])]
@@ -3683,7 +4061,7 @@
[(set_attr "op_type" "RRE,RXY")])
(define_insn_and_split "*adddi3_31z"
- [(set (match_operand:DI 0 "register_operand" "=&d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
(match_operand:DI 2 "general_operand" "do") ) )
(clobber (reg:CC CC_REGNUM))]
@@ -3708,7 +4086,7 @@
operands[8] = operand_subword (operands[2], 1, 0, DImode);")
(define_insn_and_split "*adddi3_31"
- [(set (match_operand:DI 0 "register_operand" "=&d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
(match_operand:DI 2 "general_operand" "do") ) )
(clobber (reg:CC CC_REGNUM))]
@@ -3745,7 +4123,7 @@
(define_expand "addsi3"
[(parallel
- [(set (match_operand:SI 0 "register_operand" "")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
(plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
(match_operand:SI 2 "general_operand" "")))
(clobber (reg:CC CC_REGNUM))])]
@@ -3767,11 +4145,11 @@
; add(di|si)3 instruction pattern(s).
;
-; ar, ahi, alfi, slfi, a, ay, agr, aghi, algfi, slgfi, ag
+; ar, ahi, alfi, slfi, a, ay, agr, aghi, algfi, slgfi, ag, asi, agsi
(define_insn "*add<mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d,d")
- (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0,0")
- (match_operand:GPR 2 "general_operand" "d,K,Op,On,R,T") ) )
+ [(set (match_operand:GPR 0 "nonimmediate_operand" "=d,d,d,d,d,d,QS")
+ (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,K,Op,On,R,T,C") ) )
(clobber (reg:CC CC_REGNUM))]
""
"@
@@ -3780,16 +4158,18 @@
al<g>fi\t%0,%2
sl<g>fi\t%0,%n2
a<g>\t%0,%2
- a<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RI,RIL,RIL,RX<Y>,RXY")])
+ a<y>\t%0,%2
+ a<g>si\t%0,%c2"
+ [(set_attr "op_type" "RR<E>,RI,RIL,RIL,RX<Y>,RXY,SIY")
+ (set_attr "cpu_facility" "*,*,extimm,extimm,*,*,z10")])
-; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg
+; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg, alsi, algsi
(define_insn "*add<mode>3_carry1_cc"
[(set (reg CC_REGNUM)
- (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0")
- (match_operand:GPR 2 "general_operand" "d,Op,On,R,T"))
+ (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,Op,On,R,T,C"))
(match_dup 1)))
- (set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
+ (set (match_operand:GPR 0 "nonimmediate_operand" "=d,d,d,d,d,d")
(plus:GPR (match_dup 1) (match_dup 2)))]
"s390_match_ccmode (insn, CCL1mode)"
"@
@@ -3797,8 +4177,10 @@
al<g>fi\t%0,%2
sl<g>fi\t%0,%n2
al<g>\t%0,%2
- al<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RIL,RIL,RX<Y>,RXY")])
+ al<y>\t%0,%2
+ al<g>si\t%0,%c2"
+ [(set_attr "op_type" "RR<E>,RIL,RIL,RX<Y>,RXY,SIY")
+ (set_attr "cpu_facility" "*,extimm,extimm,*,*,z10")])
; alr, al, aly, algr, alg
(define_insn "*add<mode>3_carry1_cconly"
@@ -3814,13 +4196,13 @@
al<y>\t%0,%2"
[(set_attr "op_type" "RR<E>,RX<Y>,RXY")])
-; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg
+; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg, alsi, algsi
(define_insn "*add<mode>3_carry2_cc"
[(set (reg CC_REGNUM)
- (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0")
- (match_operand:GPR 2 "general_operand" "d,Op,On,R,T"))
+ (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,Op,On,R,T,C"))
(match_dup 2)))
- (set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
+ (set (match_operand:GPR 0 "nonimmediate_operand" "=d,d,d,d,d,RS")
(plus:GPR (match_dup 1) (match_dup 2)))]
"s390_match_ccmode (insn, CCL1mode)"
"@
@@ -3828,8 +4210,10 @@
al<g>fi\t%0,%2
sl<g>fi\t%0,%n2
al<g>\t%0,%2
- al<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RIL,RIL,RX<Y>,RXY")])
+ al<y>\t%0,%2
+ al<g>si\t%0,%c2"
+ [(set_attr "op_type" "RR<E>,RIL,RIL,RX<Y>,RXY,SIY")
+ (set_attr "cpu_facility" "*,extimm,extimm,*,*,z10")])
; alr, al, aly, algr, alg
(define_insn "*add<mode>3_carry2_cconly"
@@ -3845,13 +4229,13 @@
al<y>\t%0,%2"
[(set_attr "op_type" "RR<E>,RX<Y>,RXY")])
-; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg
+; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg, alsi, algsi
(define_insn "*add<mode>3_cc"
[(set (reg CC_REGNUM)
- (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0")
- (match_operand:GPR 2 "general_operand" "d,Op,On,R,T"))
+ (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,Op,On,R,T,C"))
(const_int 0)))
- (set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
+ (set (match_operand:GPR 0 "nonimmediate_operand" "=d,d,d,d,d,RS")
(plus:GPR (match_dup 1) (match_dup 2)))]
"s390_match_ccmode (insn, CCLmode)"
"@
@@ -3859,8 +4243,10 @@
al<g>fi\t%0,%2
sl<g>fi\t%0,%n2
al<g>\t%0,%2
- al<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RIL,RIL,RX<Y>,RXY")])
+ al<y>\t%0,%2
+ al<g>si\t%0,%c2"
+ [(set_attr "op_type" "RR<E>,RIL,RIL,RX<Y>,RXY,SIY")
+ (set_attr "cpu_facility" "*,extimm,extimm,*,*,z10")])
; alr, al, aly, algr, alg
(define_insn "*add<mode>3_cconly"
@@ -3889,22 +4275,25 @@
al<y>\t%0,%2"
[(set_attr "op_type" "RR<E>,RX<Y>,RXY")])
-; ahi, afi, aghi, agfi
+; ahi, afi, aghi, agfi, asi, agsi
(define_insn "*add<mode>3_imm_cc"
[(set (reg CC_REGNUM)
- (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "0,0")
- (match_operand:GPR 2 "const_int_operand" "K,Os"))
+ (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "0,0,0")
+ (match_operand:GPR 2 "const_int_operand" "K,Os,C"))
(const_int 0)))
- (set (match_operand:GPR 0 "register_operand" "=d,d")
+ (set (match_operand:GPR 0 "nonimmediate_operand" "=d,d,QS")
(plus:GPR (match_dup 1) (match_dup 2)))]
"s390_match_ccmode (insn, CCAmode)
&& (CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'K', \"K\")
- || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'O', \"Os\"))
+ || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'O', \"Os\")
+ || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'C', \"C\"))
&& INTVAL (operands[2]) != -((HOST_WIDE_INT)1 << (GET_MODE_BITSIZE(<MODE>mode) - 1))"
"@
a<g>hi\t%0,%h2
- a<g>fi\t%0,%2"
- [(set_attr "op_type" "RI,RIL")])
+ a<g>fi\t%0,%2
+ a<g>si\t%0,%c2"
+ [(set_attr "op_type" "RI,RIL,SIY")
+ (set_attr "cpu_facility" "*,extimm,z10")])
;
; add(tf|df|sf|td|dd)3 instruction pattern(s).
@@ -4503,69 +4892,78 @@
(define_insn "*muldi3_sign"
[(set (match_operand:DI 0 "register_operand" "=d,d")
- (mult:DI (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "d,RT"))
+ (mult:DI (sign_extend:DI (match_operand:SI 2 "general_operand" "d,RT"))
(match_operand:DI 1 "register_operand" "0,0")))]
"TARGET_64BIT"
"@
msgfr\t%0,%2
msgf\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "type" "imuldi")])
+ [(set_attr "op_type" "RRE,RXY")
+ (set_attr "type" "imuldi")])
(define_insn "muldi3"
- [(set (match_operand:DI 0 "register_operand" "=d,d,d")
- (mult:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:DI 2 "general_operand" "d,K,RT")))]
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d,d")
+ (mult:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,0")
+ (match_operand:DI 2 "general_operand" "d,K,RT,Os")))]
"TARGET_64BIT"
"@
msgr\t%0,%2
mghi\t%0,%h2
- msg\t%0,%2"
- [(set_attr "op_type" "RRE,RI,RXY")
- (set_attr "type" "imuldi")])
+ msg\t%0,%2
+ msgfi\t%0,%2"
+ [(set_attr "op_type" "RRE,RI,RXY,RIL")
+ (set_attr "type" "imuldi")
+ (set_attr "cpu_facility" "*,*,*,z10")])
;
; mulsi3 instruction pattern(s).
;
(define_insn "*mulsi3_sign"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (mult:SI (sign_extend:SI (match_operand:HI 2 "memory_operand" "R"))
- (match_operand:SI 1 "register_operand" "0")))]
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (mult:SI (sign_extend:SI (match_operand:HI 2 "memory_operand" "R,T"))
+ (match_operand:SI 1 "register_operand" "0,0")))]
""
- "mh\t%0,%2"
- [(set_attr "op_type" "RX")
- (set_attr "type" "imulhi")])
+ "@
+ mh\t%0,%2
+ mhy\t%0,%2"
+ [(set_attr "op_type" "RX,RXY")
+ (set_attr "type" "imulhi")
+ (set_attr "cpu_facility" "*,z10")])
(define_insn "mulsi3"
- [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
- (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0")
- (match_operand:SI 2 "general_operand" "d,K,R,T")))]
+ [(set (match_operand:SI 0 "register_operand" "=d,d,d,d,d")
+ (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0,0")
+ (match_operand:SI 2 "general_operand" "d,K,R,T,Os")))]
""
"@
msr\t%0,%2
mhi\t%0,%h2
ms\t%0,%2
- msy\t%0,%2"
- [(set_attr "op_type" "RRE,RI,RX,RXY")
- (set_attr "type" "imulsi,imulhi,imulsi,imulsi")])
+ msy\t%0,%2
+ msfi\t%0,%2"
+ [(set_attr "op_type" "RRE,RI,RX,RXY,RIL")
+ (set_attr "type" "imulsi,imulhi,imulsi,imulsi,imulsi")
+ (set_attr "cpu_facility" "*,*,*,*,z10")])
;
; mulsidi3 instruction pattern(s).
;
(define_insn "mulsidi3"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d")
(mult:DI (sign_extend:DI
- (match_operand:SI 1 "register_operand" "%0,0"))
+ (match_operand:SI 1 "register_operand" "%0,0,0"))
(sign_extend:DI
- (match_operand:SI 2 "nonimmediate_operand" "d,R"))))]
+ (match_operand:SI 2 "nonimmediate_operand" "d,R,T"))))]
"!TARGET_64BIT"
"@
mr\t%0,%2
- m\t%0,%2"
- [(set_attr "op_type" "RR,RX")
- (set_attr "type" "imulsi")])
+ m\t%0,%2
+ mfy\t%0,%2"
+ [(set_attr "op_type" "RR,RX,RXY")
+ (set_attr "type" "imulsi")
+ (set_attr "cpu_facility" "*,*,z10")])
;
; umulsidi3 instruction pattern(s).
@@ -6762,6 +7160,32 @@
[(set_attr "op_type" "RI")
(set_attr "type" "branch")])
+; crt, cgrt, cit, cgit
+(define_insn "*cmp_and_trap_signed_int<mode>"
+ [(trap_if (match_operator 0 "s390_signed_integer_comparison"
+ [(match_operand:GPR 1 "register_operand" "d,d")
+ (match_operand:GPR 2 "nonmemory_operand" "d,K")])
+ (const_int 0))]
+ "TARGET_Z10"
+ "@
+ c<g>rt%C0\t%1,%2
+ c<g>it%C0\t%1,%h2"
+ [(set_attr "op_type" "RRF,RIE")
+ (set_attr "type" "branch")])
+
+; clrt, clgrt, clfit, clgit
+(define_insn "*cmp_and_trap_unsigned_int<mode>"
+ [(trap_if (match_operator 0 "s390_unsigned_integer_comparison"
+ [(match_operand:GPR 1 "register_operand" "d,d")
+ (match_operand:GPR 2 "nonmemory_operand" "d,D")])
+ (const_int 0))]
+ "TARGET_Z10"
+ "@
+ cl<g>rt%C0\t%1,%2
+ cl<gf>it%C0\t%1,%x2"
+ [(set_attr "op_type" "RRF,RIE")
+ (set_attr "type" "branch")])
+
;;
;;- Loop instructions.
;;
@@ -7908,3 +8332,30 @@
""
""
[(set_attr "length" "0")])
+
+
+;
+; Data prefetch patterns
+;
+
+(define_insn "prefetch"
+ [(prefetch (match_operand 0 "address_operand" "UW,X")
+ (match_operand:SI 1 "const_int_operand" "n,n")
+ (match_operand:SI 2 "const_int_operand" "n,n"))]
+ "TARGET_Z10"
+{
+ if (larl_operand (operands[0], Pmode))
+ return INTVAL (operands[1]) == 1 ? "pfdrl\t2,%a0" : "pfdrl\t1,%a0";
+
+ if (s390_mem_constraint ("W", operands[0])
+ || s390_mem_constraint ("U", operands[0]))
+ return INTVAL (operands[1]) == 1 ? "pfd\t2,%a0" : "pfd\t1,%a0";
+
+ /* This point might be reached if op0 is a larl operand with an
+ uneven addend. In this case we simply omit issuing a prefetch
+ instruction. */
+
+ return "";
+
+} [(set_attr "type" "load,larl")
+ (set_attr "op_type" "RXY,RIL")])