2005-05-08 Stephane Carrez <stcarrez@nerim.fr>
+ * config/m68hc11/predicates.md (reg_or_some_mem_operand): Do not allow
+ the 68HC12 address indirect addressing mode as it is not supported by
+ bset and bclr.
+ * config/m68hc11/m68hc11-protos.h (m68hc11_valid_addressing_p): Declare.
+ (m68hc11_add_mode): Declare.
+ * config/m68hc11/m68hc11.c (m68hc11_valid_addressing_p): Rename from
+ register_indirect_p and export it.
+ (m68hc11_z_replacement): Use emit_insn_after when adding the save Z
+ instruction so that it is part of the good BB.
+ (m68hc11_gen_movhi): Fix invalid generation of indexed indirect
+ addressing with movw.
+ (m68hc11_gen_movqi): Use pula and pulb instead of lda and ldb for
+ 68HC12.
+ * config/m68hc11/m68hc11.h (ADDR_STRICT, ADDR_INCDEC, ADDR_INDEXED,
+ ADDR_OFFSET, ADDR_INDIRECT, ADDR__CONST): Moved from m68hc11.c.
+ * config/m68hc11/m68hc11.md ("movhi_const0"): Use this pattern only
+ for 68HC11.
+ ("*movhi_68hc12"): Handle movhi_const0.
+ ("*subhi3", "subqi3"): Use general_operand for operand 1.
+ ("*subhi3_zext"): Likewise.
+
+2005-05-08 Stephane Carrez <stcarrez@nerim.fr>
+
PR target/19051
* config/m68hc11/m68hc11.md ("mulqi3"): Use general_operand for operand
1 and fix constraints.
extern void m68hc11_split_logical (enum machine_mode, int, rtx*);
extern int m68hc11_register_indirect_p (rtx, enum machine_mode);
+extern int m68hc11_valid_addressing_p (rtx, enum machine_mode, int);
extern int symbolic_memory_operand (rtx, enum machine_mode);
extern HOST_WIDE_INT m68hc11_min_offset;
extern HOST_WIDE_INT m68hc11_max_offset;
+extern int m68hc11_addr_mode;
#endif /* HAVE_MACHINE_MODES */
#endif /* RTX_CODE */
static void m68hc11_emit_logical (enum machine_mode, int, rtx *);
static void m68hc11_reorg (void);
static int go_if_legitimate_address_internal (rtx, enum machine_mode, int);
-static int register_indirect_p (rtx, enum machine_mode, int);
static rtx m68hc11_expand_compare (enum rtx_code, rtx, rtx);
static int must_parenthesize (rtx);
static int m68hc11_address_cost (rtx);
This is 1 for 68HC11 and 0 for 68HC12. */
int m68hc11_sp_correction;
-#define ADDR_STRICT 0x01 /* Accept only registers in class A_REGS */
-#define ADDR_INCDEC 0x02 /* Post/Pre inc/dec */
-#define ADDR_INDEXED 0x04 /* D-reg index */
-#define ADDR_OFFSET 0x08
-#define ADDR_INDIRECT 0x10 /* Accept (mem (mem ...)) for [n,X] */
-#define ADDR_CONST 0x20 /* Accept const and symbol_ref */
-
int m68hc11_addr_mode;
int m68hc11_mov_addr_mode;
/* Return 1 if the operand is a valid indexed addressing mode.
For 68hc11: n,r with n in [0..255] and r in A_REGS class
For 68hc12: n,r no constraint on the constant, r in A_REGS class. */
-static int
-register_indirect_p (rtx operand, enum machine_mode mode, int addr_mode)
+int
+m68hc11_valid_addressing_p (rtx operand, enum machine_mode mode, int addr_mode)
{
rtx base, offset;
{
case MEM:
if ((addr_mode & ADDR_INDIRECT) && GET_MODE_SIZE (mode) <= 2)
- return register_indirect_p (XEXP (operand, 0), mode,
- addr_mode & (ADDR_STRICT | ADDR_OFFSET));
+ return m68hc11_valid_addressing_p (XEXP (operand, 0), mode,
+ addr_mode & (ADDR_STRICT | ADDR_OFFSET));
return 0;
case POST_INC:
case POST_DEC:
case PRE_DEC:
if (addr_mode & ADDR_INCDEC)
- return register_indirect_p (XEXP (operand, 0), mode,
- addr_mode & ADDR_STRICT);
+ return m68hc11_valid_addressing_p (XEXP (operand, 0), mode,
+ addr_mode & ADDR_STRICT);
return 0;
case PLUS:
return 1;
addr_mode = m68hc11_mov_addr_mode | (reload_completed ? ADDR_STRICT : 0);
- if (!register_indirect_p (operand, mode, addr_mode))
+ if (!m68hc11_valid_addressing_p (operand, mode, addr_mode))
return 0;
if (TARGET_M6812 && GET_CODE (operand) == PLUS
operand = XEXP (operand, 0);
addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
- return register_indirect_p (operand, mode, addr_mode);
+ return m68hc11_valid_addressing_p (operand, mode, addr_mode);
}
static int
return 1;
}
addr_mode = m68hc11_addr_mode | (strict ? ADDR_STRICT : 0);
- if (register_indirect_p (operand, mode, addr_mode))
+ if (m68hc11_valid_addressing_p (operand, mode, addr_mode))
{
return 1;
}
operand = XEXP (operand, 0);
addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
- return register_indirect_p (operand, mode, addr_mode);
+ return m68hc11_valid_addressing_p (operand, mode, addr_mode);
}
return 0;
}
if (TARGET_M6812)
{
- if (IS_STACK_PUSH (operands[0]) && H_REG_P (operands[1]))
+ rtx from = operands[1];
+ rtx to = operands[0];
+
+ if (IS_STACK_PUSH (to) && H_REG_P (from))
{
cc_status = cc_prev_status;
- switch (REGNO (operands[1]))
+ switch (REGNO (from))
{
case HARD_X_REGNUM:
case HARD_Y_REGNUM:
}
return;
}
- if (IS_STACK_POP (operands[1]) && H_REG_P (operands[0]))
+ if (IS_STACK_POP (from) && H_REG_P (to))
{
cc_status = cc_prev_status;
- switch (REGNO (operands[0]))
+ switch (REGNO (to))
{
case HARD_X_REGNUM:
case HARD_Y_REGNUM:
else
output_asm_insn ("st%1\t%0", operands);
}
+
+ /* The 68hc12 does not support (MEM:HI (MEM:HI)) with the movw
+ instruction. We have to use a scratch register as temporary location.
+ Trying to use a specific pattern or constrain failed. */
+ else if (GET_CODE (to) == MEM && GET_CODE (XEXP (to, 0)) == MEM)
+ {
+ rtx ops[4];
+
+ ops[0] = to;
+ ops[2] = from;
+ ops[3] = 0;
+ if (dead_register_here (insn, d_reg))
+ ops[1] = d_reg;
+ else if (dead_register_here (insn, ix_reg))
+ ops[1] = ix_reg;
+ else if (dead_register_here (insn, iy_reg))
+ ops[1] = iy_reg;
+ else
+ {
+ ops[1] = d_reg;
+ ops[3] = d_reg;
+ output_asm_insn ("psh%3", ops);
+ }
+
+ ops[0] = to;
+ ops[2] = from;
+ output_asm_insn ("ld%1\t%2", ops);
+ output_asm_insn ("st%1\t%0", ops);
+ if (ops[3])
+ output_asm_insn ("pul%3", ops);
+ }
+
+ /* Use movw for non-null constants or when we are clearing
+ a volatile memory reference. However, this is possible
+ only if the memory reference has a small offset or is an
+ absolute address. */
+ else if (GET_CODE (from) == CONST_INT
+ && INTVAL (from) == 0
+ && (MEM_VOLATILE_P (to) == 0
+ || m68hc11_small_indexed_indirect_p (to, HImode) == 0))
+ {
+ output_asm_insn ("clr\t%h0", operands);
+ output_asm_insn ("clr\t%b0", operands);
+ }
else
{
- rtx from = operands[1];
- rtx to = operands[0];
-
if ((m68hc11_register_indirect_p (from, GET_MODE (from))
&& !m68hc11_small_indexed_indirect_p (from, GET_MODE (from)))
|| (m68hc11_register_indirect_p (to, GET_MODE (to))
ops[0] = to;
ops[1] = operands[2];
m68hc11_gen_movhi (insn, ops);
+ return;
}
else
{
fatal_insn ("move insn not handled", insn);
}
}
- else
- {
- if (GET_CODE (from) == CONST_INT && INTVAL (from) == 0)
- {
- output_asm_insn ("clr\t%h0", operands);
- output_asm_insn ("clr\t%b0", operands);
- }
- else
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("movw\t%1,%0", operands);
- }
- }
+ else
+ {
+ m68hc11_notice_keep_cc (operands[0]);
+ output_asm_insn ("movw\t%1,%0", operands);
+ }
}
return;
}
}
else if (H_REG_P (operands[0]))
{
- if (Q_REG_P (operands[0]))
- output_asm_insn ("lda%0\t%b1", operands);
+ if (IS_STACK_POP (operands[1]))
+ output_asm_insn ("pul%b0", operands);
+ else if (Q_REG_P (operands[0]))
+ output_asm_insn ("lda%0\t%b1", operands);
else if (D_REG_P (operands[0]))
output_asm_insn ("ldab\t%b1", operands);
else
\f
/* Addressing modes, and classification of registers for them. */
+#define ADDR_STRICT 0x01 /* Accept only registers in class A_REGS */
+#define ADDR_INCDEC 0x02 /* Post/Pre inc/dec */
+#define ADDR_INDEXED 0x04 /* D-reg index */
+#define ADDR_OFFSET 0x08
+#define ADDR_INDIRECT 0x10 /* Accept (mem (mem ...)) for [n,X] */
+#define ADDR_CONST 0x20 /* Accept const and symbol_ref */
+
/* The 68HC12 has all the post/pre increment/decrement modes. */
#define HAVE_POST_INCREMENT (TARGET_M6812 && TARGET_AUTO_INC_DEC)
#define HAVE_PRE_INCREMENT (TARGET_M6812 && TARGET_AUTO_INC_DEC)
DONE;")
(define_insn_and_split "movdf_internal"
- [(set (match_operand:DF 0 "non_push_operand" "=mu,U,!u,U,m,m,!u")
- (match_operand:DF 1 "general_operand" "G,iU,iU,!u,mi,!u,!mu"))
+ [(set (match_operand:DF 0 "non_push_operand" "=mu,U,m,!u,U,m,!u")
+ (match_operand:DF 1 "general_operand" "G,iU,mi,iU,!u,!u,!mu"))
(clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
""
"#"
}
}")
-(define_insn "movhi_const0"
- [(set (match_operand:HI 0 "splitable_operand" "=d,A,um")
- (const_int 0))]
- ""
- "@
- clra\\n\\tclrb
- ld%0\\t#0
- clr\\t%b0\\n\\tclr\\t%h0")
-
(define_insn "*movhi_68hc12"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,U,U,m,!u")
- (match_operand:HI 1 "general_operand" "U,dAwim,!u,dAwi,!u,dAw,riU"))]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,m,U,U,m,!u")
+ (match_operand:HI 1 "general_operand" "U,dAwim,!u,K,dAwi,!u,dAw,riU"))]
"TARGET_M6812"
"*
{
return \"\";
}")
+(define_insn "movhi_const0"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,A,um")
+ (const_int 0))]
+ "TARGET_M6811"
+ "@
+ clra\\n\\tclrb
+ ld%0\\t#0
+ clr\\t%b0\\n\\tclr\\t%h0")
+
(define_insn "*movhi_m68hc11"
[(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
(match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
[(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
(zero_extend:DI
(match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
- (clobber (match_scratch:HI 2 "=d,d,&d,d"))]
+ (clobber (match_scratch:HI 2 "=d,d,d,d"))]
""
"#")
[(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
(plus:HI (zero_extend:HI
(match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
- (match_operand:HI 2 "hard_reg_operand" "0,0")))]
+ (match_operand:HI 2 "general_operand" "0,0")))]
""
"*
{
(define_insn "*subhi3"
[(set (match_operand:HI 0 "register_operand" "=d,*A,d,*A")
- (minus:HI (match_operand:HI 1 "register_operand" "0,0,0,0")
+ (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
(match_operand:HI 2 "general_operand" "im*A*d,im*d*A,u,!u")))]
""
"*
(define_insn "*subhi3_zext"
[(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
- (minus:HI (match_operand:HI 1 "hard_reg_operand" "0,0")
+ (minus:HI (match_operand:HI 1 "general_operand" "0,0")
(zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
""
"*
(define_insn "subqi3"
[(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
- (minus:QI (match_operand:QI 1 "hard_reg_operand" "0,0")
+ (minus:QI (match_operand:QI 1 "general_operand" "0,0")
(match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
""
"*
(define_insn "*andqi3_gen"
[(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
- (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "mi,!u,?*A,!um,?*A*d,!um*A")))]
+ (and:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
+ (match_operand:QI 2 "general_operand" "mi,!*u,?*A,!*um,?*A*d,!*um*A")))]
""
"*
{
(define_insn "*iorqi3_gen"
[(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
- (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "mi,!u,!*A,!um,?*A*d,!um*A")))]
+ (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
+ (match_operand:QI 2 "general_operand" "mi,!*u,!*A,!*um,?*A*d,!*um*A")))]
""
"*
{
(define_insn "xorqi3"
[(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
- (xor:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "im,!u,!*A,!ium,?*A*d,!ium*A")))]
+ (xor:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
+ (match_operand:QI 2 "general_operand" "im,!*u,!*A,!i*um,?*A*d,!i*um*A")))]
""
"*
{
;;
;; Replace "leas 2,sp" with a "pulx" or a "puly".
;; On 68HC12, this is one cycle slower but one byte smaller.
-;; pr target/6899: This peephole is not valid because a register CSE
-;; pass removes the pulx/puly.
+;; pr target/6899: This peephole was not valid because a register CSE
+;; pass removes the pulx/puly. The 'use' clause ensure that the pulx is
+;; not removed.
;;
(define_peephole2
[(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
(match_scratch:HI 0 "xy")]
- "0 && TARGET_M6812 && optimize_size"
- [(set (match_dup 0) (match_dup 1))]
+ "TARGET_M6812 && optimize_size"
+ [(set (match_dup 0) (match_dup 1))
+ (use (match_dup 0))]
"operands[1] = gen_rtx_MEM (HImode,
gen_rtx_POST_INC (HImode,
gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
if (GET_CODE (op) == MEM)
{
rtx op0 = XEXP (op, 0);
+ int addr_mode;
if (symbolic_memory_operand (op0, mode))
return 1;
if (IS_STACK_PUSH (op))
return 1;
- if (m68hc11_register_indirect_p (op, mode))
- return 1;
-
- return 0;
+ if (GET_CODE (op) == REG && reload_in_progress
+ && REGNO (op) >= FIRST_PSEUDO_REGISTER
+ && reg_equiv_memory_loc[REGNO (op)])
+ {
+ op = reg_equiv_memory_loc[REGNO (op)];
+ op = eliminate_regs (op, 0, NULL_RTX);
+ }
+ if (GET_CODE (op) != MEM)
+ return 0;
+
+ op0 = XEXP (op, 0);
+ addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
+ addr_mode &= ~ADDR_INDIRECT;
+ return m68hc11_valid_addressing_p (op0, mode, addr_mode);
}
return register_operand (op, mode);