Subject: Re: 64bit ns32k.md changes for GCC
To: Jon Buller <jonb@metronet.com>
From: Matthias Pfaller <leo@dachau.marco.de>
List: port-pc532
Date: 03/25/1996 10:33:36
Hi Jon,

thank's for your really marvelous idea. I changed your patch to handle
immediate constants. The code knows about constants in the -7...8 range
and ommits the addition of the low half if it is 0.

	Thank's - Matthias

PS: If you wish to send this to the fsf, afaik you have to send the patch
    with a ChangeLog entry to Richard Kenner (kenner@vlsi1.ultra.nyu.edu).

Here comes my version of your patch (I did a prototype ChangeLog entry for
you):

Mon Mar 25 10:28:57 1996  Jon Buller  (jonb@metronet.com)

	* 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.

--- ns32k.c.ORIG	Mon Dec 11 21:14:23 1995
+++ ns32k.c	Fri Mar 22 23:35:38 1996
@@ -227,6 +227,39 @@
 	      || 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". (stolen from i386/i386.c) */
+
+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.  */
 
--- ns32k.md.ORIG	Mon Dec 11 21:14:24 1995
+++ ns32k.md	Sat Mar 23 16:55:57 1996
@@ -858,6 +858,47 @@
   "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,6 +1012,47 @@
   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,6 +1471,25 @@
 	(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")))]
+  ""
+  "*
+{
+  output_asm_insn (\"negd %1,%0\", operands);
+  if (REG_P (operands[0]))
+    operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+  else
+    operands[0] = adj_offsettable_operand (operands[0], 4);
+  if (REG_P (operands[1]))
+    operands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+  else
+    operands[1] = adj_offsettable_operand (operands[1], 4);
+  output_asm_insn (\"movqd 0,%0\", operands);
+  return \"subcd %1,%0\"; 
+}")
 
 (define_insn "negsi2"
   [(set (match_operand:SI 0 "general_operand" "=g<")
-- 
leo@dachau.marco.de			in real life: Matthias Pfaller
marco GmbH, 85221 Dachau, Germany	tel: +49 8131 516142