\f
;; zero extension instructions
-(define_insn "zero_extendqidi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
- (zero_extend:DI (match_operand:QI 1 "general_operand" "dm")))]
+;; two special patterns to match various post_inc/pre_dec patterns
+(define_insn_and_split "*zero_extend_inc"
+ [(set (match_operand 0 "post_inc_operand" "")
+ (zero_extend (match_operand 1 "register_operand" "")))]
+ "GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_INT &&
+ GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT &&
+ GET_MODE_SIZE (GET_MODE (operands[0])) == GET_MODE_SIZE (GET_MODE (operands[1])) * 2"
+ "#"
+ ""
+ [(set (match_dup 0)
+ (const_int 0))
+ (set (match_dup 0)
+ (match_dup 1))]
+{
+ operands[0] = adjust_address (operands[0], GET_MODE (operands[1]), 0);
+})
+
+(define_insn_and_split "*zero_extend_dec"
+ [(set (match_operand 0 "pre_dec_operand" "")
+ (zero_extend (match_operand 1 "register_operand" "")))]
+ "(GET_MODE (operands[0]) != HImode || XEXP (XEXP (operands[0], 0), 0) != stack_pointer_rtx) &&
+ GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_INT &&
+ GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT &&
+ GET_MODE_SIZE (GET_MODE (operands[0])) == GET_MODE_SIZE (GET_MODE (operands[1])) * 2"
+ "#"
""
+ [(set (match_dup 0)
+ (match_dup 1))
+ (set (match_dup 0)
+ (const_int 0))]
{
- CC_STATUS_INIT;
- operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- return "moveq #0,%0\;moveq #0,%2\;move%.b %1,%2";
+ operands[0] = adjust_address (operands[0], GET_MODE (operands[1]), 0);
})
-(define_insn "zero_extendhidi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
- (zero_extend:DI (match_operand:HI 1 "general_operand" "rm")))]
+(define_insn_and_split "zero_extendqidi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extend:DI (match_operand:QI 1 "nonimmediate_src_operand" "")))]
+ ""
+ "#"
""
+ [(set (match_dup 2)
+ (zero_extend:SI (match_dup 1)))
+ (set (match_dup 3)
+ (const_int 0))]
{
- CC_STATUS_INIT;
- operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- return "moveq #0,%0\;moveq #0,%2\;move%.w %1,%2";
+ operands[2] = gen_lowpart (SImode, operands[0]);
+ operands[3] = gen_highpart (SImode, operands[0]);
+})
+
+(define_insn_and_split "zero_extendhidi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extend:DI (match_operand:HI 1 "nonimmediate_src_operand" "")))]
+ ""
+ "#"
+ ""
+ [(set (match_dup 2)
+ (zero_extend:SI (match_dup 1)))
+ (set (match_dup 3)
+ (const_int 0))]
+{
+ operands[2] = gen_lowpart (SImode, operands[0]);
+ operands[3] = gen_highpart (SImode, operands[0]);
})
-;; this is the canonical form for (lshiftrt:DI x 32)
(define_expand "zero_extendsidi2"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
- (zero_extend:DI (match_operand:SI 1 "general_operand" "")))]
+ (zero_extend:DI (match_operand:SI 1 "nonimmediate_src_operand" "")))]
""
"")
-(define_insn "*zero_extendsidi2_cf"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,m")
- (zero_extend:DI (match_operand:SI 1 "general_operand" "rm,r")))]
- "TARGET_COLDFIRE"
+(define_insn_and_split "*zero_extendsidi2"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (zero_extend:DI (match_operand:SI 1 "nonimmediate_src_operand" "")))]
+ "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
+ "#"
+ ""
+ [(set (match_dup 2)
+ (match_dup 1))
+ (set (match_dup 3)
+ (const_int 0))]
{
- CC_STATUS_INIT;
- if (GET_CODE (operands[0]) == REG)
- operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
- return "move%.l %1,%0\;clr%.l %0";
- else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
- return "clr%.l %0\;move%.l %1,%0";
- else
- operands[2] = adjust_address (operands[0], SImode, 4);
- if (GET_CODE (operands[1]) != REG || GET_CODE (operands[2]) != REG
- || REGNO (operands[1]) != REGNO (operands[2]))
- output_asm_insn ("move%.l %1,%2", operands);
- if (ADDRESS_REG_P (operands[0]))
- return "sub%.l %0,%0";
- else
- return "clr%.l %0";
+ operands[2] = gen_lowpart (SImode, operands[0]);
+ operands[3] = gen_highpart (SImode, operands[0]);
})
-(define_insn "*zero_extendsidi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
- (zero_extend:DI (match_operand:SI 1 "general_operand" "rm")))]
- "!TARGET_COLDFIRE"
-{
- CC_STATUS_INIT;
- if (GET_CODE (operands[0]) == REG)
- operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
- return "move%.l %1,%0\;clr%.l %0";
- else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
- return "clr%.l %0\;move%.l %1,%0";
- else
- operands[2] = adjust_address (operands[0], SImode, 4);
- if (GET_CODE (operands[1]) != REG || GET_CODE (operands[2]) != REG
- || REGNO (operands[1]) != REGNO (operands[2]))
- output_asm_insn ("move%.l %1,%2", operands);
- if (ADDRESS_REG_P (operands[0]))
- return "sub%.l %0,%0";
- else
- return "clr%.l %0";
-})
+(define_insn "*zero_extendhisi2_cf"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "rmS")))]
+ "TARGET_CFV4"
+ "mvz%.w %1,%0")
-(define_expand "zero_extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (const_int 0))
- (set (strict_low_part (match_dup 2))
- (match_operand:HI 1 "general_operand" ""))]
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "rmS")))]
""
- "
-{
- operands[1] = make_safe_from (operands[1], operands[0]);
- operands[2] = gen_lowpart_SUBREG (HImode, operands[0]);
-}")
+ "#")
(define_expand "zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "")
- (const_int 0))
- (set (strict_low_part (match_dup 2))
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{
- operands[1] = make_safe_from (operands[1], operands[0]);
- operands[2] = gen_lowpart_SUBREG (QImode, operands[0]);
-}")
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "")))]
+ "!TARGET_COLDFIRE"
+ "")
-(define_expand "zero_extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (const_int 0))
- (set (strict_low_part (match_dup 2))
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{
- operands[1] = make_safe_from (operands[1], operands[0]);
- operands[2] = gen_lowpart_SUBREG (QImode, operands[0]);
-}")
-\f
-;; Patterns to recognize zero-extend insns produced by the combiner.
-;; We don't allow both operands in memory, because of aliasing problems.
-;; Explicitly disallow two memory operands via the condition since reloading
-;; of this case will result in worse code than the uncombined patterns.
+(define_insn "*zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "dmS")))]
+ "!TARGET_COLDFIRE"
+ "#")
-(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=do<>,d<")
- (zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "r,mS")))]
- "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
-{
- if (DATA_REG_P (operands[0]))
- {
- if (TARGET_CFV4)
- return "mvz%.w %1,%0";
- if (GET_CODE (operands[1]) == REG
- && REGNO (operands[0]) == REGNO (operands[1]))
- return "and%.l #0xFFFF,%0";
- if (reg_mentioned_p (operands[0], operands[1]))
- return "move%.w %1,%0\;and%.l #0xFFFF,%0";
- return "clr%.l %0\;move%.w %1,%0";
- }
- else if (GET_CODE (operands[0]) == MEM
- && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
- return "move%.w %1,%0\;clr%.w %0";
- else if (GET_CODE (operands[0]) == MEM
- && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
- return "clr%.w %0\;move%.w %1,%0";
- else
- {
- output_asm_insn ("clr%.w %0", operands);
- operands[0] = adjust_address (operands[0], HImode, 2);
- return "move%.w %1,%0";
- }
-})
+(define_insn "*zero_extendqisi2_cfv4"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "dmS")))]
+ "TARGET_CFV4"
+ "mvz%.b %1,%0")
-(define_insn ""
- [(set (match_operand:HI 0 "nonimmediate_operand" "=do<>,d")
- (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
- "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "dmS")))]
+ ""
+ "#")
+
+;; these two pattern split everything else which isn't matched by
+;; something else above
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (zero_extend (match_operand 1 "nonimmediate_src_operand" "")))]
+ "!TARGET_CFV4 && reload_completed && reg_mentioned_p (operands[0], operands[1])"
+ [(set (strict_low_part (match_dup 2))
+ (match_dup 1))
+ (set (match_dup 0)
+ (match_op_dup 4 [(match_dup 0) (match_dup 3)]))]
{
- if (DATA_REG_P (operands[0]))
- {
- if (GET_CODE (operands[1]) == REG
- && REGNO (operands[0]) == REGNO (operands[1]))
- {
- if (TARGET_CFV4)
- return "mvz%.b %0,%0";
- return (!TARGET_COLDFIRE ? "and%.w #0xFF,%0" : "and%.l #0xFF,%0");
- }
- if (reg_mentioned_p (operands[0], operands[1]))
- {
- if (TARGET_CFV4)
- return "mvz%.b %1,%0";
- return (!TARGET_COLDFIRE ? "move%.b %1,%0\;and%.w #0xFF,%0"
- : "move%.b %1,%0\;and%.l #0xFF,%0");
- }
- return "clr%.w %0\;move%.b %1,%0";
- }
- else if (GET_CODE (operands[0]) == MEM
- && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
- {
- if (REGNO (XEXP (XEXP (operands[0], 0), 0))
- == STACK_POINTER_REGNUM)
- {
- output_asm_insn ("clr%.w %-", operands);
- operands[0] = gen_rtx_MEM (GET_MODE (operands[0]),
- plus_constant (stack_pointer_rtx, 1));
- return "move%.b %1,%0";
- }
- else
- return "move%.b %1,%0\;clr%.b %0";
- }
- else if (GET_CODE (operands[0]) == MEM
- && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
- return "clr%.b %0\;move%.b %1,%0";
- else
- {
- output_asm_insn ("clr%.b %0", operands);
- operands[0] = adjust_address (operands[0], QImode, 1);
- return "move%.b %1,%0";
- }
+ operands[2] = gen_lowpart (GET_MODE (operands[1]), operands[0]);
+ operands[3] = GEN_INT (GET_MODE_MASK (GET_MODE (operands[1])));
+ operands[4] = gen_rtx_AND (GET_MODE (operands[0]), operands[0], operands[3]);
})
-(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=do<>,d")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
- "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (zero_extend (match_operand 1 "nonimmediate_src_operand" "")))]
+ "!TARGET_CFV4 && reload_completed"
+ [(set (match_dup 0)
+ (const_int 0))
+ (set (strict_low_part (match_dup 2))
+ (match_dup 1))]
{
- if (DATA_REG_P (operands[0]))
- {
- if (TARGET_CFV4)
- return "mvz%.b %1,%0";
- if (GET_CODE (operands[1]) == REG
- && REGNO (operands[0]) == REGNO (operands[1]))
- return "and%.l #0xFF,%0";
- if (reg_mentioned_p (operands[0], operands[1]))
- return "move%.b %1,%0\;and%.l #0xFF,%0";
- return "clr%.l %0\;move%.b %1,%0";
- }
- else if (GET_CODE (operands[0]) == MEM
- && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
- {
- operands[0] = XEXP (XEXP (operands[0], 0), 0);
- return MOTOROLA ?
- "clr%.l -(%0)\;move%.b %1,(3,%0)" :
- "clrl %0@-\;moveb %1,%0@(3)";
- }
- else if (GET_CODE (operands[0]) == MEM
- && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
- {
- operands[0] = XEXP (XEXP (operands[0], 0), 0);
- return MOTOROLA ?
- "clr%.l (%0)+\;move%.b %1,(-1,%0)" :
- "clrl %0@+\;moveb %1,%0@(-1)";
- }
- else
- {
- output_asm_insn ("clr%.l %0", operands);
- operands[0] = adjust_address (operands[0], QImode, 3);
- return "move%.b %1,%0";
- }
+ operands[2] = gen_lowpart (GET_MODE (operands[1]), operands[0]);
})
\f
;; sign extension instructions
""
"")
+;; produced by split operations after reload finished
+(define_insn "*andsi3_split"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (and:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_int_operand" "i")))]
+ "reload_completed && !TARGET_COLDFIRE"
+{
+ return output_andsi3 (operands);
+})
+
(define_insn "andsi3_internal"
[(set (match_operand:SI 0 "not_sp_operand" "=m,d")
(and:SI (match_operand:SI 1 "general_operand" "%0,0")