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)
#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:
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.
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, \
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, \
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 ()
{ 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. */
(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) \
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) \
#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 \
{ 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. */
((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))
"%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. */
(UNSPEC_INDNTPOFF 505)
; TLS support
- (UNSPEC_TP 510)
(UNSPEC_TLSLDM_NTPOFF 511)
(UNSPEC_TLS_LOAD 512)
(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
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")
(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
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
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" "")
;
(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).
;;- 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")