• J
    target-ppc: mcrfs should always update FEX/VX and only clear exception bits · d1277156
    James Clarke 提交于
    Here is the description of the mcrfs instruction from the PowerPC Architecture
    Book, Version 2.02, Book I: PowerPC User Instruction Set Architecture
    (http://www.ibm.com/developerworks/systems/library/es-archguide-v2.html), found
    on page 120:
    
        The contents of FPSCR field BFA are copied to Condition Register field BF.
        All exception bits copied are set to 0 in the FPSCR. If the FX bit is
        copied, it is set to 0 in the FPSCR.
    
        Special Registers Altered:
            CR field BF
            FX OX                        (if BFA=0)
            UX ZX XX VXSNAN              (if BFA=1)
            VXISI VXIDI VXZDZ VXIMZ      (if BFA=2)
            VXVC                         (if BFA=3)
            VXSOFT VXSQRT VXCVI          (if BFA=5)
    
    However, currently every bit in FPSCR field BFA is set to 0, including ones not
    on that list.
    
    This can be seen in the following simple C program:
    
        #include <fenv.h>
        #include <stdio.h>
    
        int main(int argc, char **argv) {
            int ret;
            ret = fegetround();
            printf("Current rounding: %d\n", ret);
            ret = fesetround(FE_UPWARD);
            printf("Setting to FE_UPWARD (%d): %d\n", FE_UPWARD, ret);
            ret = fegetround();
            printf("Current rounding: %d\n", ret);
            ret = fegetround();
            printf("Current rounding: %d\n", ret);
            return 0;
        }
    
    which gave the output (before this commit):
    
        Current rounding: 0
        Setting to FE_UPWARD (2): 0
        Current rounding: 2
        Current rounding: 0
    
    instead of (after this commit):
    
        Current rounding: 0
        Setting to FE_UPWARD (2): 0
        Current rounding: 2
        Current rounding: 2
    
    The relevant disassembly is in fegetround(), which, on my system, is:
    
        __GI___fegetround:
        <+0>:   mcrfs  cr7, cr7
        <+4>:   mfcr   r3
        <+8>:   clrldi r3, r3, 62
        <+12>:  blr
    
    What happens is that, the first time fegetround() is called, FPSCR field 7 is
    retrieved. However, because of the bug in mcrfs, the entirety of field 7 is set
    to 0, which includes the rounding mode.
    
    There are other issues this will fix, such as condition flags not persisting
    when they should if read, and if you were to read a specific field with some
    exception bits set, but no others were set in the entire register, then the
    bits would be cleared correctly, but FEX/VX would not be updated to 0 as they
    should be.
    Signed-off-by: NJames Clarke <jrtc27@jrtc27.com>
    Signed-off-by: NDavid Gibson <david@gibson.dropbear.id.au>
    d1277156
cpu.h 97.2 KB