entered into RCS
authorJim Wilson <wilson@gcc.gnu.org>
Wed, 3 Jun 1992 20:40:18 +0000 (13:40 -0700)
committerJim Wilson <wilson@gcc.gnu.org>
Wed, 3 Jun 1992 20:40:18 +0000 (13:40 -0700)
From-SVN: r1150

gcc/config/i960/i960.c
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h
gcc/config/sparc/sparc.md

index 0a633665c41343530dc300cac3091182aa571e06..0e2546e51e94709d591caee0930dd85c81cc96e8 100644 (file)
@@ -965,7 +965,7 @@ i960_function_prologue (file, size)
   register int i, j, nr;
   int n_iregs = 0;
   int rsize = 0;
-  int actual_fsize;
+  int actual_fsize, offset;
   char tmpstr[1000];
   /* -1 if reg must be saved on proc entry, 0 if available, 1 if saved
      somewhere.  */
@@ -1051,7 +1051,12 @@ i960_function_prologue (file, size)
 #if 0
   /* ??? The 1.2.1 compiler does this also.  This is meant to round the frame
      size up to the nearest multiple of 16.  I don't know whether this is
-     necessary, or even desirable.  */
+     necessary, or even desirable.
+
+     The frame pointer must be aligned, but the call instruction takes care of
+     that.  If we leave the stack pointer unaligned, we may save a little on
+     dynamic stack allocation.  And we don't lose, at least according to the
+     i960CA manual.  */
   actual_fsize = (actual_fsize + 15) & ~0xF;
 #endif
 
@@ -1063,7 +1068,10 @@ i960_function_prologue (file, size)
       else
        fprintf (file, "\tlda\t%d(sp),sp\n", actual_fsize);
     }
-  
+
+  /* Take hardware register save area created by the call instruction
+     into account.  */
+  offset = compute_frame_size (size) + 64;
   /* Save registers on stack if needed.  */
   for (i = 0, j = n_iregs; j > 0 && i < 16; i++)
     {
@@ -1072,10 +1080,11 @@ i960_function_prologue (file, size)
 
       nr = 1;
 
-      if (i <= 14 && i % 2 == 0 && regs[i+1] == -1)
+      if (i <= 14 && i % 2 == 0 && regs[i+1] == -1 && offset % 2 == 0)
        nr = 2;
 
-      if (nr == 2 && i <= 12 && i % 4 == 0 && regs[i+2] == -1)
+      if (nr == 2 && i <= 12 && i % 4 == 0 && regs[i+2] == -1
+         && offset % 4 == 0)
        nr = 3;
 
       if (nr == 3 && regs[i+3] == -1)
@@ -1085,15 +1094,16 @@ i960_function_prologue (file, size)
               ((nr == 4) ? "q" :
                (nr == 3) ? "t" :
                (nr == 2) ? "l" : ""),
-              reg_names[i], size+(nr*4));
+              reg_names[i], offset);
       sprintf (tmpstr,"\tld%s  %d(fp),%s\n",
               ((nr == 4) ? "q" :
                (nr == 3) ? "t" :
                (nr == 2) ? "l" : ""),
-              size+(nr*4), reg_names[i]);
+              offset, reg_names[i]);
       strcat (epilogue_string, tmpstr);
       i += nr-1;
       j -= nr;
+      offset += nr * 4;
     }
 
   if (actual_fsize == 0 && size == 0 && rsize == 0)
index 9639dd6d9155169a58ea63060357bbea97c37b3b..080936a8dc21b18df07bce3591efbd0b6cb19100 100644 (file)
@@ -2749,7 +2749,7 @@ print_operand (file, x, code)
       return;
     case 'r':
       /* In this case we need a register.  Use %g0 if the
-        operand in const0_rtx.  */
+        operand is const0_rtx.  */
       if (x == const0_rtx)
        {
          fputs ("%g0", file);
@@ -2872,8 +2872,37 @@ output_double_int (file, value)
     abort ();
 }
 \f
-/* Compute the code to put in the .proc statement
-   for a function that returns type TYPE.  */
+#ifndef CHAR_TYPE_SIZE
+#define CHAR_TYPE_SIZE BITS_PER_UNIT
+#endif
+
+#ifndef SHORT_TYPE_SIZE
+#define SHORT_TYPE_SIZE (BITS_PER_UNIT * 2)
+#endif
+
+#ifndef INT_TYPE_SIZE
+#define INT_TYPE_SIZE BITS_PER_WORD
+#endif
+
+#ifndef LONG_TYPE_SIZE
+#define LONG_TYPE_SIZE BITS_PER_WORD
+#endif
+
+#ifndef LONG_LONG_TYPE_SIZE
+#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
+#endif
+
+#ifndef FLOAT_TYPE_SIZE
+#define FLOAT_TYPE_SIZE BITS_PER_WORD
+#endif
+
+#ifndef DOUBLE_TYPE_SIZE
+#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
+#endif
+
+#ifndef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
+#endif
 
 unsigned long
 sparc_type_code (type)
@@ -2923,16 +2952,79 @@ sparc_type_code (type)
          return (qualifiers | 16);
 
        case INTEGER_TYPE:
-        /* This return value is not always completely the same as Sun's
-           but the Sun assembler's peephole optimizer probably doesn't
-           care.  */
-        return (qualifiers | 4);
+         /* Carefully distinguish all the standard types of C,
+            without messing up if the language is not C.
+            Note that we check only for the names that contain spaces;
+            other names might occur by coincidence in other languages.  */
+         if (TYPE_NAME (type) != 0
+             && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+             && DECL_NAME (TYPE_NAME (type)) != 0
+             && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
+           {
+             char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+  
+             if (!strcmp (name, "unsigned char"))
+               return (qualifiers | 12);
+             if (!strcmp (name, "signed char"))
+               return (qualifiers | 2);
+             if (!strcmp (name, "unsigned int"))
+               return (qualifiers | 14);
+             if (!strcmp (name, "short int"))
+               return (qualifiers | 3);
+             if (!strcmp (name, "short unsigned int"))
+               return (qualifiers | 13);
+             if (!strcmp (name, "long int"))
+               return (qualifiers | 5);
+             if (!strcmp (name, "long unsigned int"))
+               return (qualifiers | 15);
+             if (!strcmp (name, "long long int"))
+               return (qualifiers | 5);        /* Who knows? */
+             if (!strcmp (name, "long long unsigned int"))
+               return (qualifiers | 15);       /* Who knows? */
+           }
+  
+         /* Most integer types will be sorted out above, however, for the
+            sake of special `array index' integer types, the following code
+            is also provided.  */
+  
+         if (TYPE_PRECISION (type) == INT_TYPE_SIZE)
+           return (qualifiers | (TREE_UNSIGNED (type) ? 14 : 4));
+  
+         if (TYPE_PRECISION (type) == LONG_TYPE_SIZE)
+           return (qualifiers | (TREE_UNSIGNED (type) ? 15 : 5));
+  
+         if (TYPE_PRECISION (type) == LONG_LONG_TYPE_SIZE)
+           return (qualifiers | (TREE_UNSIGNED (type) ? 15 : 5));
+  
+         if (TYPE_PRECISION (type) == SHORT_TYPE_SIZE)
+           return (qualifiers | (TREE_UNSIGNED (type) ? 13 : 3));
+  
+         if (TYPE_PRECISION (type) == CHAR_TYPE_SIZE)
+           return (qualifiers | (TREE_UNSIGNED (type) ? 12 : 2));
+  
+         abort ();
   
        case REAL_TYPE:
-         if (TYPE_PRECISION (type) == 32)
+         /* Carefully distinguish all the standard types of C,
+            without messing up if the language is not C.  */
+         if (TYPE_NAME (type) != 0
+             && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+             && DECL_NAME (TYPE_NAME (type)) != 0
+             && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
+           {
+             char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+  
+             if (!strcmp (name, "long double"))
+               return (qualifiers | 7);        /* Who knows? */
+           }
+  
+         if (TYPE_PRECISION (type) == DOUBLE_TYPE_SIZE)
+           return (qualifiers | 7);
+         if (TYPE_PRECISION (type) == FLOAT_TYPE_SIZE)
            return (qualifiers | 6);
-         else
+         if (TYPE_PRECISION (type) == LONG_DOUBLE_TYPE_SIZE)
            return (qualifiers | 7);    /* Who knows? */
+         abort ();
   
        case COMPLEX_TYPE:      /* GNU Fortran COMPLEX type.  */
        case CHAR_TYPE:         /* GNU Pascal CHAR type.  Not used in C.  */
index e052ffc93542acce6351492c3623a72805433cda..7a5781307000c0da1761bc8507f4518988fbaed2 100644 (file)
@@ -185,16 +185,19 @@ extern int target_flags;
 /* No data type wants to be aligned rounder than this.  */
 #define BIGGEST_ALIGNMENT 64
 
+/* The best alignment to use in cases where we have a choice.  */
+#define FASTEST_ALIGNMENT 64
+
 /* Make strings word-aligned so strcpy from constants will be faster.  */
 #define CONSTANT_ALIGNMENT(EXP, ALIGN)  \
   (TREE_CODE (EXP) == STRING_CST       \
-   && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
+   && (ALIGN) < FASTEST_ALIGNMENT ? FASTEST_ALIGNMENT : (ALIGN))
 
 /* Make arrays of chars word-aligned for the same reasons.  */
 #define DATA_ALIGNMENT(TYPE, ALIGN)            \
   (TREE_CODE (TYPE) == ARRAY_TYPE              \
    && TYPE_MODE (TREE_TYPE (TYPE)) == QImode   \
-   && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
+   && (ALIGN) < FASTEST_ALIGNMENT ? FASTEST_ALIGNMENT : (ALIGN))
 
 /* Set this nonzero if move instructions will actually fail to work
    when given unaligned data.  */
index cfc13bd0d615ac14813bd163f947f567dd5248d2..3643efec1810f3de04b09903947dc4e412450f24 100644 (file)
   ""
   "subcc %1,%2,%0")
 
+(define_insn "mulsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (mult:SI (match_operand:SI 1 "arith_operand" "%r")
+                (match_operand:SI 2 "arith_operand" "rI")))]
+  "TARGET_V8 || TARGET_SPARCLITE"
+  "smul %1,%2,%0")
+
+;; It is not known whether this will match.
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (mult:SI (match_operand:SI 1 "arith_operand" "%r")
+                (match_operand:SI 2 "arith_operand" "rI")))
+   (set (reg:CC_NOOV 0)
+       (compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2))
+                        (const_int 0)))]
+  "TARGET_V8 || TARGET_SPARCLITE"
+  "smulcc %1,%2,%0")
+
+(define_insn "mulsidi3"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_operand" "%r"))
+                (sign_extend:DI (match_operand:SI 2 "arith_operand" "rI"))))]
+  "TARGET_V8 || TARGET_SPARCLITE"
+  "smul %1,%2,%R0\;rd %y,%0"
+  [(set_attr "length" "2")])
+
+(define_insn "umulsidi3"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_operand" "%r"))
+                (zero_extend:DI (match_operand:SI 2 "arith_operand" "rI"))))]
+  "TARGET_V8 || TARGET_SPARCLITE"
+  "umul %1,%2,%R0\;rd %y,%0"
+  [(set_attr "length" "2")])
+
+;; The architecture specifies that there must be 3 instructions between
+;; a y register write and a use of it for correct results.
+
+(define_insn "divsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (div:SI (match_operand:SI 1 "register_operand" "r")
+               (match_operand:SI 2 "arith_operand" "rI")))
+   (clobber (match_scratch:SI 3 "=&r"))]
+  "TARGET_V8"
+  "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0"
+  [(set_attr "length" "3")])
+
+;; It is not known whether this will match.
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (div:SI (match_operand:SI 1 "register_operand" "r")
+               (match_operand:SI 2 "arith_operand" "rI")))
+   (set (reg:CC 0)
+       (compare:CC (div:SI (match_dup 1) (match_dup 2))
+                   (const_int 0)))
+   (clobber (match_scratch:SI 3 "=&r"))]
+  "TARGET_V8"
+  "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdivcc %1,%2,%0"
+  [(set_attr "length" "3")])
+
+(define_insn "udivsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (udiv:SI (match_operand:SI 1 "register_operand" "r")
+               (match_operand:SI 2 "arith_operand" "rI")))]
+  "TARGET_V8"
+  "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udiv %1,%2,%0"
+  [(set_attr "length" "2")])
+
+;; It is not known whether this will match.
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (udiv:SI (match_operand:SI 1 "register_operand" "r")
+               (match_operand:SI 2 "arith_operand" "rI")))
+   (set (reg:CC 0)
+       (compare:CC (udiv:SI (match_dup 1) (match_dup 2))
+                   (const_int 0)))]
+  "TARGET_V8"
+  "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0"
+  [(set_attr "length" "2")])
+
 ;;- and instructions
 ;; We define DImode `and` so with DImode `not` we can get
 ;; DImode `andn`.  Other combinations are possible.