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
This commit is contained in:
Stephane Carrez 2004-03-02 23:40:57 +01:00 committed by Stephane Carrez
parent d6da68b9d4
commit de70723b1d
2 changed files with 108 additions and 20 deletions

View File

@ -1,3 +1,17 @@
2004-03-02 Stephane Carrez <stcarrez@nerim.fr>
* 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.
2004-03-02 Kazu Hirata <kazu@cs.umass.edu>
* builtins.c (BUILTIN_SETJMP_FRAME_VALUE): Remove.

View File

@ -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;
}