aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/m68hc11
diff options
context:
space:
mode:
authorStephane Carrez <stcarrez@nerim.fr>2004-03-02 23:40:57 +0100
committerStephane Carrez <ciceron@gcc.gnu.org>2004-03-02 23:40:57 +0100
commitde70723b1d7a97c50386a44ec93bb81580947e7f (patch)
tree658e9739cd9735ba9bb88ca14c4590094d5a4506 /gcc/config/m68hc11
parentd6da68b9d4dec53bfd5d0ac6b80847cbc65eb806 (diff)
downloadgcc-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.c114
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;
}