VirtualBox

Changeset 96218 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Aug 15, 2022 12:33:57 PM (2 years ago)
Author:
vboxsync
Message:

IPRT/nocrt: Fixed buggy remainder[fl] code. Added tests for it. bugref:10261

Location:
trunk/src/VBox/Runtime
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/math/remainder.asm

    r96014 r96218  
    2525;
    2626
     27
     28%define RT_ASM_WITH_SEH64
    2729%include "iprt/asmdefs.mac"
     30%include "iprt/x86.mac"
     31
    2832
    2933BEGINCODE
     
    3135;;
    3236; See SUS.
    33 ; @returns st(0)
    34 ; @param    rd1    [ebp + 8h]  xmm0
    35 ; @param    rd2    [ebp + 10h]  xmm1
     37; @returns  st(0) / xmm0
     38; @param    rd1    [ebp + 8h]   xmm0    Dividend.
     39; @param    rd2    [ebp + 10h]  xmm1    Divisor.
    3640RT_NOCRT_BEGINPROC remainder
    37     push    xBP
    38     mov     xBP, xSP
    39     sub     xSP, 20h
    40 ;int3
     41        push    xBP
     42        SEH64_PUSH_xBP
     43        mov     xBP, xSP
     44        SEH64_SET_FRAME_xBP 0
     45%ifdef RT_ARCH_AMD64
     46        sub     xSP, 20h
     47        SEH64_ALLOCATE_STACK 20h
     48%endif
     49        SEH64_END_PROLOGUE
    4150
     51        ;
     52        ; Load the dividend into st0 and divisor into st1.
     53        ;
    4254%ifdef RT_ARCH_AMD64
    43     movsd   [rsp + 10h], xmm1
    44     movsd   [rsp], xmm0
    45     fld     qword [rsp + 10h]
    46     fld     qword [rsp]
     55        movsd   [xBP - 20h], xmm1
     56        movsd   [xBP - 10h], xmm0
     57        fld     qword [xBP - 20h]
     58        fld     qword [xBP - 10h]
    4759%else
    48     fld     qword [ebp + 10h]
    49     fld     qword [ebp + 8h]
     60        fld     qword [ebp + 10h]
     61        fld     qword [ebp + 08h]
    5062%endif
    5163
    52     fprem1
    53     fstsw   ax
    54     test    ah, 04h
    55     jnz     .done
    56     fstp    st1
    57 
    58 .done:
    59 %ifdef RT_ARCH_AMD64
    60     fstp    qword [rsp]
    61     movsd   xmm0, [rsp]
     64        ;
     65        ; The fprem1 only does between 32 and 64 rounds, so we have to loop
     66        ; here till we've got a final result.  We count down in ECX to
     67        ; avoid getting stuck here...
     68        ;
     69        mov     ecx, 2048 / 32 + 4
     70.again:
     71        fprem1
     72        fstsw   ax
     73        test    ah, (X86_FSW_C2 >> 8)
     74        jz      .done
     75        dec     cx
     76        jnz     .again
     77%ifdef RT_STRICT
     78        int3
    6279%endif
    6380
    64     leave
    65     ret
     81        ;
     82        ; Return the result.
     83        ;
     84.done:
     85        fstp    st1
     86%ifdef RT_ARCH_AMD64
     87        fstp    qword [rsp]
     88        movsd   xmm0, [rsp]
     89%endif
     90
     91        leave
     92        ret
    6693ENDPROC   RT_NOCRT(remainder)
    6794
  • trunk/src/VBox/Runtime/common/math/remainderf.asm

    r96014 r96218  
    2525;
    2626
     27
     28%define RT_ASM_WITH_SEH64
    2729%include "iprt/asmdefs.mac"
     30%include "iprt/x86.mac"
     31
    2832
    2933BEGINCODE
     
    3135;;
    3236; See SUS.
    33 ; @returns st(0)
    34 ; @param    rf1    [ebp + 08h]  xmm0
    35 ; @param    rf2    [ebp + 0ch]  xmm1
     37; @returns  st(0) / xmm0
     38; @param    rf1    [ebp + 8h]   xmm0    Dividend.
     39; @param    rf2    [ebp + 10h]  xmm1    Divisor.
    3640RT_NOCRT_BEGINPROC remainderf
    37     push    xBP
    38     mov     xBP, xSP
    39     sub     xSP, 20h
     41        push    xBP
     42        SEH64_PUSH_xBP
     43        mov     xBP, xSP
     44        SEH64_SET_FRAME_xBP 0
     45%ifdef RT_ARCH_AMD64
     46        sub     xSP, 20h
     47        SEH64_ALLOCATE_STACK 20h
     48%endif
     49        SEH64_END_PROLOGUE
    4050
     51        ;
     52        ; Load the dividend into st0 and divisor into st1.
     53        ;
    4154%ifdef RT_ARCH_AMD64
    42     movss   [rsp], xmm1
    43     movss   [rsp + 10h], xmm0
    44     fld     dword [rsp]
    45     fld     dword [rsp + 10h]
     55        movss   [xBP - 20h], xmm1
     56        movss   [xBP - 10h], xmm0
     57        fld     dword [xBP - 20h]
     58        fld     dword [xBP - 10h]
    4659%else
    47     fld     dword [ebp + 0ch]
    48     fld     dword [ebp + 8h]
     60        fld     dword [ebp + 0ch]
     61        fld     dword [ebp + 08h]
    4962%endif
    5063
    51     fprem1
    52     fstsw   ax
    53     test    ah, 04h
    54     jnz     .done
    55     fstp    st1
    56 
    57 .done:
    58 %ifdef RT_ARCH_AMD64
    59     fstp    dword [rsp]
    60     movss   xmm0, [rsp]
     64        ;
     65        ; The fprem1 only does between 32 and 64 rounds, so we have to loop
     66        ; here till we've got a final result.  We count down in ECX to
     67        ; avoid getting stuck here...
     68        ;
     69        mov     ecx, 256 / 32 + 4
     70.again:
     71        fprem1
     72        fstsw   ax
     73        test    ah, (X86_FSW_C2 >> 8)
     74        jz      .done
     75        dec     cx
     76        jnz     .again
     77%ifdef RT_STRICT
     78        int3
    6179%endif
    6280
    63     leave
    64     ret
     81        ;
     82        ; Return the result.
     83        ;
     84.done:
     85        fstp    st1
     86%ifdef RT_ARCH_AMD64
     87        fstp    dword [rsp]
     88        movss   xmm0, [rsp]
     89%endif
     90
     91        leave
     92        ret
    6593ENDPROC   RT_NOCRT(remainderf)
    6694
  • trunk/src/VBox/Runtime/common/math/remainderl.asm

    r96014 r96218  
    2525;
    2626
     27
     28%define RT_ASM_WITH_SEH64
    2729%include "iprt/asmdefs.mac"
     30%include "iprt/x86.mac"
     31
    2832
    2933BEGINCODE
     
    3539; @param    lrd2    [rbp + 20h]
    3640RT_NOCRT_BEGINPROC remainderl
    37     push    xBP
    38     mov     xBP, xSP
     41        push    xBP
     42        SEH64_PUSH_xBP
     43        mov     xBP, xSP
     44        SEH64_SET_FRAME_xBP 0
     45        SEH64_END_PROLOGUE
    3946
    40 %ifdef RT_ARCH_AMD64
    41     fld     tword [rbp + 10h + RTLRD_CB]
    42     fld     tword [rbp + 10h]
    43 %else
    44     fld     tword [ebp + 8h + RTLRD_CB]
    45     fld     tword [ebp + 8h]
     47        ;
     48        ; Load the dividend into st0 and divisor into st1.
     49        ;
     50        fld     tword [xBP + 2*xCB + RTLRD_CB]
     51        fld     tword [xBP + 2*xCB]
     52
     53        ;
     54        ; The fprem1 only does between 32 and 64 rounds, so we have to loop
     55        ; here till we've got a final result.  We count down in ECX to
     56        ; avoid getting stuck here...
     57        ;
     58        mov     ecx, 16384 / 32 + 4
     59.again:
     60        fprem1
     61        fstsw   ax
     62        test    ah, (X86_FSW_C2 >> 8)
     63        jz      .done
     64        dec     cx
     65        jnz     .again
     66%ifdef RT_STRICT
     67        int3
    4668%endif
    4769
    48     fprem1
    49     fstsw   ax
    50     test    ah, 04h
    51     jnz     .done
    52     fstp    st1
    53 
     70        ;
     71        ; Return the result.
     72        ;
    5473.done:
    55     leave
    56     ret
     74        fstp    st1
     75        leave
     76        ret
    5777ENDPROC   RT_NOCRT(remainderl)
    5878
  • trunk/src/VBox/Runtime/testcase/tstRTNoCrt-2.cpp

    r96217 r96218  
    240240                || RTFLOAT64U_IS_NAN(&uNoCrtRet) \
    241241                || RTFLOAT64U_IS_NAN(&uCrtRet) ) ) \
     242        { \
     243            RTStrFormatR64(g_szFloat[0], sizeof(g_szFloat[0]), &uNoCrtRet, 0, 0, RTSTR_F_SPECIAL); \
     244            RTStrFormatR64(g_szFloat[1], sizeof(g_szFloat[0]), &uCrtRet,   0, 0, RTSTR_F_SPECIAL); \
     245            RTTestFailed(g_hTest, "line %u: %s%s: noCRT => %s; CRT => %s", \
     246                         __LINE__, #a_Fn, #a_Args, g_szFloat[0], g_szFloat[1]); \
     247        } \
     248    } while (0)
     249
     250#define CHECK_DBL_SAME_RELAXED_NAN(a_Fn, a_Args) do { \
     251        RTFLOAT64U uNoCrtRet, uCrtRet; \
     252        uNoCrtRet.r = RT_NOCRT(a_Fn) a_Args; \
     253        uCrtRet.r   =          a_Fn  a_Args; \
     254        if (   !RTFLOAT64U_ARE_IDENTICAL(&uNoCrtRet, &uCrtRet) \
     255            && (   !RTFLOAT64U_IS_NAN(&uNoCrtRet) \
     256                || !RTFLOAT64U_IS_NAN(&uCrtRet) ) ) \
    242257        { \
    243258            RTStrFormatR64(g_szFloat[0], sizeof(g_szFloat[0]), &uNoCrtRet, 0, 0, RTSTR_F_SPECIAL); \
     
    24532468
    24542469
     2470void testRemainder()
     2471{
     2472    RTTestSub(g_hTest, "remainder[f]");
     2473
     2474    /* The UCRT and x87 FPU generally disagree on the sign of the NaN, so don't be too picky here for now. */
     2475
     2476    CHECK_DBL(        RT_NOCRT(remainder)(              1.0,                    1.0), +0.0);
     2477    CHECK_DBL(        RT_NOCRT(remainder)(              1.5,                    1.0), -0.5);
     2478    CHECK_DBL_SAME_RELAXED_NAN(remainder,(              1.0,                    1.0));
     2479    CHECK_DBL_SAME_RELAXED_NAN(remainder,(              1.5,                    1.0));
     2480    CHECK_DBL_SAME_RELAXED_NAN(remainder,(             +0.0,                   +0.0));
     2481    CHECK_DBL_SAME_RELAXED_NAN(remainder,(             +0.0,                   -0.0));
     2482    CHECK_DBL_SAME_RELAXED_NAN(remainder,(             -0.0,                   -0.0));
     2483    CHECK_DBL_SAME_RELAXED_NAN(remainder,(             -0.0,                   +0.0));
     2484    CHECK_DBL_SAME_RELAXED_NAN(remainder,(         999999.0,                33334.0));
     2485    CHECK_DBL_SAME_RELAXED_NAN(remainder,(        -999999.0,                33334.0));
     2486    CHECK_DBL_SAME_RELAXED_NAN(remainder,(        -999999.0,               -33334.0));
     2487    CHECK_DBL_SAME_RELAXED_NAN(remainder,(         999999.0,               -33334.0));
     2488    CHECK_DBL_SAME_RELAXED_NAN(remainder,(      39560.32334,              9605.5546));
     2489    CHECK_DBL_SAME_RELAXED_NAN(remainder,(      39560.32334,          -59079.345069));
     2490    CHECK_DBL_SAME_RELAXED_NAN(remainder,(        +INFINITY,              +INFINITY));
     2491    CHECK_DBL_SAME_RELAXED_NAN(remainder,(              2.4,              +INFINITY));
     2492    CHECK_DBL_SAME_RELAXED_NAN(remainder,(        +INFINITY,                    2.4));
     2493    CHECK_DBL_SAME_RELAXED_NAN(remainder,(2.34960584706e100,       7.6050698459e+13));
     2494    CHECK_DBL_SAME_RELAXED_NAN(remainder,(2.34960584706e300,      -7.6050698459e-13));
     2495
     2496    CHECK_DBL(        RT_NOCRT(remainderf)(              1.0f,                   1.0f), +0.0f);
     2497    CHECK_DBL(        RT_NOCRT(remainderf)(              1.5f,                   1.0f), -0.5f);
     2498    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(              1.0f,                   1.0f));
     2499    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(              1.5f,                   1.0f));
     2500    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(             +0.0f,                  +0.0f));
     2501    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(             +0.0f,                  -0.0f));
     2502    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(             -0.0f,                  -0.0f));
     2503    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(             -0.0f,                  +0.0f));
     2504    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(         999999.0f,               33334.0f));
     2505    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(        -999999.0f,               33334.0f));
     2506    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(        -999999.0f,              -33334.0f));
     2507    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(         999999.0f,              -33334.0f));
     2508    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(      39560.32334f,             9605.5546f));
     2509    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(      39560.32334f,         -59079.345069f));
     2510    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(         +INFINITY,              +INFINITY));
     2511    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(              2.4f,              +INFINITY));
     2512    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(         +INFINITY,                   2.4f));
     2513    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(-2.34960584706e+35f,     7.6050698459e-23f));
     2514    CHECK_DBL_SAME_RELAXED_NAN(remainderf,(2.34960584706e+35f,      7.6050698459e-13f));
     2515
     2516}
     2517
     2518
    24552519
    24562520
     
    25052569    testLdExp();
    25062570    testFma();
     2571    testRemainder();
    25072572
    25082573#if 0
     
    25142579    ../common/math/cosf.asm \
    25152580    ../common/math/cosl.asm \
    2516     ../common/math/ldexp.asm \
    2517     ../common/math/ldexpf.asm \
    25182581    ../common/math/log.asm \
    25192582    ../common/math/logf.asm \
    2520     ../common/math/remainder.asm \
    2521     ../common/math/remainderf.asm \
    25222583    ../common/math/sin.asm \
    25232584    ../common/math/sinf.asm \
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette