VirtualBox

Changeset 106510 in vbox for trunk/src


Ignore:
Timestamp:
Oct 20, 2024 12:47:58 AM (4 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
165342
Message:

Runtime/ftol2-vcc.asm: Added ftoul2_legacy, ftoul2 and ftoui2 for the various /fpcvt+/arch modes of the 2022 compiler. jiraref:VBP-1171

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/compiler/vcc/ftol2-vcc.asm

    r106061 r106510  
    4040
    4141
     42%define RTFLOAT80U_EXP_BIAS                    (16383)
     43
     44
    4245;;
    4346; Convert st0 to integer returning it in eax, popping st0.
    4447;
    4548; @returns  value in eax
    46 ; @param    st0     The value to convet.  Will be popped.
    47 ; @uses     eax, st0, FSW.TOP
     49; @param    st0     The value to convert.  Will be popped.
     50; @uses     eax, st0, FSW.TOP, FSW.exception
    4851;
    4952GLOBALNAME_RAW  __ftol2_sse_excpt, function, RT_NOTHING
     
    6467;
    6568; @returns  value in edx:eax
    66 ; @param    st0     The value to convet.  Will be popped.
    67 ; @uses     eax, edx, st0, FSW.TOP
     69; @param    st0     The value to convert.  Will be popped.
     70; @uses     eax, edx, st0, FSW.TOP, FSW.exception
    6871;
    6972BEGINPROC_RAW   __ftol2
     
    7982ENDPROC_RAW     __ftol2
    8083
     84
     85;;
     86; Convert st0 to an unsigned integer returning it in edx:eax, popping st0.
     87;
     88; Used when /fpcvt:IA is given together with /ARCH:IA32 or /ARCH:SSE.
     89;
     90; @returns  value in edx:eax
     91; @param    st0     The value to convert.  Will be popped.
     92; @uses     eax, edx, st0, FSW.TOP
     93;
     94BEGINPROC_RAW   __ftoui2
     95        push    ebp
     96        mov     ebp, esp
     97
     98        ; Proper stack alignment for a qword store (see note below).
     99        sub     esp, 8h
     100        and     esp, 0fffffff8h             ; proper alignment.
     101
     102        ; Check if the value is unordered or negative.
     103        fldz
     104        fucomip st0, st1
     105        jp      .unordered                  ; PF=1 only when unordered.
     106        ja      .negative                   ; jumps if ZF=0 & CF=0, i.e. if zero > value.
     107
     108        ; Check if the value is too large for uint32_t.
     109        fld     dword [g_r32TwoToThePowerOf32]
     110        fucomip st0, st1                    ; if 1*2^32 <= value
     111        jbe     .too_large                  ; then jmp
     112
     113        ;
     114        ; The value is unproblematic, so just convert and return it.
     115        ;
     116        ; Note! We do a 64-bit conversion here, not a 32-bit. This helps with
     117        ;       values at or above 2**31.
     118        ;
     119        fisttp  qword [esp]                 ; Raise exceptions as appropriate, pop ST0.
     120        mov     eax, [esp]
     121.return:
     122        leave
     123        ret
     124
     125        ;
     126        ; Negative value.
     127        ;
     128.negative:
     129        ; If the value is -1.0 or smaller, treat it as unordered.
     130        fabs
     131        fld1
     132        fucomip st0, st1                    ; if 1.0 <= abs(value)
     133        jbe     .unordered                  ; then jmp  (jbe = jmp if ZF or/and CF set)
     134
     135        ; Values between -1.0 and 0 (both exclusively) are truncated to zero.
     136        fisttp  dword [esp]                 ; Raise exceptions as appropriate, pop ST0.
     137        xor     eax, eax
     138        jmp     .return
     139
     140        ; Return MAX after maybe raising an exception.
     141.unordered:
     142.too_large:
     143        fcomp   dword [g_r32QNaN]           ; Set C0-3, raise exceptions as appropriate, pop ST0.
     144        mov     eax, -1
     145        jmp     .return
     146ENDPROC_RAW     __ftoui2
     147
     148
     149;;
     150; Convert st0 to an unsigned long integer returning it in edx:eax, popping st0.
     151;
     152; Used when /fpcvt:IA is given together with /ARCH:IA32 or /ARCH:SSE.
     153;
     154; @returns  value in edx:eax
     155; @param    st0     The value to convert.  Will be popped.
     156; @uses     eax, edx, st0, FSW.TOP
     157;
     158BEGINPROC_RAW   __ftoul2
     159        push    ebp
     160        mov     ebp, esp
     161
     162        ; We may need to store a RTFLOAT80 and uint64_t, so make sure the stack is 16 byte aligned.
     163        sub     esp, 16h
     164        and     esp, 0fffffff0h
     165
     166        ; Check if the value is unordered or negative.
     167        fldz
     168        fucomip st0, st1
     169        jp      .unordered                  ; PF=1 only when unordered.
     170        ja      .negative                   ; jumps if ZF=0 & CF=0, i.e. if zero > value.
     171
     172        ; Check if the value is in signed 64-bit integer range, i.e. less than 1.0*2^63.
     173        fld     dword [g_r32TwoToThePowerOf63]
     174        fucomip st0, st1                                        ; if 1*2^63 <= value
     175        jbe     .larger_than_or_equal_to_2_to_the_power_of_63   ; then jmp;
     176
     177        ;
     178        ; The value is unproblematic for 64-bit signed conversion, so just convert and return it.
     179        ;
     180        fisttp  qword [esp]                 ; Raise exceptions as appropriate, pop ST0.
     181        mov     edx, [esp + 4]
     182        mov     eax, [esp]
     183.return:
     184        leave
     185        ret
     186
     187        ;
     188        ; We've got a value that so large that fisttp can't handle it, however
     189        ; it may still be covertable to uint64_t, iff the exponent is 63.
     190        ;
     191.larger_than_or_equal_to_2_to_the_power_of_63:
     192
     193        ; Save the value on the stack so we can examine it in it's full 80-bit format.
     194        fld     st0
     195        fstp    tword [esp]                 ; RTFLOAT80U
     196        movzx   eax, word [esp + 8]         ; The exponent and (zero) sign value.
     197
     198%ifdef RT_STRICT
     199        ; Negative numbers shall not end up here, we checked for that in the zero compare above!
     200        bt      eax, 15
     201        jnc     .sign_clear_as_expected
     202        int3
     203.sign_clear_as_expected:
     204        ; The exponent shall not be less than 63, we checked for that in the g_r32TwoToThePowerOf63 compare above!
     205        cmp     eax, RTFLOAT80U_EXP_BIAS+63
     206        jae     .exp_not_below_63_as_expected
     207        int3
     208.exp_not_below_63_as_expected:
     209%endif
     210
     211        ; Check that the exponent is 63, because if it isn't it must be higher
     212        ; and out of range for a conversion to uint64_t.
     213        cmp     eax, RTFLOAT80U_EXP_BIAS+63
     214        jne     .too_large
     215
     216        ; Check for unnormal values just to be on the safe side.
     217        mov     edx, [esp + 4]
     218        bt      edx, 31                     ; Check if the most significant bit in the mantissa is zero.
     219        jnc     .unnormal
     220
     221        ; Load the rest of the value.
     222        mov     eax, [esp]
     223        frndint                             ; Clear C1 & raising exceptions as appropriate.
     224        ffreep  st0
     225        jmp     .return
     226
     227        ;
     228        ; Negative value.
     229        ;
     230.negative:
     231        ; If the value is -1.0 or smaller, treat it as unordered.
     232        fabs
     233        fld1
     234        fucomip st0, st1                    ; if 1.0 <= abs(value)
     235        jbe     .unordered                  ; then jmp  (jbe = jmp if ZF or/and CF set)
     236
     237        ; Values between -1.0 and 0 (both exclusively) are truncated to zero.
     238        fisttp  qword [esp]                 ; Raise exceptions as appropriate, pop ST0.
     239        xor     edx, edx
     240        xor     eax, eax
     241        jmp     .return
     242
     243        ;
     244        ; Unordered or a value in the (-1.0, 0) range.
     245        ; Return -1 after popping ST0.
     246        ;
     247.unordered:
     248.unnormal:
     249.too_large:
     250        fcomp   dword [g_r32QNaN]           ; Set C0-3, raise exceptions as appropriate, pop ST0.
     251        mov     edx, -1
     252        mov     eax, -1
     253        jmp     .return
     254ENDPROC_RAW     __ftoul2
     255
     256
     257;;
     258; Convert st0 to unsigned integer returning it in edx:eax, popping st0.
     259;
     260; This is new with VC 14.3 / 2022 and changes how extreme values are handled.
     261;
     262; This is used for /ARCH:IA32 & /ARCH:SSE, the compiler generates inline conversion
     263; code for /ARCH:SSE2 it seems.  If either of those two are used with /fpcvt:IA, the
     264; __ftoul2 is used instead.
     265;
     266; @returns  value in edx:eax
     267; @param    st0     The value to convert.  Will be popped.
     268; @uses     eax, edx, st0, FSW.TOP
     269;
     270BEGINPROC_RAW   __ftoul2_legacy
     271        sub     esp, 4
     272        fst     dword [esp]
     273        pop     edx
     274        cmp     edx, 0x5f800000             ; RTFLOAT32U
     275        jae     __ftol2                     ; Jump if exponent >= 64 or the value is signed.
     276        jmp     __ftoul2
     277ENDPROC_RAW     __ftoul2_legacy
     278
     279
     280;
     281; Constants.
     282;
     283ALIGNCODE(4)
     284g_r32TwoToThePowerOf32:
     285        dd      0x4f800000                  ; 1.0*2^32
     286g_r32TwoToThePowerOf63:
     287        dd      0x5f000000                  ; 1.0*2^63
     288g_r32QNaN:
     289        dd      0xffc00000                  ; Quite negative NaN (RTFLOAT32U_INIT_QNAN)
     290
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