diff mbox

RFA: RL78: Fix handling of (SUBREG (SYMBOL_REF))

Message ID 87vbusry1g.fsf@redhat.com
State New
Headers show

Commit Message

Nick Clifton April 2, 2014, 7:27 a.m. UTC
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  <nickc@redhat.com>

	* config/rl78/rl78-expand.md (movqi): Handle (SUBREG (SYMBOL_REF))
	properly.

Comments

DJ Delorie April 2, 2014, 7:30 p.m. UTC | #1
This is OK.  Thanks!
diff mbox

Patch

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;