Alan Modra <alan@linuxcare.com.au>
authorAlan Modra <alan@linuxcare.com.au>
Tue, 28 Mar 2000 06:10:09 +0000 (22:10 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Tue, 28 Mar 2000 06:10:09 +0000 (22:10 -0800)
        * config/i386/i386.c (output_387_binary_op): Correct intel
        mode assembly output, and add spaces after commas in AT&T
        output.  Correct Unixware assembler comment.  Document input
        constraints.  Comment fp operations.  Reduce profligate buffer
        size.  Remove extraneous abort.  Localize temp var.
        (SYSV386_COMPAT): Define.  Add !SYSV386_COMPAT code.
        (output_fix_trunc): Add spaces after commas in assembly output.

From-SVN: r32778

gcc/ChangeLog
gcc/config/i386/i386.c

index 4f72a1b13358527d28f3269fe93fc4186cf91416..c223a64e58bafcfdd2970f5995838cb9a28f63ef 100644 (file)
@@ -1,3 +1,13 @@
+2000-03-27  Alan Modra  <alan@linuxcare.com.au>
+
+       * config/i386/i386.c (output_387_binary_op): Correct intel
+       mode assembly output, and add spaces after commas in AT&T
+       output.  Correct Unixware assembler comment.  Document input
+       constraints.  Comment fp operations.  Reduce profligate buffer
+       size.  Remove extraneous abort.  Localize temp var.
+       (SYSV386_COMPAT): Define.  Add !SYSV386_COMPAT code.
+       (output_fix_trunc): Add spaces after commas in assembly output.
+
 2000-03-27  Richard Henderson  <rth@cygnus.com>
 
        * i386-protos.h (ix86_match_ccmode): Declare.
@@ -575,8 +585,8 @@ Thu Mar 23 11:34:39 2000  Jim Wilson  <wilson@cygnus.com>
 
 Thu Mar 23 16:04:40 2000  Andrew Haley  <aph@cygnus.com>
 
-        * config/mips/mips.md (movdf_internal1a): Delete (set 'f', 'F')
-        alternative when using -fp64 -gp32.
+       * config/mips/mips.md (movdf_internal1a): Delete (set 'f', 'F')
+       alternative when using -fp64 -gp32.
 
 2000-03-22  Jason Merrill  <jason@casey.cygnus.com>
 
@@ -594,7 +604,7 @@ Thu Mar 23 16:04:40 2000  Andrew Haley  <aph@cygnus.com>
 
 2000-03-22  Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>
 
-        * builtin.c (get_pointer_alignment): Use DECL_P and TYPE_P macros.
+       * builtin.c (get_pointer_alignment): Use DECL_P and TYPE_P macros.
        * c-common.c (decl_attributes,check_format_info,truthvalue_conversion,
          c_get_alias_set): Likewise.
        * c-decl.c (duplicate_decls): Likewise.
@@ -679,7 +689,7 @@ Wed Mar 22 11:44:50 MET 2000  Jan Hubicka  <jh@suse.cz>
 
 2000-03-21  Richard Henderson  <rth@cygnus.com>
 
-        * flow.c (delete_block): Fix typo last change.
+       * flow.c (delete_block): Fix typo last change.
 
 2000-03-21  Mark Mitchell  <mark@codesourcery.com>
 
index 9c755a56aa8070de98bf754d8e8383680166b9ff..d3f3a6573f9c6a05571136d007b92a8a5574e0c1 100644 (file)
@@ -3434,15 +3434,39 @@ split_di (operands, num, lo_half, hi_half)
    There is no guarantee that the operands are the same mode, as they
    might be within FLOAT or FLOAT_EXTEND expressions. */
 
+#ifndef SYSV386_COMPAT
+/* Set to 1 for compatibility with brain-damaged assemblers.  No-one
+   wants to fix the assemblers because that causes incompatibility
+   with gcc.  No-one wants to fix gcc because that causes
+   incompatibility with assemblers...  You can use the option of
+   -DSYSV386_COMPAT=0 if you recompile both gcc and gas this way.  */
+#define SYSV386_COMPAT 1
+#endif
+
 const char *
 output_387_binary_op (insn, operands)
      rtx insn;
      rtx *operands;
 {
-  static char buf[100];
-  rtx temp;
+  static char buf[30];
   const char *p;
 
+#ifdef ENABLE_CHECKING
+  /* Even if we do not want to check the inputs, this documents input
+     constraints.  Which helps in understanding the following code.  */
+  if (STACK_REG_P (operands[0])
+      && ((REG_P (operands[1])
+          && REGNO (operands[0]) == REGNO (operands[1])
+          && (STACK_REG_P (operands[2]) || GET_CODE (operands[2]) == MEM))
+         || (REG_P (operands[2])
+             && REGNO (operands[0]) == REGNO (operands[2])
+             && (STACK_REG_P (operands[1]) || GET_CODE (operands[1]) == MEM)))
+      && (STACK_TOP_P (operands[1]) || STACK_TOP_P (operands[2])))
+    ; /* ok */
+  else
+    abort ();
+#endif
+
   switch (GET_CODE (operands[3]))
     {
     case PLUS:
@@ -3489,11 +3513,13 @@ output_387_binary_op (insn, operands)
     case PLUS:
       if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
        {
-         temp = operands[2];
+         rtx temp = operands[2];
          operands[2] = operands[1];
          operands[1] = temp;
        }
 
+      /* know operands[0] == operands[1].  */
+
       if (GET_CODE (operands[2]) == MEM)
        {
          p = "%z2\t%2";
@@ -3503,16 +3529,23 @@ output_387_binary_op (insn, operands)
       if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
        {
          if (STACK_TOP_P (operands[0]))
-           p = "p\t{%0,%2|%2, %0}";
+           /* How is it that we are storing to a dead operand[2]?
+              Well, presumably operands[1] is dead too.  We can't
+              store the result to st(0) as st(0) gets popped on this
+              instruction.  Instead store to operands[2] (which I
+              think has to be st(1)).  st(1) will be popped later.
+              gcc <= 2.8.1 didn't have this check and generated
+              assembly code that the Unixware assembler rejected.  */
+           p = "p\t{%0, %2|%2, %0}";   /* st(1) = st(0) op st(1); pop */
          else
-           p = "p\t{%2,%0|%0, %2}";
+           p = "p\t{%2, %0|%0, %2}";   /* st(r1) = st(r1) op st(0); pop */
          break;
        }
 
       if (STACK_TOP_P (operands[0]))
-       p = "\t{%y2,%0|%0, %y2}";
+       p = "\t{%y2, %0|%0, %y2}";      /* st(0) = st(0) op st(r2) */
       else
-       p = "\t{%2,%0|%0, %2}";
+       p = "\t{%2, %0|%0, %2}";        /* st(r1) = st(r1) op st(0) */
       break;
 
     case MINUS:
@@ -3529,42 +3562,69 @@ output_387_binary_op (insn, operands)
          break;
        }
 
-      if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2]))
-       abort ();
-
-      /* Note that the Unixware assembler, and the AT&T assembler before
-        that, are confusingly not reversed from Intel syntax in this
-        area.  */
       if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
        {
+#if SYSV386_COMPAT
+         /* The SystemV/386 SVR3.2 assembler, and probably all AT&T
+            derived assemblers, confusingly reverse the direction of
+            the operation for fsub{r} and fdiv{r} when the
+            destination register is not st(0).  The Intel assembler
+            doesn't have this brain damage.  Read !SYSV386_COMPAT to
+            figure out what the hardware really does.  */
+         if (STACK_TOP_P (operands[0]))
+           p = "{p\t%0, %2|rp\t%2, %0}";
+         else
+           p = "{rp\t%2, %0|p\t%0, %2}";
+#else
          if (STACK_TOP_P (operands[0]))
-           p = "p\t%0,%2";
+           /* As above for fmul/fadd, we can't store to st(0).  */
+           p = "rp\t{%0, %2|%2, %0}";  /* st(1) = st(0) op st(1); pop */
          else
-           p = "rp\t%2,%0";
+           p = "p\t{%2, %0|%0, %2}";   /* st(r1) = st(r1) op st(0); pop */
+#endif
          break;
        }
 
       if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
        {
+#if SYSV386_COMPAT
          if (STACK_TOP_P (operands[0]))
-           p = "rp\t%0,%1";
+           p = "{rp\t%0, %1|p\t%1, %0}";
          else
-           p = "p\t%1,%0";
+           p = "{p\t%1, %0|rp\t%0, %1}";
+#else
+         if (STACK_TOP_P (operands[0]))
+           p = "p\t{%0, %1|%1, %0}";   /* st(1) = st(1) op st(0); pop */
+         else
+           p = "rp\t{%1, %0|%0, %1}";  /* st(r2) = st(0) op st(r2); pop */
+#endif
          break;
        }
 
       if (STACK_TOP_P (operands[0]))
        {
          if (STACK_TOP_P (operands[1]))
-           p = "\t%y2,%0";
+           p = "\t{%y2, %0|%0, %y2}";  /* st(0) = st(0) op st(r2) */
          else
-           p = "r\t%y1,%0";
+           p = "r\t{%y1, %0|%0, %y1}"; /* st(0) = st(r1) op st(0) */
          break;
        }
       else if (STACK_TOP_P (operands[1]))
-       p = "\t%1,%0";
+       {
+#if SYSV386_COMPAT
+         p = "{\t%1, %0|r\t%0, %1}";
+#else
+         p = "r\t{%1, %0|%0, %1}";     /* st(r2) = st(0) op st(r2) */
+#endif
+       }
       else
-       p = "r\t%2,%0";
+       {
+#if SYSV386_COMPAT
+         p = "{r\t%2, %0|\t%0, %2}";
+#else
+         p = "\t{%2, %0|%0, %2}";      /* st(r1) = st(r1) op st(0) */
+#endif
+       }
       break;
 
     default:
@@ -3628,7 +3688,7 @@ output_fix_trunc (insn, operands)
          output_asm_insn ("mov{l}\t{%3, %1|%1, %3}", xops);
        }
       else
-       output_asm_insn ("mov{l}\t{%3,%0|%0, %3}", operands);
+       output_asm_insn ("mov{l}\t{%3, %0|%0, %3}", operands);
     }
 
   return "";