static int s390_branch_condition_mask (rtx);
static const char *s390_branch_condition_mnemonic (rtx, int);
static int check_mode (rtx, enum machine_mode *);
-static int general_s_operand (rtx, enum machine_mode, int);
static int s390_short_displacement (rtx);
static int s390_decompose_address (rtx, struct s390_address *);
static rtx get_thread_pointer (void);
return 0;
}
-/* Helper routine to implement s_operand and s_imm_operand.
+/* Return true if OP is a valid S-type operand.
OP is the current operation.
- MODE is the current operation mode.
- ALLOW_IMMEDIATE specifies whether immediate operands should
- be accepted or not. */
+ MODE is the current operation mode. */
-static int
-general_s_operand (register rtx op, enum machine_mode mode,
- int allow_immediate)
+int
+s_operand (rtx op, enum machine_mode mode)
{
struct s390_address addr;
&& GET_CODE (SUBREG_REG (op)) == MEM)
op = SUBREG_REG (op);
- switch (GET_CODE (op))
- {
- /* Constants are OK as s-operand if ALLOW_IMMEDIATE
- is true and we are still before reload. */
- case CONST_INT:
- case CONST_DOUBLE:
- if (!allow_immediate || reload_completed)
- return 0;
- return 1;
-
- /* Memory operands are OK unless they already use an
- index register. */
- case MEM:
- if (!s390_decompose_address (XEXP (op, 0), &addr))
- return 0;
- if (addr.indx)
- return 0;
- /* Do not allow literal pool references unless ALLOW_IMMEDIATE
- is true. This prevents compares between two literal pool
- entries from being accepted. */
- if (!allow_immediate
- && addr.base && REGNO (addr.base) == BASE_REGNUM)
- return 0;
- return 1;
-
- default:
- break;
- }
+ if (GET_CODE (op) != MEM)
+ return 0;
+ if (!s390_decompose_address (XEXP (op, 0), &addr))
+ return 0;
+ if (addr.indx)
+ return 0;
- return 0;
+ return 1;
}
-/* Return true if OP is a valid S-type operand.
- OP is the current operation.
- MODE is the current operation mode. */
+/* Return true if OP is a memory operand pointing to the
+ literal pool, or an immediate operand. */
-int
-s_operand (register rtx op, enum machine_mode mode)
+bool
+s390_pool_operand (rtx op)
{
- return general_s_operand (op, mode, 0);
-}
+ struct s390_address addr;
-/* Return true if OP is a valid S-type operand or an immediate
- operand that can be addressed as S-type operand by forcing
- it into the literal pool.
- OP is the current operation.
- MODE is the current operation mode. */
+ /* Just like memory_operand, allow (subreg (mem ...))
+ after reload. */
+ if (reload_completed
+ && GET_CODE (op) == SUBREG
+ && GET_CODE (SUBREG_REG (op)) == MEM)
+ op = SUBREG_REG (op);
-int
-s_imm_operand (register rtx op, enum machine_mode mode)
-{
- return general_s_operand (op, mode, 1);
+ switch (GET_CODE (op))
+ {
+ case CONST_INT:
+ case CONST_DOUBLE:
+ return true;
+
+ case MEM:
+ if (!s390_decompose_address (XEXP (op, 0), &addr))
+ return false;
+ if (addr.base && REG_P (addr.base) && REGNO (addr.base) == BASE_REGNUM)
+ return true;
+ if (addr.indx && REG_P (addr.indx) && REGNO (addr.indx) == BASE_REGNUM)
+ return true;
+ return false;
+
+ default:
+ return false;
+ }
}
/* Return true if OP a valid shift count operand.
[(set_attr "op_type" "RS,RSY")])
+; Compare (equality) instructions
+
+(define_insn "*cmpdi_cct"
+ [(set (reg 33)
+ (compare (match_operand:DI 0 "nonimmediate_operand" "d,d,d,m,Q")
+ (match_operand:DI 1 "general_operand" "d,K,m,d,Q")))]
+ "s390_match_ccmode (insn, CCTmode) && TARGET_64BIT
+ && (!s390_pool_operand (operands[0]) || !s390_pool_operand (operands[1]))"
+ "@
+ cgr\t%0,%1
+ cghi\t%0,%c1
+ cg\t%0,%1
+ cg\t%1,%0
+ clc\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "RRE,RI,RXY,RXY,SS")])
+
+(define_insn "*cmpsi_cct"
+ [(set (reg 33)
+ (compare (match_operand:SI 0 "nonimmediate_operand" "d,d,d,d,R,T,Q")
+ (match_operand:SI 1 "general_operand" "d,K,R,T,d,d,Q")))]
+ "s390_match_ccmode (insn, CCTmode)
+ && (!s390_pool_operand (operands[0]) || !s390_pool_operand (operands[1]))"
+ "@
+ cr\t%0,%1
+ chi\t%0,%c1
+ c\t%0,%1
+ cy\t%0,%1
+ c\t%1,%0
+ cy\t%1,%0
+ clc\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "RR,RI,RX,RXY,RX,RXY,SS")])
+
+
; Compare (signed) instructions
(define_insn "*cmpdi_ccs_sign"
[(set (reg 33)
(compare (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m"))
(match_operand:DI 0 "register_operand" "d,d")))]
- "s390_match_ccmode(insn, CCURmode) && TARGET_64BIT"
+ "s390_match_ccmode (insn, CCURmode) && TARGET_64BIT"
"@
clgfr\t%0,%1
clgf\t%0,%1"
(define_insn "*cmpdi_ccu"
[(set (reg 33)
- (compare (match_operand:DI 0 "register_operand" "d,d")
- (match_operand:DI 1 "general_operand" "d,m")))]
- "s390_match_ccmode(insn, CCUmode) && TARGET_64BIT"
+ (compare (match_operand:DI 0 "nonimmediate_operand" "d,d,Q")
+ (match_operand:DI 1 "general_operand" "d,m,Q")))]
+ "s390_match_ccmode (insn, CCUmode) && TARGET_64BIT
+ && (!s390_pool_operand (operands[0]) || !s390_pool_operand (operands[1]))"
"@
clgr\t%0,%1
- clg\t%0,%1"
- [(set_attr "op_type" "RRE,RXY")])
+ clg\t%0,%1
+ clc\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "RRE,RXY,SS")])
(define_insn "*cmpsi_ccu"
[(set (reg 33)
- (compare (match_operand:SI 0 "register_operand" "d,d,d")
- (match_operand:SI 1 "general_operand" "d,R,T")))]
- "s390_match_ccmode(insn, CCUmode)"
+ (compare (match_operand:SI 0 "nonimmediate_operand" "d,d,d,Q")
+ (match_operand:SI 1 "general_operand" "d,R,T,Q")))]
+ "s390_match_ccmode (insn, CCUmode)
+ && (!s390_pool_operand (operands[0]) || !s390_pool_operand (operands[1]))"
"@
clr\t%0,%1
cl\t%0,%1
- cly\t%0,%1"
- [(set_attr "op_type" "RR,RX,RXY")])
+ cly\t%0,%1
+ clc\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "RR,RX,RXY,SS")])
(define_insn "*cmphi_ccu"
[(set (reg 33)
- (compare (match_operand:HI 0 "register_operand" "d,d")
- (match_operand:HI 1 "s_imm_operand" "Q,S")))]
- "s390_match_ccmode(insn, CCUmode)"
+ (compare (match_operand:HI 0 "nonimmediate_operand" "d,d,Q")
+ (match_operand:HI 1 "general_operand" "Q,S,Q")))]
+ "s390_match_ccmode (insn, CCUmode)
+ && (!s390_pool_operand (operands[0]) || !s390_pool_operand (operands[1]))
+ && !register_operand (operands[1], HImode)"
"@
clm\t%0,3,%1
- clmy\t%0,3,%1"
- [(set_attr "op_type" "RS,RSY")])
+ clmy\t%0,3,%1
+ clc\t%O0(2,%R0),%1"
+ [(set_attr "op_type" "RS,RSY,SS")])
(define_insn "*cmpqi_ccu"
[(set (reg 33)
- (compare (match_operand:QI 0 "register_operand" "d,d")
- (match_operand:QI 1 "s_imm_operand" "Q,S")))]
- "s390_match_ccmode(insn, CCUmode)"
+ (compare (match_operand:QI 0 "nonimmediate_operand" "d,d,Q,S,Q")
+ (match_operand:QI 1 "general_operand" "Q,S,n,n,Q")))]
+ "s390_match_ccmode (insn, CCUmode)
+ && (!s390_pool_operand (operands[0]) || !s390_pool_operand (operands[1]))
+ && !register_operand (operands[1], QImode)"
"@
clm\t%0,1,%1
- clmy\t%0,1,%1"
- [(set_attr "op_type" "RS,RSY")])
-
-(define_insn "*cli"
- [(set (reg 33)
- (compare (match_operand:QI 0 "memory_operand" "Q,S")
- (match_operand:QI 1 "immediate_operand" "n,n")))]
- "s390_match_ccmode (insn, CCUmode)"
- "@
+ clmy\t%0,1,%1
cli\t%0,%b1
- cliy\t%0,%b1"
- [(set_attr "op_type" "SI,SIY")])
-
-(define_insn "*cmpdi_ccu_mem"
- [(set (reg 33)
- (compare (match_operand:DI 0 "s_operand" "Q")
- (match_operand:DI 1 "s_imm_operand" "Q")))]
- "s390_match_ccmode(insn, CCUmode)"
- "clc\t%O0(8,%R0),%1"
- [(set_attr "op_type" "SS")])
-
-(define_insn "*cmpsi_ccu_mem"
- [(set (reg 33)
- (compare (match_operand:SI 0 "s_operand" "Q")
- (match_operand:SI 1 "s_imm_operand" "Q")))]
- "s390_match_ccmode(insn, CCUmode)"
- "clc\t%O0(4,%R0),%1"
- [(set_attr "op_type" "SS")])
-
-(define_insn "*cmphi_ccu_mem"
- [(set (reg 33)
- (compare (match_operand:HI 0 "s_operand" "Q")
- (match_operand:HI 1 "s_imm_operand" "Q")))]
- "s390_match_ccmode(insn, CCUmode)"
- "clc\t%O0(2,%R0),%1"
- [(set_attr "op_type" "SS")])
-
-(define_insn "*cmpqi_ccu_mem"
- [(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "Q")
- (match_operand:QI 1 "s_imm_operand" "Q")))]
- "s390_match_ccmode(insn, CCUmode)"
- "clc\t%O0(1,%R0),%1"
- [(set_attr "op_type" "SS")])
+ cliy\t%0,%b1
+ clc\t%O0(1,%R0),%1"
+ [(set_attr "op_type" "RS,RSY,SI,SIY,SS")])
; DF instructions
(define_insn "*movstricthi"
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d,d"))
- (match_operand:HI 1 "s_imm_operand" "Q,S"))
+ (match_operand:HI 1 "memory_operand" "Q,S"))
(clobber (reg:CC 33))]
""
"@