diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 20447da43ba..5d7eef5e68e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2014-04-03 Nick Clifton + + * config/rl78/rl78-expand.md (movqi): Handle (SUBREG (SYMBOL_REF)) + properly. + 2014-04-03 Martin Jambor * ipa-cp.c (ipcp_verify_propagated_values): Also dump symtab and diff --git a/gcc/config/rl78/rl78-expand.md b/gcc/config/rl78/rl78-expand.md index f794d7cb13d..f61e444b5da 100644 --- a/gcc/config/rl78/rl78-expand.md +++ b/gcc/config/rl78/rl78-expand.md @@ -30,18 +30,23 @@ if (rl78_far_p (operands[0]) && rl78_far_p (operands[1])) operands[1] = copy_to_mode_reg (QImode, operands[1]); - /* FIXME: Not sure how GCC can generate (SUBREG (SYMBOL_REF)), - but it does. Since this makes no sense, reject it here. */ + /* GCC can generate (SUBREG (SYMBOL_REF)) when it has to store a symbol + into a bitfield, or a packed ordinary field. We can handle this + provided that the destination is a register. If not, then load the + source into a register first. */ if (GET_CODE (operands[1]) == SUBREG - && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) - FAIL; + && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF + && ! REG_P (operands[0])) + operands[1] = copy_to_mode_reg (QImode, operands[1]); + /* Similarly for (SUBREG (CONST (PLUS (SYMBOL_REF)))). cf. g++.dg/abi/packed.C. */ if (GET_CODE (operands[1]) == SUBREG && GET_CODE (XEXP (operands[1], 0)) == CONST && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == PLUS - && GET_CODE (XEXP (XEXP (XEXP (operands[1], 0), 0), 0)) == SYMBOL_REF) - FAIL; + && GET_CODE (XEXP (XEXP (XEXP (operands[1], 0), 0), 0)) == SYMBOL_REF + && ! REG_P (operands[0])) + operands[1] = copy_to_mode_reg (QImode, operands[1]); if (CONST_INT_P (operands[1]) && ! IN_RANGE (INTVAL (operands[1]), (-1 << 8) + 1, (1 << 8) - 1)) FAIL;