(movdi matchers): Support odd numbered regs.
authorRichard Kenner <kenner@gcc.gnu.org>
Fri, 28 Jul 1995 12:43:44 +0000 (08:43 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Fri, 28 Jul 1995 12:43:44 +0000 (08:43 -0400)
From-SVN: r10177

gcc/config/i960/i960.md

index a458aadd01f32f790175358af886637a8f601881..a86fb67ce68f4ac88276cd83ca9233e1d2eb13b4 100644 (file)
 
 ;; The store case can not be separate.  See comment above.
 (define_insn ""
-  [(set (match_operand:DI 0 "general_operand" "=d,d,d,m,o")
-       (match_operand:DI 1 "general_operand" "dI,i,m,d,J"))]
+  [(set (match_operand:DI 0 "general_operand" "=d,d,d,d,m,o")
+       (match_operand:DI 1 "general_operand" "d,I,i,m,d,J"))]
   "(current_function_args_size == 0
     && current_function_varargs == 0
     && current_function_stdarg == 0
   switch (which_alternative)
     {
     case 0:
-      return \"movl    %1,%0\";
+      if ((REGNO (operands[0]) & 1)
+         || (REGNO (operands[1]) & 1))
+       {
+         /* We normally copy the low-numbered register first.  However, if
+            the second register operand 0 is the same as the first register
+            of operand 1, we must copy in the opposite order.  */
+         if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
+           return \"mov        %D0,%D1\;mov    %0,%1\";
+         else
+           return \"mov        %0,%1\;mov      %D0,%D1\";
+       }
+      else
+       return \"movl   %1,%0\";
     case 1:
-      return i960_output_ldconst (operands[0], operands[1]);
+      if (REGNO (operands[0]) & 1)
+       return \"mov    %1,%0\;mov      0,%D0\";
+      else
+       return \"movl   %1,%0\";
     case 2:
-      return \"ldl     %1,%0\";
+      return i960_output_ldconst (operands[0], operands[1]);
     case 3:
-      return \"stl     %1,%0\";
+      if (REGNO (operands[0]) & 1)
+       {
+         /* One can optimize a few cases here, but you have to be
+            careful of clobbering registers used in the address and
+            edge conditions.  */
+         operands[2] = gen_rtx (REG, Pmode, REGNO (operands[0]) + 1);
+         operands[3] = gen_rtx (MEM, word_mode, operands[2]);
+         operands[4] = adj_offsettable_operand (operands[3], UNITS_PER_WORD);
+         return \"lda  %1,%2\;ld       %3,%0\;ld       %4,%D0\";
+       }
+      else
+       return \"ldl    %1,%0\";
     case 4:
+      return \"stl     %1,%0\";
+    case 5:
       operands[1] = adj_offsettable_operand (operands[0], 4);
       return \"st      g14,%0\;st      g14,%1\";
     }
 }"
-  [(set_attr "type" "move,load,load,store,store")])
+  [(set_attr "type" "move,move,load,load,store,store")])
 
 ;; The store case can not be separate.  See comment above.
 (define_insn ""
-  [(set (match_operand:DI 0 "general_operand" "=d,d,d,m")
-       (match_operand:DI 1 "general_operand" "dI,i,m,d"))]
+  [(set (match_operand:DI 0 "general_operand" "=d,d,d,d,m")
+       (match_operand:DI 1 "general_operand" "d,I,i,m,d"))]
   "(current_function_args_size != 0
     || current_function_varargs != 0
     || current_function_stdarg != 0
   switch (which_alternative)
     {
     case 0:
-      return \"movl    %1,%0\";
+      if ((REGNO (operands[0]) & 1)
+         || (REGNO (operands[1]) & 1))
+       {
+         /* We normally copy the low-numbered register first.  However, if
+            the second register operand 0 is the same as the first register
+            of operand 1, we must copy in the opposite order.  */
+         if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
+           return \"mov        %D0,%D1\;mov    %0,%1\";
+         else
+           return \"mov        %0,%1\;mov      %D0,%D1\";
+       }
+      else
+       return \"movl   %1,%0\";
     case 1:
-      return i960_output_ldconst (operands[0], operands[1]);
+      if (REGNO (operands[0]) & 1)
+       return \"mov    %1,%0\;mov      0,%D0\";
+      else
+       return \"movl   %1,%0\";
     case 2:
-      return \"ldl     %1,%0\";
+      return i960_output_ldconst (operands[0], operands[1]);
     case 3:
+      if (REGNO (operands[0]) & 1)
+       {
+         /* One can optimize a few cases here, but you have to be
+            careful of clobbering registers used in the address and
+            edge conditions.  */
+         operands[2] = gen_rtx (REG, Pmode, REGNO (operands[0]) + 1);
+         operands[3] = gen_rtx (MEM, word_mode, operands[2]);
+         operands[4] = adj_offsettable_operand (operands[3], UNITS_PER_WORD);
+         return \"lda  %1,%2\;ld       %3,%0\;ld       %4,%D0\";
+       }
+      else
+       return \"ldl    %1,%0\";
+    case 4:
       return \"stl     %1,%0\";
     }
 }"
-  [(set_attr "type" "move,load,load,store")])
+  [(set_attr "type" "move,move,load,load,store")])
 
 (define_expand "movti"
   [(set (match_operand:TI 0 "general_operand" "")