diff options
author | Stephane Carrez <stcarrez@nerim.fr> | 2004-03-02 23:40:57 +0100 |
---|---|---|
committer | Stephane Carrez <ciceron@gcc.gnu.org> | 2004-03-02 23:40:57 +0100 |
commit | de70723b1d7a97c50386a44ec93bb81580947e7f (patch) | |
tree | 658e9739cd9735ba9bb88ca14c4590094d5a4506 /gcc/config/m68hc11 | |
parent | d6da68b9d4dec53bfd5d0ac6b80847cbc65eb806 (diff) | |
download | gcc-de70723b1d7a97c50386a44ec93bb81580947e7f.zip gcc-de70723b1d7a97c50386a44ec93bb81580947e7f.tar.gz gcc-de70723b1d7a97c50386a44ec93bb81580947e7f.tar.bz2 |
m68hc11.c (m68hc11_addr_mode): New variable.
* config/m68hc11/m68hc11.c (m68hc11_addr_mode): New variable.
(m68hc11_mov_addr_mode): Likewise.
(m68hc11_override_options): Initialize them based on target.
(register_indirect_p): Allow a MEM for indirect addressing modes and
use flags to control what is allowed.
(m68hc11_small_indexed_indirect_p): Use m68hc11_mov_addr_mode for
supported addressing modes.
(m68hc11_register_indirect_p): Use m68hc11_addr_mode.
(go_if_legitimate_address_internal): Likewise.
(m68hc11_indirect_p): Likewise and check the mode.
(print_operand): Allow a (MEM (MEM)) and generate indirect addressing.
From-SVN: r78792
Diffstat (limited to 'gcc/config/m68hc11')
-rw-r--r-- | gcc/config/m68hc11/m68hc11.c | 114 |
1 files changed, 94 insertions, 20 deletions
diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c index a0e83c3..cca40ed 100644 --- a/gcc/config/m68hc11/m68hc11.c +++ b/gcc/config/m68hc11/m68hc11.c @@ -139,6 +139,16 @@ 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; + /* Comparison operands saved by the "tstxx" and "cmpxx" expand patterns. */ rtx m68hc11_compare_op0; rtx m68hc11_compare_op1; @@ -298,6 +308,8 @@ m68hc11_override_options (void) m68hc11_reg_valid_for_base[HARD_Z_REGNUM] = 1; m68hc11_sp_correction = 1; m68hc11_tmp_regs_class = D_REGS; + m68hc11_addr_mode = ADDR_OFFSET; + m68hc11_mov_addr_mode = 0; if (m68hc11_soft_reg_count == 0 && !TARGET_M6812) m68hc11_soft_reg_count = "4"; } @@ -317,6 +329,10 @@ m68hc11_override_options (void) m68hc11_reg_valid_for_index[HARD_D_REGNUM] = 1; m68hc11_sp_correction = 0; m68hc11_tmp_regs_class = TMP_REGS; + m68hc11_addr_mode = ADDR_INDIRECT | ADDR_OFFSET | ADDR_CONST + | (TARGET_AUTO_INC_DEC ? ADDR_INCDEC : 0); + m68hc11_mov_addr_mode = ADDR_OFFSET | ADDR_CONST + | (TARGET_AUTO_INC_DEC ? ADDR_INCDEC : 0); target_flags &= ~MASK_M6811; target_flags |= MASK_NO_DIRECT_MODE; if (m68hc11_soft_reg_count == 0) @@ -551,18 +567,25 @@ preferred_reload_class (rtx operand, enum reg_class class) 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 strict) +register_indirect_p (rtx operand, enum machine_mode mode, int addr_mode) { rtx base, offset; switch (GET_CODE (operand)) { + 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 0; + case POST_INC: case PRE_INC: case POST_DEC: case PRE_DEC: - if (TARGET_M6812 && TARGET_AUTO_INC_DEC) - return register_indirect_p (XEXP (operand, 0), mode, strict); + if (addr_mode & ADDR_INCDEC) + return register_indirect_p (XEXP (operand, 0), mode, + addr_mode & ADDR_STRICT); return 0; case PLUS: @@ -574,36 +597,57 @@ register_indirect_p (rtx operand, enum machine_mode mode, int strict) if (GET_CODE (offset) == MEM) return 0; + /* Indexed addressing mode with 2 registers. */ + if (GET_CODE (base) == REG && GET_CODE (offset) == REG) + { + if (!(addr_mode & ADDR_INDEXED)) + return 0; + + addr_mode &= ADDR_STRICT; + if (REGNO_OK_FOR_BASE_P2 (REGNO (base), addr_mode) + && REGNO_OK_FOR_INDEX_P2 (REGNO (offset), addr_mode)) + return 1; + + if (REGNO_OK_FOR_BASE_P2 (REGNO (offset), addr_mode) + && REGNO_OK_FOR_INDEX_P2 (REGNO (base), addr_mode)) + return 1; + + return 0; + } + + if (!(addr_mode & ADDR_OFFSET)) + return 0; + if (GET_CODE (base) == REG) { - if (!VALID_CONSTANT_OFFSET_P (offset, mode)) + if (!VALID_CONSTANT_OFFSET_P (offset, mode)) return 0; - if (strict == 0) + if (!(addr_mode & ADDR_STRICT)) return 1; - return REGNO_OK_FOR_BASE_P2 (REGNO (base), strict); + return REGNO_OK_FOR_BASE_P2 (REGNO (base), 1); } + if (GET_CODE (offset) == REG) { if (!VALID_CONSTANT_OFFSET_P (base, mode)) return 0; - if (strict == 0) + if (!(addr_mode & ADDR_STRICT)) return 1; - return REGNO_OK_FOR_BASE_P2 (REGNO (offset), strict); + return REGNO_OK_FOR_BASE_P2 (REGNO (offset), 1); } return 0; case REG: - return REGNO_OK_FOR_BASE_P2 (REGNO (operand), strict); + return REGNO_OK_FOR_BASE_P2 (REGNO (operand), addr_mode & ADDR_STRICT); case CONST_INT: - if (TARGET_M6811) - return 0; - - return VALID_CONSTANT_OFFSET_P (operand, mode); + if (addr_mode & ADDR_CONST) + return VALID_CONSTANT_OFFSET_P (operand, mode); + return 0; default: return 0; @@ -616,6 +660,7 @@ int m68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode) { rtx base, offset; + int addr_mode; if (GET_CODE (operand) == REG && reload_in_progress && REGNO (operand) >= FIRST_PSEUDO_REGISTER @@ -635,7 +680,8 @@ m68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode) if (PUSH_POP_ADDRESS_P (operand)) return 1; - if (!register_indirect_p (operand, mode, reload_completed)) + addr_mode = m68hc11_mov_addr_mode | (reload_completed ? ADDR_STRICT : 0); + if (!register_indirect_p (operand, mode, addr_mode)) return 0; if (TARGET_M6812 && GET_CODE (operand) == PLUS @@ -676,18 +722,29 @@ m68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode) int m68hc11_register_indirect_p (rtx operand, enum machine_mode mode) { + int addr_mode; + + if (GET_CODE (operand) == REG && reload_in_progress + && REGNO (operand) >= FIRST_PSEUDO_REGISTER + && reg_equiv_memory_loc[REGNO (operand)]) + { + operand = reg_equiv_memory_loc[REGNO (operand)]; + operand = eliminate_regs (operand, 0, NULL_RTX); + } if (GET_CODE (operand) != MEM) return 0; operand = XEXP (operand, 0); - return register_indirect_p (operand, mode, - (reload_completed | reload_in_progress)); + addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0); + return register_indirect_p (operand, mode, addr_mode); } static int go_if_legitimate_address_internal (rtx operand, enum machine_mode mode, int strict) { + int addr_mode; + if (CONSTANT_ADDRESS_P (operand) && TARGET_M6812) { /* Reject the global variables if they are too wide. This forces @@ -697,7 +754,8 @@ go_if_legitimate_address_internal (rtx operand, enum machine_mode mode, return 1; } - if (register_indirect_p (operand, mode, strict)) + addr_mode = m68hc11_addr_mode | (strict ? ADDR_STRICT : 0); + if (register_indirect_p (operand, mode, addr_mode)) { return 1; } @@ -984,18 +1042,20 @@ m68hc11_symbolic_p (rtx operand, enum machine_mode mode) int m68hc11_indirect_p (rtx operand, enum machine_mode mode) { - if (GET_CODE (operand) == MEM) + if (GET_CODE (operand) == MEM && GET_MODE (operand) == mode) { rtx op = XEXP (operand, 0); + int addr_mode; if (symbolic_memory_operand (op, mode)) - return 0; + return TARGET_M6812; if (reload_in_progress) return 1; operand = XEXP (operand, 0); - return register_indirect_p (operand, mode, reload_completed); + addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0); + return register_indirect_p (operand, mode, addr_mode); } return 0; } @@ -2247,7 +2307,21 @@ print_operand (FILE *file, rtx op, int letter) abort (); break; + case MEM: + if (TARGET_M6812) + { + fprintf (file, "["); + print_operand_address (file, XEXP (base, 0)); + fprintf (file, "]"); + } + else + abort (); + break; + default: + if (m68hc11_page0_symbol_p (base)) + fprintf (file, "*"); + output_address (base); break; } |