parent
12f7c8764c
commit
77a02b01f2
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue