diff options
-rw-r--r-- | gcc/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/config/m68hc11/m68hc11-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/m68hc11/m68hc11.c | 111 | ||||
-rw-r--r-- | gcc/config/m68hc11/m68hc11.h | 7 | ||||
-rw-r--r-- | gcc/config/m68hc11/m68hc11.md | 58 | ||||
-rw-r--r-- | gcc/config/m68hc11/predicates.md | 19 |
6 files changed, 148 insertions, 72 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ff70fabc705..3cb7bf42d3d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,28 @@ 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. diff --git a/gcc/config/m68hc11/m68hc11-protos.h b/gcc/config/m68hc11/m68hc11-protos.h index 4a123e8de01..aad6f4ad0b8 100644 --- a/gcc/config/m68hc11/m68hc11-protos.h +++ b/gcc/config/m68hc11/m68hc11-protos.h @@ -98,6 +98,7 @@ extern int memory_indexed_operand (rtx, enum machine_mode); 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); @@ -123,6 +124,7 @@ extern int m68hc11_page0_symbol_p (rtx x); 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 */ diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c index 93fe2c3d9ad..17d0dd49b86 100644 --- a/gcc/config/m68hc11/m68hc11.c +++ b/gcc/config/m68hc11/m68hc11.c @@ -65,7 +65,6 @@ static rtx simplify_logical (enum machine_mode, int, rtx, rtx *); 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); @@ -140,13 +139,6 @@ unsigned char m68hc11_reg_valid_for_index[FIRST_PSEUDO_REGISTER]; 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; @@ -560,8 +552,8 @@ preferred_reload_class (rtx operand, enum reg_class class) /* 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; @@ -569,8 +561,8 @@ register_indirect_p (rtx operand, enum machine_mode mode, int addr_mode) { 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: @@ -578,8 +570,8 @@ register_indirect_p (rtx operand, enum machine_mode mode, int addr_mode) 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: @@ -675,7 +667,7 @@ m68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode) 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 @@ -730,7 +722,7 @@ m68hc11_register_indirect_p (rtx operand, enum machine_mode mode) 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 @@ -749,7 +741,7 @@ go_if_legitimate_address_internal (rtx operand, enum machine_mode mode, 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; } @@ -995,7 +987,7 @@ m68hc11_indirect_p (rtx operand, enum machine_mode mode) 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; } @@ -3110,10 +3102,13 @@ m68hc11_gen_movhi (rtx insn, rtx *operands) 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: @@ -3128,10 +3123,10 @@ m68hc11_gen_movhi (rtx insn, rtx *operands) } 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: @@ -3162,11 +3157,52 @@ m68hc11_gen_movhi (rtx insn, rtx *operands) 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)) @@ -3183,6 +3219,7 @@ m68hc11_gen_movhi (rtx insn, rtx *operands) ops[0] = to; ops[1] = operands[2]; m68hc11_gen_movhi (insn, ops); + return; } else { @@ -3190,19 +3227,11 @@ m68hc11_gen_movhi (rtx insn, rtx *operands) 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; } @@ -3530,8 +3559,10 @@ m68hc11_gen_movqi (rtx insn, rtx *operands) } 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 diff --git a/gcc/config/m68hc11/m68hc11.h b/gcc/config/m68hc11/m68hc11.h index b513dcd1865..02b08566555 100644 --- a/gcc/config/m68hc11/m68hc11.h +++ b/gcc/config/m68hc11/m68hc11.h @@ -1037,6 +1037,13 @@ typedef struct m68hc11_args /* 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) diff --git a/gcc/config/m68hc11/m68hc11.md b/gcc/config/m68hc11/m68hc11.md index 845910067c9..c03191c7337 100644 --- a/gcc/config/m68hc11/m68hc11.md +++ b/gcc/config/m68hc11/m68hc11.md @@ -689,8 +689,8 @@ 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"))] "" "#" @@ -886,18 +886,9 @@ } }") -(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" "* { @@ -905,6 +896,15 @@ 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"))] @@ -1237,7 +1237,7 @@ [(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"))] "" "#") @@ -2382,7 +2382,7 @@ [(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")))] "" "* { @@ -2716,7 +2716,7 @@ (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")))] "" "* @@ -2731,7 +2731,7 @@ (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"))))] "" "* @@ -2751,7 +2751,7 @@ (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")))] "" "* @@ -3326,8 +3326,8 @@ (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")))] "" "* { @@ -3544,8 +3544,8 @@ (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")))] "" "* { @@ -3636,8 +3636,8 @@ (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")))] "" "* { @@ -6914,14 +6914,16 @@ ;; ;; 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)));") diff --git a/gcc/config/m68hc11/predicates.md b/gcc/config/m68hc11/predicates.md index 67d1f988840..904c5b1194a 100644 --- a/gcc/config/m68hc11/predicates.md +++ b/gcc/config/m68hc11/predicates.md @@ -173,6 +173,7 @@ if (GET_CODE (op) == MEM) { rtx op0 = XEXP (op, 0); + int addr_mode; if (symbolic_memory_operand (op0, mode)) return 1; @@ -180,10 +181,20 @@ 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); |