Hi,

This patch (diff-le-dfp) backports fixes for TDmode on a little endian
target.

Thanks,
Bill


2014-03-19  Bill Schmidt  <wschm...@linux.vnet.ibm.com>

        Backport from mainline r205123:

        2013-11-20  Ulrich Weigand  <ulrich.weig...@de.ibm.com>

        * config/rs6000/rs6000.c (rs6000_cannot_change_mode_class): Do not
        allow subregs of TDmode in FPRs of smaller size in little-endian.
        (rs6000_split_multireg_move): When splitting an access to TDmode
        in FPRs, do not use simplify_gen_subreg.

        Backport from mainline r204927:

        2013-11-17  Ulrich Weigand  <ulrich.weig...@de.ibm.com>

        * config/rs6000/rs6000.c (rs6000_emit_move): Use low word of
        sdmode_stack_slot also in little-endian mode.


Index: gcc-4_8-test/gcc/config/rs6000/rs6000.c
===================================================================
--- gcc-4_8-test.orig/gcc/config/rs6000/rs6000.c
+++ gcc-4_8-test/gcc/config/rs6000/rs6000.c
@@ -7963,7 +7963,9 @@ rs6000_emit_move (rtx dest, rtx source,
        }
       else if (INT_REGNO_P (REGNO (operands[1])))
        {
-         rtx mem = adjust_address_nv (operands[0], mode, 4);
+         rtx mem = operands[0];
+         if (BYTES_BIG_ENDIAN)
+           mem = adjust_address_nv (mem, mode, 4);
          mem = eliminate_regs (mem, VOIDmode, NULL_RTX);
          emit_insn (gen_movsd_hardfloat (mem, operands[1]));
        }
@@ -7986,7 +7988,9 @@ rs6000_emit_move (rtx dest, rtx source,
        }
       else if (INT_REGNO_P (REGNO (operands[0])))
        {
-         rtx mem = adjust_address_nv (operands[1], mode, 4);
+         rtx mem = operands[1];
+         if (BYTES_BIG_ENDIAN)
+           mem = adjust_address_nv (mem, mode, 4);
          mem = eliminate_regs (mem, VOIDmode, NULL_RTX);
          emit_insn (gen_movsd_hardfloat (operands[0], mem));
        }
@@ -16082,6 +16086,13 @@ rs6000_cannot_change_mode_class (enum ma
          if (TARGET_IEEEQUAD && (to == TFmode || from == TFmode))
            return true;
 
+         /* TDmode in floating-mode registers must always go into a register
+            pair with the most significant word in the even-numbered register
+            to match ISA requirements.  In little-endian mode, this does not
+            match subreg numbering, so we cannot allow subregs.  */
+         if (!BYTES_BIG_ENDIAN && (to == TDmode || from == TDmode))
+           return true;
+
          if (from_size < 8 || to_size < 8)
            return true;
 
@@ -19028,6 +19039,39 @@ rs6000_split_multireg_move (rtx dst, rtx
 
   gcc_assert (reg_mode_size * nregs == GET_MODE_SIZE (mode));
 
+  /* TDmode residing in FP registers is special, since the ISA requires that
+     the lower-numbered word of a register pair is always the most significant
+     word, even in little-endian mode.  This does not match the usual subreg
+     semantics, so we cannnot use simplify_gen_subreg in those cases.  Access
+     the appropriate constituent registers "by hand" in little-endian mode.
+
+     Note we do not need to check for destructive overlap here since TDmode
+     can only reside in even/odd register pairs.  */
+  if (FP_REGNO_P (reg) && DECIMAL_FLOAT_MODE_P (mode) && !BYTES_BIG_ENDIAN)
+    {
+      rtx p_src, p_dst;
+      int i;
+
+      for (i = 0; i < nregs; i++)
+       {
+         if (REG_P (src) && FP_REGNO_P (REGNO (src)))
+           p_src = gen_rtx_REG (reg_mode, REGNO (src) + nregs - 1 - i);
+         else
+           p_src = simplify_gen_subreg (reg_mode, src, mode,
+                                        i * reg_mode_size);
+
+         if (REG_P (dst) && FP_REGNO_P (REGNO (dst)))
+           p_dst = gen_rtx_REG (reg_mode, REGNO (dst) + nregs - 1 - i);
+         else
+           p_dst = simplify_gen_subreg (reg_mode, dst, mode,
+                                        i * reg_mode_size);
+
+         emit_insn (gen_rtx_SET (VOIDmode, p_dst, p_src));
+       }
+
+      return;
+    }
+
   if (REG_P (src) && REG_P (dst) && (REGNO (src) < REGNO (dst)))
     {
       /* Move register range backwards, if we might have destructive



Reply via email to