s390-protos.h (s390_split_access_reg): Add prototype.
* config/s390/s390-protos.h (s390_split_access_reg): Add prototype. * config/s390/s390.c (s390_split_access_reg): New function. (regclass_map): Add access registers. (get_thread_pointer): Use access register instead of UNSPEC_TP. * config/s390/s390.h (FIRST_PSEUDO_REGISTER): Set to 38. (ACCESS_REGNO_P, ACCESS_REG_P): New macros. (TP_REGNUM): New define. (FIXED_REGISTERS, CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS, REG_ALLOC_ORDER): Add access registers. (HARD_REGNO_NREGS, HARD_REGNO_MODE_OK, CLASS_MAX_NREGS, CANNOT_CHANGE_MODE_CLASS): Support access registers. (enum reg_class): Add ACCESS_REGS. (REG_CLASS_NAMES, REG_CLASS_CONTENTS): Likewise. (REG_CLASS_FROM_LETTER): Add 't' constraint. (REGISTER_NAMES): Add access registers. * config/s390/s390.md (UNSPEC_TP): Remove. ("*movdi_64"): Add access register alternatives. Provide splitters to split DImode access register <-> GPR moves into SImode moves. ("*movsi_zarch", "*movsi_esa"): Add access register alternatives. ("movstrictsi"): Likewise. ("get_tp_64", "get_tp_31"): Reimplement using access registers. ("set_tp_64", "set_tp_31"): Likewise. ("*set_tp"): New insn. From-SVN: r90036
This commit is contained in:
parent
57f60923b2
commit
c5aa1d125c
5 changed files with 176 additions and 76 deletions
|
@ -1,3 +1,29 @@
|
|||
2004-11-03 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* config/s390/s390-protos.h (s390_split_access_reg): Add prototype.
|
||||
* config/s390/s390.c (s390_split_access_reg): New function.
|
||||
(regclass_map): Add access registers.
|
||||
(get_thread_pointer): Use access register instead of UNSPEC_TP.
|
||||
* config/s390/s390.h (FIRST_PSEUDO_REGISTER): Set to 38.
|
||||
(ACCESS_REGNO_P, ACCESS_REG_P): New macros.
|
||||
(TP_REGNUM): New define.
|
||||
(FIXED_REGISTERS, CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS,
|
||||
REG_ALLOC_ORDER): Add access registers.
|
||||
(HARD_REGNO_NREGS, HARD_REGNO_MODE_OK, CLASS_MAX_NREGS,
|
||||
CANNOT_CHANGE_MODE_CLASS): Support access registers.
|
||||
(enum reg_class): Add ACCESS_REGS.
|
||||
(REG_CLASS_NAMES, REG_CLASS_CONTENTS): Likewise.
|
||||
(REG_CLASS_FROM_LETTER): Add 't' constraint.
|
||||
(REGISTER_NAMES): Add access registers.
|
||||
* config/s390/s390.md (UNSPEC_TP): Remove.
|
||||
("*movdi_64"): Add access register alternatives. Provide splitters
|
||||
to split DImode access register <-> GPR moves into SImode moves.
|
||||
("*movsi_zarch", "*movsi_esa"): Add access register alternatives.
|
||||
("movstrictsi"): Likewise.
|
||||
("get_tp_64", "get_tp_31"): Reimplement using access registers.
|
||||
("set_tp_64", "set_tp_31"): Likewise.
|
||||
("*set_tp"): New insn.
|
||||
|
||||
2004-11-03 Kazu Hirata <kazu@cs.umass.edu>
|
||||
|
||||
* tree-phinodes.c (resize_phi_node): Copy only a portion of
|
||||
|
|
|
@ -90,6 +90,7 @@ extern void s390_expand_logical_operator (enum rtx_code,
|
|||
extern bool s390_logical_operator_ok_p (rtx *);
|
||||
extern void s390_narrow_logical_operator (enum rtx_code, rtx *, rtx *);
|
||||
extern bool s390_pool_operand (rtx);
|
||||
extern void s390_split_access_reg (rtx, rtx *, rtx *);
|
||||
|
||||
extern bool s390_output_addr_const_extra (FILE*, rtx);
|
||||
extern void print_operand_address (FILE *, rtx);
|
||||
|
|
|
@ -1355,7 +1355,8 @@ const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
|
|||
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
|
||||
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
|
||||
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
|
||||
ADDR_REGS, CC_REGS, ADDR_REGS, ADDR_REGS
|
||||
ADDR_REGS, CC_REGS, ADDR_REGS, ADDR_REGS,
|
||||
ACCESS_REGS, ACCESS_REGS
|
||||
};
|
||||
|
||||
/* Return attribute type of insn. */
|
||||
|
@ -2019,6 +2020,22 @@ store_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Split DImode access register reference REG (on 64-bit) into its constituent
|
||||
low and high parts, and store them into LO and HI. Note that gen_lowpart/
|
||||
gen_highpart cannot be used as they assume all registers are word-sized,
|
||||
while our access registers have only half that size. */
|
||||
|
||||
void
|
||||
s390_split_access_reg (rtx reg, rtx *lo, rtx *hi)
|
||||
{
|
||||
gcc_assert (TARGET_64BIT);
|
||||
gcc_assert (ACCESS_REG_P (reg));
|
||||
gcc_assert (GET_MODE (reg) == DImode);
|
||||
gcc_assert (!(REGNO (reg) & 1));
|
||||
|
||||
*lo = gen_rtx_REG (SImode, REGNO (reg) + 1);
|
||||
*hi = gen_rtx_REG (SImode, REGNO (reg));
|
||||
}
|
||||
|
||||
/* Return true if OP contains a symbol reference */
|
||||
|
||||
|
@ -3033,10 +3050,9 @@ legitimize_pic_address (rtx orig, rtx reg)
|
|||
static rtx
|
||||
get_thread_pointer (void)
|
||||
{
|
||||
rtx tp;
|
||||
rtx tp = gen_reg_rtx (Pmode);
|
||||
|
||||
tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP);
|
||||
tp = force_reg (Pmode, tp);
|
||||
emit_move_insn (tp, gen_rtx_REG (Pmode, TP_REGNUM));
|
||||
mark_reg_pointer (tp, BITS_PER_WORD);
|
||||
|
||||
return tp;
|
||||
|
|
|
@ -307,13 +307,17 @@ if (INTEGRAL_MODE_P (MODE) && \
|
|||
GPR 14: Return address register
|
||||
GPR 15: Stack pointer
|
||||
|
||||
Registers 32-34 are 'fake' hard registers that do not
|
||||
Registers 32-35 are 'fake' hard registers that do not
|
||||
correspond to actual hardware:
|
||||
Reg 32: Argument pointer
|
||||
Reg 33: Condition code
|
||||
Reg 34: Frame pointer */
|
||||
Reg 34: Frame pointer
|
||||
Reg 35: Return address pointer
|
||||
|
||||
#define FIRST_PSEUDO_REGISTER 36
|
||||
Registers 36 and 37 are mapped to access registers
|
||||
0 and 1, used to implement thread-local storage. */
|
||||
|
||||
#define FIRST_PSEUDO_REGISTER 38
|
||||
|
||||
/* Standard register usage. */
|
||||
#define GENERAL_REGNO_P(N) ((int)(N) >= 0 && (N) < 16)
|
||||
|
@ -321,17 +325,20 @@ if (INTEGRAL_MODE_P (MODE) && \
|
|||
#define FP_REGNO_P(N) ((N) >= 16 && (N) < (TARGET_IEEE_FLOAT? 32 : 20))
|
||||
#define CC_REGNO_P(N) ((N) == 33)
|
||||
#define FRAME_REGNO_P(N) ((N) == 32 || (N) == 34 || (N) == 35)
|
||||
#define ACCESS_REGNO_P(N) ((N) == 36 || (N) == 37)
|
||||
|
||||
#define GENERAL_REG_P(X) (REG_P (X) && GENERAL_REGNO_P (REGNO (X)))
|
||||
#define ADDR_REG_P(X) (REG_P (X) && ADDR_REGNO_P (REGNO (X)))
|
||||
#define FP_REG_P(X) (REG_P (X) && FP_REGNO_P (REGNO (X)))
|
||||
#define CC_REG_P(X) (REG_P (X) && CC_REGNO_P (REGNO (X)))
|
||||
#define FRAME_REG_P(X) (REG_P (X) && FRAME_REGNO_P (REGNO (X)))
|
||||
#define ACCESS_REG_P(X) (REG_P (X) && ACCESS_REGNO_P (REGNO (X)))
|
||||
|
||||
#define SIBCALL_REGNUM 1
|
||||
#define BASE_REGNUM 13
|
||||
#define RETURN_REGNUM 14
|
||||
#define CC_REGNUM 33
|
||||
#define TP_REGNUM 36
|
||||
|
||||
/* Set up fixed registers and calling convention:
|
||||
|
||||
|
@ -342,6 +349,7 @@ if (INTEGRAL_MODE_P (MODE) && \
|
|||
GPR 14 is always fixed on S/390 machines (as return address).
|
||||
GPR 15 is always fixed (as stack pointer).
|
||||
The 'fake' hard registers are call-clobbered and fixed.
|
||||
The access registers are call-saved and fixed.
|
||||
|
||||
On 31-bit, FPRs 18-19 are call-clobbered;
|
||||
on 64-bit, FPRs 24-31 are call-clobbered.
|
||||
|
@ -356,7 +364,8 @@ if (INTEGRAL_MODE_P (MODE) && \
|
|||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
1, 1, 1, 1 }
|
||||
1, 1, 1, 1, \
|
||||
1, 1 }
|
||||
|
||||
#define CALL_USED_REGISTERS \
|
||||
{ 1, 1, 1, 1, \
|
||||
|
@ -367,7 +376,8 @@ if (INTEGRAL_MODE_P (MODE) && \
|
|||
1, 1, 1, 1, \
|
||||
1, 1, 1, 1, \
|
||||
1, 1, 1, 1, \
|
||||
1, 1, 1, 1 }
|
||||
1, 1, 1, 1, \
|
||||
1, 1 }
|
||||
|
||||
#define CALL_REALLY_USED_REGISTERS \
|
||||
{ 1, 1, 1, 1, \
|
||||
|
@ -378,7 +388,8 @@ if (INTEGRAL_MODE_P (MODE) && \
|
|||
1, 1, 1, 1, \
|
||||
1, 1, 1, 1, \
|
||||
1, 1, 1, 1, \
|
||||
1, 1, 1, 1 }
|
||||
1, 1, 1, 1, \
|
||||
0, 0 }
|
||||
|
||||
#define CONDITIONAL_REGISTER_USAGE s390_conditional_register_usage ()
|
||||
|
||||
|
@ -387,7 +398,7 @@ if (INTEGRAL_MODE_P (MODE) && \
|
|||
{ 1, 2, 3, 4, 5, 0, 13, 12, 11, 10, 9, 8, 7, 6, 14, \
|
||||
16, 17, 18, 19, 20, 21, 22, 23, \
|
||||
24, 25, 26, 27, 28, 29, 30, 31, \
|
||||
15, 32, 33, 34, 35 }
|
||||
15, 32, 33, 34, 35, 36, 37 }
|
||||
|
||||
|
||||
/* Fitting values into registers. */
|
||||
|
@ -411,6 +422,8 @@ if (INTEGRAL_MODE_P (MODE) && \
|
|||
(GET_MODE_CLASS(MODE) == MODE_COMPLEX_FLOAT ? 2 : 1) : \
|
||||
GENERAL_REGNO_P(REGNO)? \
|
||||
((GET_MODE_SIZE(MODE)+UNITS_PER_WORD-1) / UNITS_PER_WORD) : \
|
||||
ACCESS_REGNO_P(REGNO)? \
|
||||
((GET_MODE_SIZE(MODE)+32-1) / 32) : \
|
||||
1)
|
||||
|
||||
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
|
||||
|
@ -424,6 +437,9 @@ if (INTEGRAL_MODE_P (MODE) && \
|
|||
GET_MODE_CLASS (MODE) == MODE_CC : \
|
||||
FRAME_REGNO_P(REGNO)? \
|
||||
(enum machine_mode) (MODE) == Pmode : \
|
||||
ACCESS_REGNO_P(REGNO)? \
|
||||
(((MODE) == SImode || ((enum machine_mode) (MODE) == Pmode)) \
|
||||
&& (HARD_REGNO_NREGS(REGNO, MODE) == 1 || !((REGNO) & 1))) : \
|
||||
0)
|
||||
|
||||
#define MODES_TIEABLE_P(MODE1, MODE2) \
|
||||
|
@ -435,48 +451,54 @@ if (INTEGRAL_MODE_P (MODE) && \
|
|||
#define CLASS_MAX_NREGS(CLASS, MODE) \
|
||||
((CLASS) == FP_REGS ? \
|
||||
(GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT ? 2 : 1) : \
|
||||
(CLASS) == ACCESS_REGS ? \
|
||||
(GET_MODE_SIZE (MODE) + 32 - 1) / 32 : \
|
||||
(GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
|
||||
|
||||
/* If a 4-byte value is loaded into a FPR, it is placed into the
|
||||
*upper* half of the register, not the lower. Therefore, we
|
||||
cannot use SUBREGs to switch between modes in FP registers. */
|
||||
cannot use SUBREGs to switch between modes in FP registers.
|
||||
Likewise for access registers, since they have only half the
|
||||
word size on 64-bit. */
|
||||
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
|
||||
(GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
|
||||
? reg_classes_intersect_p (FP_REGS, CLASS) : 0)
|
||||
? reg_classes_intersect_p (FP_REGS, CLASS) \
|
||||
|| reg_classes_intersect_p (ACCESS_REGS, CLASS) : 0)
|
||||
|
||||
/* Register classes. */
|
||||
|
||||
/* We use the following register classes:
|
||||
GENERAL_REGS All general purpose registers
|
||||
CC_REGS Contains only the condition code register
|
||||
ADDR_REGS All general purpose registers except %r0
|
||||
(These registers can be used in address generation)
|
||||
ADDR_CC_REGS Union of ADDR_REGS and CC_REGS
|
||||
GENERAL_CC_REGS Union of GENERAL_REGS and CC_REGS
|
||||
FP_REGS All floating point registers
|
||||
CC_REGS The condition code register
|
||||
ACCESS_REGS The access registers
|
||||
|
||||
GENERAL_FP_REGS Union of GENERAL_REGS and FP_REGS
|
||||
ADDR_FP_REGS Union of ADDR_REGS and FP_REGS
|
||||
GENERAL_CC_REGS Union of GENERAL_REGS and CC_REGS
|
||||
ADDR_CC_REGS Union of ADDR_REGS and CC_REGS
|
||||
|
||||
NO_REGS No registers
|
||||
ALL_REGS All registers
|
||||
|
||||
Note that the 'fake' frame pointer and argument pointer registers
|
||||
are included amongst the address registers here. The condition
|
||||
code register is only included in ALL_REGS. */
|
||||
are included amongst the address registers here. */
|
||||
|
||||
enum reg_class
|
||||
{
|
||||
NO_REGS, CC_REGS, ADDR_REGS, GENERAL_REGS,
|
||||
NO_REGS, CC_REGS, ADDR_REGS, GENERAL_REGS, ACCESS_REGS,
|
||||
ADDR_CC_REGS, GENERAL_CC_REGS,
|
||||
FP_REGS, ADDR_FP_REGS, GENERAL_FP_REGS,
|
||||
ALL_REGS, LIM_REG_CLASSES
|
||||
};
|
||||
#define N_REG_CLASSES (int) LIM_REG_CLASSES
|
||||
|
||||
#define REG_CLASS_NAMES \
|
||||
{ "NO_REGS", "CC_REGS", "ADDR_REGS", "GENERAL_REGS", "ADDR_CC_REGS", \
|
||||
"GENERAL_CC_REGS", "FP_REGS", "ADDR_FP_REGS", "GENERAL_FP_REGS", "ALL_REGS" }
|
||||
#define REG_CLASS_NAMES \
|
||||
{ "NO_REGS", "CC_REGS", "ADDR_REGS", "GENERAL_REGS", "ACCESS_REGS", \
|
||||
"ADDR_CC_REGS", "GENERAL_CC_REGS", \
|
||||
"FP_REGS", "ADDR_FP_REGS", "GENERAL_FP_REGS", "ALL_REGS" }
|
||||
|
||||
/* Class -> register mapping. */
|
||||
#define REG_CLASS_CONTENTS \
|
||||
|
@ -485,12 +507,13 @@ enum reg_class
|
|||
{ 0x00000000, 0x00000002 }, /* CC_REGS */ \
|
||||
{ 0x0000fffe, 0x0000000d }, /* ADDR_REGS */ \
|
||||
{ 0x0000ffff, 0x0000000d }, /* GENERAL_REGS */ \
|
||||
{ 0x00000000, 0x00000030 }, /* ACCESS_REGS */ \
|
||||
{ 0x0000fffe, 0x0000000f }, /* ADDR_CC_REGS */ \
|
||||
{ 0x0000ffff, 0x0000000f }, /* GENERAL_CC_REGS */ \
|
||||
{ 0xffff0000, 0x00000000 }, /* FP_REGS */ \
|
||||
{ 0xfffffffe, 0x0000000d }, /* ADDR_FP_REGS */ \
|
||||
{ 0xffffffff, 0x0000000d }, /* GENERAL_FP_REGS */ \
|
||||
{ 0xffffffff, 0x0000000f }, /* ALL_REGS */ \
|
||||
{ 0xffffffff, 0x0000003f }, /* ALL_REGS */ \
|
||||
}
|
||||
|
||||
/* Register -> class mapping. */
|
||||
|
@ -543,7 +566,8 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
|
|||
((C) == 'a' ? ADDR_REGS : \
|
||||
(C) == 'd' ? GENERAL_REGS : \
|
||||
(C) == 'f' ? FP_REGS : \
|
||||
(C) == 'c' ? CC_REGS : NO_REGS)
|
||||
(C) == 'c' ? CC_REGS : \
|
||||
(C) == 't' ? ACCESS_REGS : NO_REGS)
|
||||
|
||||
#define CONST_OK_FOR_CONSTRAINT_P(VALUE, C, STR) \
|
||||
s390_const_ok_for_constraint_p ((VALUE), (C), (STR))
|
||||
|
@ -976,7 +1000,7 @@ extern int flag_pic;
|
|||
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", \
|
||||
"%f0", "%f2", "%f4", "%f6", "%f1", "%f3", "%f5", "%f7", \
|
||||
"%f8", "%f10", "%f12", "%f14", "%f9", "%f11", "%f13", "%f15", \
|
||||
"%ap", "%cc", "%fp", "%rp" \
|
||||
"%ap", "%cc", "%fp", "%rp", "%a0", "%a1" \
|
||||
}
|
||||
|
||||
/* Emit a dtp-relative reference to a TLS variable. */
|
||||
|
|
|
@ -112,7 +112,6 @@
|
|||
(UNSPEC_INDNTPOFF 505)
|
||||
|
||||
; TLS support
|
||||
(UNSPEC_TP 510)
|
||||
(UNSPEC_TLSLDM_NTPOFF 511)
|
||||
(UNSPEC_TLS_LOAD 512)
|
||||
|
||||
|
@ -887,9 +886,9 @@
|
|||
|
||||
(define_insn "*movdi_64"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand"
|
||||
"=d,d,d,d,d,d,d,d,m,!*f,!*f,!*f,!R,!T,?Q")
|
||||
"=d,d,d,d,d,d,d,d,m,!*f,!*f,!*f,!R,!T,d,t,Q,t,?Q")
|
||||
(match_operand:DI 1 "general_operand"
|
||||
"K,N0HD0,N1HD0,N2HD0,N3HD0,L,d,m,d,*f,R,T,*f,*f,?Q"))]
|
||||
"K,N0HD0,N1HD0,N2HD0,N3HD0,L,d,m,d,*f,R,T,*f,*f,t,d,t,Q,?Q"))]
|
||||
"TARGET_64BIT"
|
||||
"@
|
||||
lghi\t%0,%h1
|
||||
|
@ -906,10 +905,47 @@
|
|||
ldy\t%0,%1
|
||||
std\t%1,%0
|
||||
stdy\t%1,%0
|
||||
#
|
||||
#
|
||||
stam\t%1,%N1,%S0
|
||||
lam\t%0,%N0,%S1
|
||||
#"
|
||||
[(set_attr "op_type" "RI,RI,RI,RI,RI,RXY,RRE,RXY,RXY,RR,RX,RXY,RX,RXY,SS")
|
||||
[(set_attr "op_type" "RI,RI,RI,RI,RI,RXY,RRE,RXY,RXY,RR,RX,RXY,RX,RXY,NN,NN,RS,RS,SS")
|
||||
(set_attr "type" "*,*,*,*,*,la,lr,load,store,floadd,floadd,floadd,
|
||||
fstored,fstored,cs")])
|
||||
fstored,fstored,*,*,*,*,cs")])
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_operand:DI 1 "register_operand" ""))]
|
||||
"TARGET_64BIT && ACCESS_REG_P (operands[1])"
|
||||
[(set (match_dup 2) (match_dup 3))
|
||||
(set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32)))
|
||||
(set (strict_low_part (match_dup 2)) (match_dup 4))]
|
||||
"operands[2] = gen_lowpart (SImode, operands[0]);
|
||||
s390_split_access_reg (operands[1], &operands[4], &operands[3]);")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_operand:DI 1 "register_operand" ""))]
|
||||
"TARGET_64BIT && ACCESS_REG_P (operands[0])
|
||||
&& dead_or_set_p (insn, operands[1])"
|
||||
[(set (match_dup 3) (match_dup 2))
|
||||
(set (match_dup 1) (lshiftrt:DI (match_dup 1) (const_int 32)))
|
||||
(set (match_dup 4) (match_dup 2))]
|
||||
"operands[2] = gen_lowpart (SImode, operands[1]);
|
||||
s390_split_access_reg (operands[0], &operands[3], &operands[4]);")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_operand:DI 1 "register_operand" ""))]
|
||||
"TARGET_64BIT && ACCESS_REG_P (operands[0])
|
||||
&& !dead_or_set_p (insn, operands[1])"
|
||||
[(set (match_dup 3) (match_dup 2))
|
||||
(set (match_dup 1) (rotate:DI (match_dup 1) (const_int 32)))
|
||||
(set (match_dup 4) (match_dup 2))
|
||||
(set (match_dup 1) (rotate:DI (match_dup 1) (const_int 32)))]
|
||||
"operands[2] = gen_lowpart (SImode, operands[1]);
|
||||
s390_split_access_reg (operands[0], &operands[3], &operands[4]);")
|
||||
|
||||
(define_insn "*movdi_31"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,Q,d,o,!*f,!*f,!*f,!R,!T,Q")
|
||||
|
@ -1063,9 +1099,9 @@
|
|||
|
||||
(define_insn "*movsi_zarch"
|
||||
[(set (match_operand:SI 0 "nonimmediate_operand"
|
||||
"=d,d,d,d,d,d,d,R,T,!*f,!*f,!*f,!R,!T,?Q")
|
||||
"=d,d,d,d,d,d,d,R,T,!*f,!*f,!*f,!R,!T,d,t,Q,t,?Q")
|
||||
(match_operand:SI 1 "general_operand"
|
||||
"K,N0HS0,N1HS0,L,d,R,T,d,d,*f,R,T,*f,*f,?Q"))]
|
||||
"K,N0HS0,N1HS0,L,d,R,T,d,d,*f,R,T,*f,*f,t,d,t,Q,?Q"))]
|
||||
"TARGET_ZARCH"
|
||||
"@
|
||||
lhi\t%0,%h1
|
||||
|
@ -1082,13 +1118,17 @@
|
|||
ley\t%0,%1
|
||||
ste\t%1,%0
|
||||
stey\t%1,%0
|
||||
ear\t%0,%1
|
||||
sar\t%0,%1
|
||||
stam\t%1,%1,%S0
|
||||
lam\t%0,%0,%S1
|
||||
#"
|
||||
[(set_attr "op_type" "RI,RI,RI,RXY,RR,RX,RXY,RX,RXY,RR,RX,RXY,RX,RXY,SS")
|
||||
(set_attr "type" "*,*,*,la,lr,load,load,store,store,floads,floads,floads,fstores,fstores,cs")])
|
||||
[(set_attr "op_type" "RI,RI,RI,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,floads,floads,floads,fstores,fstores,*,*,*,*,cs")])
|
||||
|
||||
(define_insn "*movsi_esa"
|
||||
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,R,!*f,!*f,!R,?Q")
|
||||
(match_operand:SI 1 "general_operand" "K,d,R,d,*f,R,*f,?Q"))]
|
||||
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,R,!*f,!*f,!R,d,t,Q,t,?Q")
|
||||
(match_operand:SI 1 "general_operand" "K,d,R,d,*f,R,*f,t,d,t,Q,?Q"))]
|
||||
"!TARGET_ZARCH"
|
||||
"@
|
||||
lhi\t%0,%h1
|
||||
|
@ -1098,9 +1138,13 @@
|
|||
ler\t%0,%1
|
||||
le\t%0,%1
|
||||
ste\t%1,%0
|
||||
ear\t%0,%1
|
||||
sar\t%0,%1
|
||||
stam\t%1,%1,%S0
|
||||
lam\t%0,%0,%S1
|
||||
#"
|
||||
[(set_attr "op_type" "RI,RR,RX,RX,RR,RX,RX,SS")
|
||||
(set_attr "type" "*,lr,load,store,floads,floads,fstores,cs")])
|
||||
[(set_attr "op_type" "RI,RR,RX,RX,RR,RX,RX,RRE,RRE,RS,RS,SS")
|
||||
(set_attr "type" "*,lr,load,store,floads,floads,fstores,*,*,*,*,cs")])
|
||||
|
||||
(define_peephole2
|
||||
[(set (match_operand:SI 0 "register_operand" "")
|
||||
|
@ -1321,15 +1365,16 @@
|
|||
;
|
||||
|
||||
(define_insn "movstrictsi"
|
||||
[(set (strict_low_part (match_operand:SI 0 "register_operand" "+d,d,d"))
|
||||
(match_operand:SI 1 "general_operand" "d,R,T"))]
|
||||
[(set (strict_low_part (match_operand:SI 0 "register_operand" "+d,d,d,d"))
|
||||
(match_operand:SI 1 "general_operand" "d,R,T,t"))]
|
||||
"TARGET_64BIT"
|
||||
"@
|
||||
lr\t%0,%1
|
||||
l\t%0,%1
|
||||
ly\t%0,%1"
|
||||
[(set_attr "op_type" "RR,RX,RXY")
|
||||
(set_attr "type" "lr,load,load")])
|
||||
ly\t%0,%1
|
||||
ear\t%0,%1"
|
||||
[(set_attr "op_type" "RR,RX,RXY,RRE")
|
||||
(set_attr "type" "lr,load,load,*")])
|
||||
|
||||
;
|
||||
; movdf instruction pattern(s).
|
||||
|
@ -7438,46 +7483,34 @@
|
|||
;;- Thread-local storage support.
|
||||
;;
|
||||
|
||||
(define_insn "get_tp_64"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=??d,Q")
|
||||
(unspec:DI [(const_int 0)] UNSPEC_TP))]
|
||||
(define_expand "get_tp_64"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "") (reg:DI 36))]
|
||||
"TARGET_64BIT"
|
||||
"@
|
||||
ear\t%0,%%a0\;sllg\t%0,%0,32\;ear\t%0,%%a1
|
||||
stam\t%%a0,%%a1,%S0"
|
||||
[(set_attr "op_type" "NN,RS")
|
||||
(set_attr "atype" "reg,*")
|
||||
(set_attr "type" "o3,*")
|
||||
(set_attr "length" "14,*")])
|
||||
"")
|
||||
|
||||
(define_insn "get_tp_31"
|
||||
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,Q")
|
||||
(unspec:SI [(const_int 0)] UNSPEC_TP))]
|
||||
(define_expand "get_tp_31"
|
||||
[(set (match_operand:SI 0 "nonimmediate_operand" "") (reg:SI 36))]
|
||||
"!TARGET_64BIT"
|
||||
"@
|
||||
ear\t%0,%%a0
|
||||
stam\t%%a0,%%a0,%S0"
|
||||
[(set_attr "op_type" "RRE,RS")])
|
||||
"")
|
||||
|
||||
(define_insn "set_tp_64"
|
||||
[(unspec_volatile [(match_operand:DI 0 "general_operand" "??d,Q")] UNSPECV_SET_TP)
|
||||
(clobber (match_scratch:SI 1 "=d,X"))]
|
||||
(define_expand "set_tp_64"
|
||||
[(set (reg:DI 36) (match_operand:DI 0 "nonimmediate_operand" ""))
|
||||
(unspec_volatile [(reg:DI 36)] UNSPECV_SET_TP)]
|
||||
"TARGET_64BIT"
|
||||
"@
|
||||
sar\t%%a1,%0\;srlg\t%1,%0,32\;sar\t%%a0,%1
|
||||
lam\t%%a0,%%a1,%S0"
|
||||
[(set_attr "op_type" "NN,RS")
|
||||
(set_attr "atype" "reg,*")
|
||||
(set_attr "type" "o3,*")
|
||||
(set_attr "length" "14,*")])
|
||||
"")
|
||||
|
||||
(define_insn "set_tp_31"
|
||||
[(unspec_volatile [(match_operand:SI 0 "general_operand" "d,Q")] UNSPECV_SET_TP)]
|
||||
(define_expand "set_tp_31"
|
||||
[(set (reg:SI 36) (match_operand:SI 0 "nonimmediate_operand" ""))
|
||||
(unspec_volatile [(reg:SI 36)] UNSPECV_SET_TP)]
|
||||
"!TARGET_64BIT"
|
||||
"@
|
||||
sar\t%%a0,%0
|
||||
lam\t%%a0,%%a0,%S0"
|
||||
[(set_attr "op_type" "RRE,RS")])
|
||||
"")
|
||||
|
||||
(define_insn "*set_tp"
|
||||
[(unspec_volatile [(reg 36)] UNSPECV_SET_TP)]
|
||||
""
|
||||
""
|
||||
[(set_attr "type" "none")
|
||||
(set_attr "length" "0")])
|
||||
|
||||
(define_insn "*tls_load_64"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
|
|
Loading…
Add table
Reference in a new issue