From c5aa1d125c72e027f99fce58cc5701ab3f269d9d Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Wed, 3 Nov 2004 21:39:48 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 26 ++++++++ gcc/config/s390/s390-protos.h | 1 + gcc/config/s390/s390.c | 24 ++++++-- gcc/config/s390/s390.h | 66 ++++++++++++++------- gcc/config/s390/s390.md | 135 ++++++++++++++++++++++++++---------------- 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 + + * 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 * 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..fbce222 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") -- 2.7.4