Commit e3c2afab by Alan Modra Committed by Richard Henderson

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.

From-SVN: r32778
parent 16189740
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> 2000-03-27 Richard Henderson <rth@cygnus.com>
* i386-protos.h (ix86_match_ccmode): Declare. * i386-protos.h (ix86_match_ccmode): Declare.
...@@ -575,8 +585,8 @@ Thu Mar 23 11:34:39 2000 Jim Wilson <wilson@cygnus.com> ...@@ -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> Thu Mar 23 16:04:40 2000 Andrew Haley <aph@cygnus.com>
* config/mips/mips.md (movdf_internal1a): Delete (set 'f', 'F') * config/mips/mips.md (movdf_internal1a): Delete (set 'f', 'F')
alternative when using -fp64 -gp32. alternative when using -fp64 -gp32.
2000-03-22 Jason Merrill <jason@casey.cygnus.com> 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> ...@@ -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> 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-common.c (decl_attributes,check_format_info,truthvalue_conversion,
c_get_alias_set): Likewise. c_get_alias_set): Likewise.
* c-decl.c (duplicate_decls): Likewise. * c-decl.c (duplicate_decls): Likewise.
...@@ -679,7 +689,7 @@ Wed Mar 22 11:44:50 MET 2000 Jan Hubicka <jh@suse.cz> ...@@ -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> 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> 2000-03-21 Mark Mitchell <mark@codesourcery.com>
......
...@@ -3434,15 +3434,39 @@ split_di (operands, num, lo_half, hi_half) ...@@ -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 There is no guarantee that the operands are the same mode, as they
might be within FLOAT or FLOAT_EXTEND expressions. */ 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 * const char *
output_387_binary_op (insn, operands) output_387_binary_op (insn, operands)
rtx insn; rtx insn;
rtx *operands; rtx *operands;
{ {
static char buf[100]; static char buf[30];
rtx temp;
const char *p; 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])) switch (GET_CODE (operands[3]))
{ {
case PLUS: case PLUS:
...@@ -3489,11 +3513,13 @@ output_387_binary_op (insn, operands) ...@@ -3489,11 +3513,13 @@ output_387_binary_op (insn, operands)
case PLUS: case PLUS:
if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2])) if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
{ {
temp = operands[2]; rtx temp = operands[2];
operands[2] = operands[1]; operands[2] = operands[1];
operands[1] = temp; operands[1] = temp;
} }
/* know operands[0] == operands[1]. */
if (GET_CODE (operands[2]) == MEM) if (GET_CODE (operands[2]) == MEM)
{ {
p = "%z2\t%2"; p = "%z2\t%2";
...@@ -3503,16 +3529,23 @@ output_387_binary_op (insn, operands) ...@@ -3503,16 +3529,23 @@ output_387_binary_op (insn, operands)
if (find_regno_note (insn, REG_DEAD, REGNO (operands[2]))) if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
{ {
if (STACK_TOP_P (operands[0])) 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 else
p = "p\t{%2,%0|%0, %2}"; p = "p\t{%2, %0|%0, %2}"; /* st(r1) = st(r1) op st(0); pop */
break; break;
} }
if (STACK_TOP_P (operands[0])) 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 else
p = "\t{%2,%0|%0, %2}"; p = "\t{%2, %0|%0, %2}"; /* st(r1) = st(r1) op st(0) */
break; break;
case MINUS: case MINUS:
...@@ -3529,42 +3562,69 @@ output_387_binary_op (insn, operands) ...@@ -3529,42 +3562,69 @@ output_387_binary_op (insn, operands)
break; 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 (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])) 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 else
p = "rp\t%2,%0"; p = "p\t{%2, %0|%0, %2}"; /* st(r1) = st(r1) op st(0); pop */
#endif
break; break;
} }
if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
{ {
#if SYSV386_COMPAT
if (STACK_TOP_P (operands[0])) if (STACK_TOP_P (operands[0]))
p = "rp\t%0,%1"; p = "{rp\t%0, %1|p\t%1, %0}";
else 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; break;
} }
if (STACK_TOP_P (operands[0])) if (STACK_TOP_P (operands[0]))
{ {
if (STACK_TOP_P (operands[1])) if (STACK_TOP_P (operands[1]))
p = "\t%y2,%0"; p = "\t{%y2, %0|%0, %y2}"; /* st(0) = st(0) op st(r2) */
else else
p = "r\t%y1,%0"; p = "r\t{%y1, %0|%0, %y1}"; /* st(0) = st(r1) op st(0) */
break; break;
} }
else if (STACK_TOP_P (operands[1])) 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 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; break;
default: default:
...@@ -3628,7 +3688,7 @@ output_fix_trunc (insn, operands) ...@@ -3628,7 +3688,7 @@ output_fix_trunc (insn, operands)
output_asm_insn ("mov{l}\t{%3, %1|%1, %3}", xops); output_asm_insn ("mov{l}\t{%3, %1|%1, %3}", xops);
} }
else else
output_asm_insn ("mov{l}\t{%3,%0|%0, %3}", operands); output_asm_insn ("mov{l}\t{%3, %0|%0, %3}", operands);
} }
return ""; return "";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment