m68k.c (post_inc_operand,pre_dec_operand): New.
* config/m68k/m68k.c (post_inc_operand,pre_dec_operand): New. * config/m68k/m68k.h (PREDICATE_CODES): add post_inc_operand, pre_dec_operand. * config/m68k/m68k.md (zero_extend*2): delay the splitting of the pattern until reload is finished to allow better code generation and split them completely into separate instrunctions. (*andsi3_split): New pattern. From-SVN: r85631
This commit is contained in:
parent
3589b69e2d
commit
9652c5316a
|
@ -1,3 +1,13 @@
|
|||
2004-08-06 Roman Zippel <zippel@linux-m68k.org>
|
||||
|
||||
* config/m68k/m68k.c (post_inc_operand,pre_dec_operand): New.
|
||||
* config/m68k/m68k.h (PREDICATE_CODES): add post_inc_operand,
|
||||
pre_dec_operand.
|
||||
* config/m68k/m68k.md (zero_extend*2): delay the splitting of the
|
||||
pattern until reload is finished to allow better code generation
|
||||
and split them completely into separate instrunctions.
|
||||
(*andsi3_split): New pattern.
|
||||
|
||||
2004-08-05 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* tree.c (handle_dll_attribute): Move here from i383/winnt.c.
|
||||
|
|
|
@ -3185,6 +3185,18 @@ memory_src_operand (rtx op, enum machine_mode mode)
|
|||
return memory_operand (op, mode);
|
||||
}
|
||||
|
||||
int
|
||||
post_inc_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return MEM_P (op) && GET_CODE (XEXP (op, 0)) == POST_INC;
|
||||
}
|
||||
|
||||
int
|
||||
pre_dec_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return MEM_P (op) && GET_CODE (XEXP (op, 0)) == PRE_DEC;
|
||||
}
|
||||
|
||||
/* Predicate that accepts only a pc-relative address. This is needed
|
||||
because pc-relative addresses don't satisfy the predicate
|
||||
"general_src_operand". */
|
||||
|
|
|
@ -1271,4 +1271,6 @@ extern int m68k_last_compare_had_fp_operands;
|
|||
{"valid_dbcc_comparison_p", {EQ, NE, GTU, LTU, GEU, LEU, \
|
||||
GT, LT, GE, LE}}, \
|
||||
{"extend_operator", {SIGN_EXTEND, ZERO_EXTEND}}, \
|
||||
{"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},
|
||||
{"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}}, \
|
||||
{"post_inc_operand", {MEM}}, \
|
||||
{"pre_dec_operand", {MEM}},
|
||||
|
|
|
@ -1136,236 +1136,153 @@
|
|||
|
||||
;; 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))]
|
||||
{
|
||||
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_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%.w %1,%2";
|
||||
operands[0] = adjust_address (operands[0], GET_MODE (operands[1]), 0);
|
||||
})
|
||||
|
||||
(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))]
|
||||
{
|
||||
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"
|
||||
{
|
||||
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_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_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_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))]
|
||||
{
|
||||
operands[1] = make_safe_from (operands[1], operands[0]);
|
||||
operands[2] = gen_lowpart_SUBREG (HImode, operands[0]);
|
||||
}")
|
||||
operands[2] = gen_lowpart (SImode, operands[0]);
|
||||
operands[3] = gen_highpart (SImode, operands[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_insn "zero_extendhisi2"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d")
|
||||
(zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "rmS")))]
|
||||
""
|
||||
"#")
|
||||
|
||||
(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]);
|
||||
}")
|
||||
|
||||
;; 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"
|
||||
(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 "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 (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";
|
||||
}
|
||||
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: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_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 (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";
|
||||
}
|
||||
})
|
||||
|
||||
(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"
|
||||
{
|
||||
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]);
|
||||
})
|
||||
|
||||
;; sign extension instructions
|
||||
|
@ -3131,6 +3048,16 @@
|
|||
""
|
||||
"")
|
||||
|
||||
;; 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")
|
||||
|
|
Loading…
Reference in New Issue