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;
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";
}
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)
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:
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;
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
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
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
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;
}
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;
}
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;
}