[Bug 264590] assembler generates wrong opcodes of instructions fdiv fdivp fdivr fdivrp fsub fsubp fsubr fsubrp

From: <bugzilla-noreply_at_freebsd.org>
Date: Fri, 10 Jun 2022 12:47:20 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=264590

Stefan Eßer <se@FreeBSD.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |se@FreeBSD.org
             Status|New                         |Open

--- Comment #2 from Stefan Eßer <se@FreeBSD.org> ---
(In reply to Li-Wen Hsu from comment #1)

Just checked with clang-14 and gcc11 on -CURRENT/amd64: the result is identical
to the one reported (0.31...).

Disassembly of sd() with objdump:

00000000002018e0 <sd>:
  2018e0:       55                      push   %rbp
  2018e1:       48 89 e5                mov    %rsp,%rbp
  2018e4:       d9 eb                   fldpi  
  2018e6:       d9 e8                   fld1   
  2018e8:       de f1                   fdivp  %st,%st(1)
  2018ea:       db 7d f0                fstpt  -0x10(%rbp)
  2018ed:       db 6d f0                fldt   -0x10(%rbp)
  2018f0:       5d                      pop    %rbp
  2018f1:       c3                      ret

Intel Architecture Software Developer’s Manual - Volume 2: Instruction Set
Reference:

> Opcode   Instruction         Description
> D8 /6    FDIV m32real        Divide ST(0) by m32real and store result in ST(0)
> DC /6    FDIV m64real        Divide ST(0) by m64real and store result in ST(0)
> D8 F0+i  FDIV ST(0),ST(i)    Divide ST(0) by ST(i) and store result in ST(0)    
> DC F8+i  FDIV ST(i),ST(0)    Divide ST(i) by ST(0) and store result in ST(i)
> DE F8+i  FDIVP ST(i),ST(0)   Divide ST(i) by ST(0), store result in ST(i), and pop the register stack

The byte sequence "de f1" does not exist in the reference manual, but if it is
decoded by the processor, then the disassembled instruction "fdivp  %st,%st(1)"
might behave in this (undocumented) way:

> DE F0+i  FDIVP ST(0),ST(i)   Divide ST(0) by ST(i), store result in ST(i), and pop the register stack

And that would explain the result obtained.

Maybe the assembler instruction "fdivp \n\t" is interpreted as if it was "fdivp
%st,st(1) \n\t", i.e. with operands reversed from what you'd expect?

-- 
You are receiving this mail because:
You are the assignee for the bug.