Commit 2a0b0bf5 by Ian Lance Taylor

Permit sign_extend operands

From-SVN: r13028
parent 7f423031
...@@ -719,6 +719,151 @@ move_operand (op, mode) ...@@ -719,6 +719,151 @@ move_operand (op, mode)
&& ! (mips_split_addresses && mips_check_split (op, mode))); && ! (mips_split_addresses && mips_check_split (op, mode)));
} }
/* Return true if OPERAND is valid as a source operand for movdi.
This accepts not only general_operand, but also sign extended
constants and registers. We need to accept sign extended constants
in case a sign extended register which is used in an expression,
and is equivalent to a constant, is spilled. */
int
movdi_operand (op, mode)
rtx op;
enum machine_mode mode;
{
if (TARGET_64BIT
&& mode == DImode
&& GET_CODE (op) == SIGN_EXTEND
&& GET_MODE (op) == DImode
&& (GET_MODE (XEXP (op, 0)) == SImode
|| (GET_CODE (XEXP (op, 0)) == CONST_INT
&& GET_MODE (XEXP (op, 0)) == VOIDmode))
&& (register_operand (XEXP (op, 0), SImode)
|| immediate_operand (XEXP (op, 0), SImode)))
return 1;
return general_operand (op, mode);
}
/* Like register_operand, but when in 64 bit mode also accept a sign
extend of a 32 bit register, since the value is known to be already
sign extended. */
int
se_register_operand (op, mode)
rtx op;
enum machine_mode mode;
{
if (TARGET_64BIT
&& mode == DImode
&& GET_CODE (op) == SIGN_EXTEND
&& GET_MODE (op) == DImode
&& GET_MODE (XEXP (op, 0)) == SImode
&& register_operand (XEXP (op, 0), SImode))
return 1;
return register_operand (op, mode);
}
/* Like reg_or_0_operand, but when in 64 bit mode also accept a sign
extend of a 32 bit register, since the value is known to be already
sign extended. */
int
se_reg_or_0_operand (op, mode)
rtx op;
enum machine_mode mode;
{
if (TARGET_64BIT
&& mode == DImode
&& GET_CODE (op) == SIGN_EXTEND
&& GET_MODE (op) == DImode
&& GET_MODE (XEXP (op, 0)) == SImode
&& register_operand (XEXP (op, 0), SImode))
return 1;
return reg_or_0_operand (op, mode);
}
/* Like uns_arith_operand, but when in 64 bit mode also accept a sign
extend of a 32 bit register, since the value is known to be already
sign extended. */
int
se_uns_arith_operand (op, mode)
rtx op;
enum machine_mode mode;
{
if (TARGET_64BIT
&& mode == DImode
&& GET_CODE (op) == SIGN_EXTEND
&& GET_MODE (op) == DImode
&& GET_MODE (XEXP (op, 0)) == SImode
&& register_operand (XEXP (op, 0), SImode))
return 1;
return uns_arith_operand (op, mode);
}
/* Like arith_operand, but when in 64 bit mode also accept a sign
extend of a 32 bit register, since the value is known to be already
sign extended. */
int
se_arith_operand (op, mode)
rtx op;
enum machine_mode mode;
{
if (TARGET_64BIT
&& mode == DImode
&& GET_CODE (op) == SIGN_EXTEND
&& GET_MODE (op) == DImode
&& GET_MODE (XEXP (op, 0)) == SImode
&& register_operand (XEXP (op, 0), SImode))
return 1;
return arith_operand (op, mode);
}
/* Like nonmemory_operand, but when in 64 bit mode also accept a sign
extend of a 32 bit register, since the value is known to be already
sign extended. */
int
se_nonmemory_operand (op, mode)
rtx op;
enum machine_mode mode;
{
if (TARGET_64BIT
&& mode == DImode
&& GET_CODE (op) == SIGN_EXTEND
&& GET_MODE (op) == DImode
&& GET_MODE (XEXP (op, 0)) == SImode
&& register_operand (XEXP (op, 0), SImode))
return 1;
return nonmemory_operand (op, mode);
}
/* Like nonimmediate_operand, but when in 64 bit mode also accept a
sign extend of a 32 bit register, since the value is known to be
already sign extended. */
int
se_nonimmediate_operand (op, mode)
rtx op;
enum machine_mode mode;
{
if (TARGET_64BIT
&& mode == DImode
&& GET_CODE (op) == SIGN_EXTEND
&& GET_MODE (op) == DImode
&& GET_MODE (XEXP (op, 0)) == SImode
&& register_operand (XEXP (op, 0), SImode))
return 1;
return nonimmediate_operand (op, mode);
}
/* Return true if we split the address into high and low parts. */ /* Return true if we split the address into high and low parts. */
/* ??? We should also handle reg+array somewhere. We get four /* ??? We should also handle reg+array somewhere. We get four
...@@ -1382,6 +1527,12 @@ mips_move_2words (operands, insn) ...@@ -1382,6 +1527,12 @@ mips_move_2words (operands, insn)
code0 = GET_CODE (op0); code0 = GET_CODE (op0);
} }
if (code1 == SIGN_EXTEND)
{
op1 = XEXP (op1, 0);
code1 = GET_CODE (op1);
}
while (code1 == SUBREG) while (code1 == SUBREG)
{ {
subreg_word1 += SUBREG_WORD (op1); subreg_word1 += SUBREG_WORD (op1);
...@@ -1389,6 +1540,12 @@ mips_move_2words (operands, insn) ...@@ -1389,6 +1540,12 @@ mips_move_2words (operands, insn)
code1 = GET_CODE (op1); code1 = GET_CODE (op1);
} }
/* Sanity check. */
if (GET_CODE (operands[1]) == SIGN_EXTEND
&& code1 != REG
&& code1 != CONST_INT)
abort ();
if (code0 == REG) if (code0 == REG)
{ {
int regno0 = REGNO (op0) + subreg_word0; int regno0 = REGNO (op0) + subreg_word0;
...@@ -1567,7 +1724,9 @@ mips_move_2words (operands, insn) ...@@ -1567,7 +1724,9 @@ mips_move_2words (operands, insn)
{ {
if (TARGET_64BIT) if (TARGET_64BIT)
{ {
if (HOST_BITS_PER_WIDE_INT < 64) if (GET_CODE (operands[1]) == SIGN_EXTEND)
ret = "li\t%0,%1\t\t# %X1";
else if (HOST_BITS_PER_WIDE_INT < 64)
/* We can't use 'X' for negative numbers, because then we won't /* We can't use 'X' for negative numbers, because then we won't
get the right value for the upper 32 bits. */ get the right value for the upper 32 bits. */
ret = ((INTVAL (op1) < 0) ? "dli\t%0,%1\t\t\t# %X1" ret = ((INTVAL (op1) < 0) ? "dli\t%0,%1\t\t\t# %X1"
...@@ -3862,6 +4021,13 @@ print_operand (file, op, letter) ...@@ -3862,6 +4021,13 @@ print_operand (file, op, letter)
} }
code = GET_CODE (op); code = GET_CODE (op);
if (code == SIGN_EXTEND)
{
op = XEXP (op, 0);
code = GET_CODE (op);
}
if (letter == 'C') if (letter == 'C')
switch (code) switch (code)
{ {
...@@ -3919,9 +4085,14 @@ print_operand (file, op, letter) ...@@ -3919,9 +4085,14 @@ print_operand (file, op, letter)
fprintf (file, "%s,", reg_names[regnum]); fprintf (file, "%s,", reg_names[regnum]);
} }
else if (code == REG) else if (code == REG || code == SUBREG)
{ {
register int regnum = REGNO (op); register int regnum;
if (code == REG)
regnum = REGNO (op);
else
regnum = true_regnum (op);
if ((letter == 'M' && ! WORDS_BIG_ENDIAN) if ((letter == 'M' && ! WORDS_BIG_ENDIAN)
|| (letter == 'L' && WORDS_BIG_ENDIAN) || (letter == 'L' && WORDS_BIG_ENDIAN)
...@@ -5832,7 +6003,28 @@ mips_secondary_reload_class (class, mode, x, in_p) ...@@ -5832,7 +6003,28 @@ mips_secondary_reload_class (class, mode, x, in_p)
{ {
int regno = -1; int regno = -1;
if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG) if (GET_CODE (x) == SIGN_EXTEND)
{
int off = 0;
x = XEXP (x, 0);
/* We may be called with reg_renumber NULL from regclass.
??? This is probably a bug. */
if (reg_renumber)
regno = true_regnum (x);
else
{
while (GET_CODE (x) == SUBREG)
{
off += SUBREG_WORD (x);
x = SUBREG_REG (x);
}
if (GET_CODE (x) == REG)
regno = REGNO (x) + off;
}
}
else if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
regno = true_regnum (x); regno = true_regnum (x);
/* We always require a general register when copying anything to /* We always require a general register when copying anything to
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment