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:
Andreas Krebbel 2008-05-28 14:11:19 +00:00 committed by Andreas Krebbel
parent 93538e8eda
commit 963fc8d00b
7 changed files with 1119 additions and 191 deletions

View file

@ -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.

View file

@ -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)"))

View file

@ -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.

View file

@ -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 */

View file

@ -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

View file

@ -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