From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alan Modra To: gas2@cygnus.com, egcs@cygnus.com, gcc2@cygnus.com Subject: gcc generates invalid i386 fmulp Date: Tue, 14 Apr 1998 00:15:00 -0000 Message-id: <199804131501.AAA05109@mullet.Levels.UniSA.Edu.Au> X-SW-Source: 1998/msg00110.html Hello all, I've been doing a little work on gas for i386, tidying up a few things and adding reasonably strict operand/suffix checking. The new gas has already found a couple of errors in the linux kernel asm, one in glibc1, and a problem with gcc. For anyone who's interested, the gas patches can be found at ftp://mullet.levels.unisa.edu.au/private/teabag/gas-980407-alan.diff.gz They should apply to binutils-2.9 without problems too. The gcc problem (found by mikeg@weiden.de (Michael L. Galbraith)), when compiling glibc2 is that gcc will generate instructions like `fsubp %st(1),%st' Now there's no instruction to do %st <- %st - %st(1) and pop, and it doesn't make sense to pop the result anyway. Older versions of gas assemble this instruction to 0xdee9, which does %st(1) <- %st(1) - %st, pop, ie. `fsubp %st,%st(1)' (Note!! Because of the broken UnixWare compatibility requirement for gas, you need to write `fsubrp %st,%st(1)' See the comments I put at the top of binutils/include/opcode/i386.h) * config/i386/i386.c (output_387_binary_op): Swap operands when popping if the result is st(0), to prevent invalid instructions like `fmulp %st(1),%st' and `fsubp %st(1),%st' --- gcc-2.8.1/config/i386/i386.c Thu Dec 4 00:31:23 1997 +++ gcc/config/i386/i386.c Tue Apr 14 00:00:43 1998 @@ -3827,9 +3827,12 @@ output_387_binary_op (insn, operands) return ""; } if (find_regno_note (insn, REG_DEAD, REGNO (operands[2]))) - return strcat (buf, AS2 (p,%2,%0)); + if (STACK_TOP_P (operands[0])) + return strcat (buf, AS2 (p,%0,%2)); + else + return strcat (buf, AS2 (p,%2,%0)); if (STACK_TOP_P (operands[0])) return strcat (buf, AS2C (%y2,%0)); else @@ -3858,12 +3861,18 @@ output_387_binary_op (insn, operands) if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2])) abort (); if (find_regno_note (insn, REG_DEAD, REGNO (operands[2]))) - return strcat (buf, AS2 (rp,%2,%0)); + if (STACK_TOP_P (operands[0])) + return strcat (buf, AS2 (p,%0,%2)); + else + return strcat (buf, AS2 (rp,%2,%0)); if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return strcat (buf, AS2 (p,%1,%0)); + if (STACK_TOP_P (operands[0])) + return strcat (buf, AS2 (rp,%0,%1)); + else + return strcat (buf, AS2 (p,%1,%0)); if (STACK_TOP_P (operands[0])) { if (STACK_TOP_P (operands[1]))