aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2004-11-03 21:39:48 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2004-11-03 21:39:48 +0000
commitc5aa1d125c72e027f99fce58cc5701ab3f269d9d (patch)
tree4b3981220f83df1f967208ac51682a2b2feba471
parent57f60923b282714a7a0cdc5965991b20fe07e5eb (diff)
downloadgcc-c5aa1d125c72e027f99fce58cc5701ab3f269d9d.zip
gcc-c5aa1d125c72e027f99fce58cc5701ab3f269d9d.tar.gz
gcc-c5aa1d125c72e027f99fce58cc5701ab3f269d9d.tar.bz2
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
-rw-r--r--gcc/ChangeLog26
-rw-r--r--gcc/config/s390/s390-protos.h1
-rw-r--r--gcc/config/s390/s390.c24
-rw-r--r--gcc/config/s390/s390.h66
-rw-r--r--gcc/config/s390/s390.md135
5 files changed, 176 insertions, 76 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3f19c86..425cf0d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 4b405f2..3b21d03 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -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);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index d56624c..8ba78a2 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -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;
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index 013fd93..0116a66 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -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. */
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 229e3e0..fbce222d 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -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")