constraints.md ('b', [...]): New constraint letters defined.
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. From-SVN: r136098
This commit is contained in:
parent
93538e8eda
commit
963fc8d00b
7 changed files with 1119 additions and 191 deletions
|
@ -1,3 +1,68 @@
|
|||
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.
|
||||
|
|
|
@ -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)"))
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) \
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue