summaryrefslogtreecommitdiff
path: root/gcc/config/sparc
diff options
context:
space:
mode:
authorwilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>1992-06-03 20:40:18 +0000
committerwilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>1992-06-03 20:40:18 +0000
commit7466c7831d6c7cd94891654bc59928ec8527618a (patch)
treef98a3d93c81c85e60764d62d3b34bbb8233495ec /gcc/config/sparc
parenta52a4060b06bf24a5697175e02a28736a7bdeb73 (diff)
downloadgcc-7466c7831d6c7cd94891654bc59928ec8527618a.tar.gz
entered into RCS
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@1150 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/sparc')
-rw-r--r--gcc/config/sparc/sparc.c110
-rw-r--r--gcc/config/sparc/sparc.h7
-rw-r--r--gcc/config/sparc/sparc.md82
3 files changed, 188 insertions, 11 deletions
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 9639dd6d915..080936a8dc2 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -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 ();
}
-/* 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. */
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index e052ffc9354..7a578130700 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -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. */
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index cfc13bd0d61..3643efec181 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -1845,6 +1845,88 @@
""
"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.