Subject: adddi3, subdi3, and negdi2 changes for ns32k.md
To: Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
From: Jon Buller <jonb@metronet.com>
List: port-pc532
Date: 06/10/1996 09:37:20
Here's a patch file for GCC 2.7.2 to improve 64 bit operations on
the ns32k platform.  It's from the CVS files of my NetBSD machine,
so the paths to the files might be slightly different than the
stock distribution.  The patch was worked out in March, but we have
held it for a while to get the bugs out (of which there were
several).  It has been stable for several months now, and since my
birthday is on the 12th, I thought I'd post date it a couple of
days...  I have a few questions about how to do muldi3 which I will
send to you seperately.  Thanks for a wonderful tool like GCC, my
pc532 would be useless without it.

Jon Buller

---------- cut here ----------

Wed Jun 12 10:28:57 1996  Jon Buller  (jonb@metronet.com)
			  Matthias Pfaller (leo@dachau.marco.de)
        * config/ns32k/ns32k.c (split_di): Pulled in from config/i386/i386.c.

	* config/ns32k/ns32k.md (adddi3, subdi3, negdi3): New patterns to
	  better support 64bit operations on the ns32k.


Index: netbsd/gnu/usr.bin/gcc/arch/ns32k/ns32k.c
diff -c netbsd/gnu/usr.bin/gcc/arch/ns32k/ns32k.c:1.1.1.1 netbsd/gnu/usr.bin/gcc/arch/ns32k/ns32k.c:1.2
*** netbsd/gnu/usr.bin/gcc/arch/ns32k/ns32k.c:1.1.1.1	Thu Jan 25 18:06:38 1996
--- netbsd/gnu/usr.bin/gcc/arch/ns32k/ns32k.c	Wed Apr  3 14:18:58 1996
***************
*** 227,232 ****
--- 227,265 ----
  	      || GET_CODE (op) == MEM));
  }
  
+ /* Split one or more DImode RTL references into pairs of SImode
+    references.  The RTL can be REG, offsettable MEM, integer constant, or
+    CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to
+    split and "num" is its length.  lo_half and hi_half are output arrays
+    that parallel "operands". */
+ 
+ void
+ split_di (operands, num, lo_half, hi_half)
+      rtx operands[];
+      int num;
+      rtx lo_half[], hi_half[];
+ {
+   while (num--)
+     {
+       if (GET_CODE (operands[num]) == REG)
+ 	{
+ 	  lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]));
+ 	  hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1);
+ 	}
+       else if (CONSTANT_P (operands[num]))
+ 	{
+ 	  split_double (operands[num], &lo_half[num], &hi_half[num]);
+ 	}
+       else if (offsettable_memref_p (operands[num]))
+ 	{
+ 	  lo_half[num] = operands[num];
+ 	  hi_half[num] = adj_offsettable_operand (operands[num], 4);
+ 	}
+       else
+ 	abort();
+     }
+ }
+ 
  /* Return the best assembler insn template
     for moving operands[1] into operands[0] as a fullword.  */
  
Index: netbsd/gnu/usr.bin/gcc/arch/ns32k/ns32k.md
diff -c netbsd/gnu/usr.bin/gcc/arch/ns32k/ns32k.md:1.1.1.1 netbsd/gnu/usr.bin/gcc/arch/ns32k/ns32k.md:1.5
*** netbsd/gnu/usr.bin/gcc/arch/ns32k/ns32k.md:1.1.1.1	Thu Jan 25 18:06:39 1996
--- netbsd/gnu/usr.bin/gcc/arch/ns32k/ns32k.md	Wed Apr  3 14:36:04 1996
***************
*** 858,863 ****
--- 858,904 ----
    "GET_CODE (operands[1]) == CONST_INT"
    "addr %c1(sp),%0")
  
