From: Jim Wilson Date: Wed, 3 Jun 1992 20:40:18 +0000 (-0700) Subject: entered into RCS X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=77a02b01f2a187724b84c45ef51915fc5011f8c5;p=gcc.git entered into RCS From-SVN: r1150 --- diff --git a/gcc/config/i960/i960.c b/gcc/config/i960/i960.c index 0a633665c41..0e2546e51e9 100644 --- a/gcc/config/i960/i960.c +++ b/gcc/config/i960/i960.c @@ -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) 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.