Hi DJ, The patch below is to fix a snafu I made whilst fixing some problems with the RL78 port a while ago. GCC was generating (SUBREG (SYMBOL_REF) <n>) which made no sense to me, so I had the movqi expander just fail when it encountered them. Now that I have more idea about why they are created - installing symbolic values into bitfields or packed structure fields - I have found that it is necessary to support them. Failure is not an option as GCC will just silently omit generating any code at all.
Tested with an rl78-elf toolchain without any regressions. OK to apply ? Cheers Nick gcc/ChangeLog 2014-04-01 Nick Clifton <ni...@redhat.com> * config/rl78/rl78-expand.md (movqi): Handle (SUBREG (SYMBOL_REF)) properly. Index: gcc/config/rl78/rl78-expand.md =================================================================== --- gcc/config/rl78/rl78-expand.md (revision 209009) +++ gcc/config/rl78/rl78-expand.md (working copy) @@ -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;