+ (define_insn "adddi3"
+   [(set (match_operand:DI 0 "general_operand" "=ro")
+ 	(plus:DI (match_operand:DI 1 "general_operand" "%0")
+ 		 (match_operand:DI 2 "general_operand" "ron")))]
+   ""
+   "*
+ {
+   rtx low[3], high[3], xops[4];
+   split_di (operands, 3, low, high);
+   xops[0] = low[0];
+   xops[1] = high[0];
+   xops[2] = low[2];
+   xops[3] = high[2];
+ 
+   if (GET_CODE (xops[2]) == CONST_INT)
+     {
+       int i = INTVAL (xops[2]);
+ 
+       if (i <= 7 && i >= -8) 
+         {
+           if (i == 0)
+ 	    {
+ 	      i = INTVAL (xops[3]);
+ 	      if (i <= 7 && i >= -8)
+                 output_asm_insn (\"addqd %$%3,%1\", xops);
+ 	      else
+                 output_asm_insn (\"addd %$%3,%1\", xops);
+ 	    }
+ 	  else
+ 	    {
+               output_asm_insn (\"addqd %$%2,%0\", xops);
+               output_asm_insn (\"addcd %$%3,%1\", xops);
+ 	    }
+ 	  return \"\";
+ 	}
+     }
+   output_asm_insn (\"addd %2,%0\", xops);
+   output_asm_insn (\"addcd %3,%1\", xops);
+   return \"\";
+ }")
+ 
  (define_insn "addsi3"
    [(set (match_operand:SI 0 "general_operand" "=g,=g&<")
  	(plus:SI (match_operand:SI 1 "general_operand" "%0,r")
***************
*** 971,976 ****
--- 1012,1058 ----
    return \"adjspd %$%0\";
  }")
  
+ (define_insn "subdi3"
+   [(set (match_operand:DI 0 "general_operand" "=ro")
+ 	(minus:DI (match_operand:DI 1 "general_operand" "0")
+ 		  (match_operand:DI 2 "general_operand" "ron")))]
+   ""
+   "*
+ {
+   rtx low[3], high[3], xops[4];
+   split_di (operands, 3, low, high);
+   xops[0] = low[0];
+   xops[1] = high[0];
+   xops[2] = low[2];
+   xops[3] = high[2];
+ 
+   if (GET_CODE (xops[2]) == CONST_INT)
+     {
+       int i = INTVAL (xops[2]);
+ 
+       if (i <= 8 && i >= -7)
+         {
+           if (i == 0)
+ 	    {
+ 	      i = INTVAL (xops[3]);
+ 	      if (i <= 8 && i >= -7)
+                 output_asm_insn (\"addqd %$%n3,%1\", xops);
+ 	      else
+                 output_asm_insn (\"subd %$%3,%1\", xops);
+ 	    }
+ 	  else
+ 	    {
+               output_asm_insn (\"addqd %$%n2,%0\", xops);
+               output_asm_insn (\"subcd %$%3,%1\", xops);
+ 	    }
+ 	  return \"\";
+ 	}
+     }
+   output_asm_insn (\"subd %2,%0\", xops);
+   output_asm_insn (\"subcd %3,%1\", xops);
+   return \"\";
+ }")
+ 
  (define_insn "subsi3"
    [(set (match_operand:SI 0 "general_operand" "=g")
  	(minus:SI (match_operand:SI 1 "general_operand" "0")
***************
*** 1389,1394 ****
--- 1471,1504 ----
  	(neg:SF (match_operand:SF 1 "general_operand" "fmF")))]
    "TARGET_32081"
    "negf %1,%0")
+ 
+ (define_insn "negdi2"
+   [(set (match_operand:DI 0 "general_operand" "=ro")
+ 	(neg:DI (match_operand:DI 1 "general_operand" "ro")))]
+   ""
+   "*
+ {
+   rtx low[2], high[2], xops[4];
+   split_di (operands, 2, low, high);
+   xops[0] = low[0];
+   xops[1] = high[0];
+   xops[2] = low[1];
+   xops[3] = high[1];
+ 
+   if (rtx_equal_p (operands[0], operands[1]))
+     {
+       output_asm_insn (\"negd %3,%1\", xops);
+       output_asm_insn (\"negd %2,%0\", xops);
+       output_asm_insn (\"subcd %$0,%1\", xops);
+     }
+   else
+     {
+       output_asm_insn (\"negd %2,%0\", xops);
+       output_asm_insn (\"movqd %$0,%1\", xops);
+       output_asm_insn (\"subcd %3,%1\", xops);
+     }
+   return \"\"; 
+ }")
  
  (define_insn "negsi2"
    [(set (match_operand:SI 0 "general_operand" "=g<")