VirtualBox

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


Ignore:
Timestamp:
Feb 8, 2023 4:01:15 PM (2 years ago)
Author:
vboxsync
Message:

IPRT/vcc: Applied the unsigned 64-bit division optimizations to the div and rem variants too. bugref:10261

Location:
trunk/src/VBox/Runtime/common/compiler/vcc
Files:
3 edited
1 copied

Legend:

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

    r98508 r98509  
    4040;*********************************************************************************************************************************
    4141%include "iprt/asmdefs.mac"
     42%include "x86-aulldvrm-core.mac"
    4243
    4344
    44 ;*********************************************************************************************************************************
    45 ;*  External Symbols                                                                                                             *
    46 ;*********************************************************************************************************************************
    47 extern NAME(RTVccUInt64Div)
     45rtVccUnsignedDivision __aulldiv, 1
    4846
    49 
    50 ;;
    51 ; Division of unsigned 64-bit values, returning the quotient.
    52 ;
    53 ; @returns  Quotient in edx:eax.
    54 ; @param    [ebp+08h]   Dividend (64-bit)
    55 ; @param    [ebp+10h]   Divisor (64-bit)
    56 ;
    57 BEGINPROC_RAW   __aulldiv
    58         push    ebp
    59         mov     ebp, esp
    60         sub     esp, 10h                    ; space for quotient and remainder.
    61 
    62         ; Call RTVccUInt64Div(RTUINT64U const *paDividendDivisor, RTUINT64U *paQuotientRemainder)
    63         mov     edx, esp
    64         push    edx
    65         lea     ecx, [ebp + 8]
    66         push    ecx
    67         call    NAME(RTVccUInt64Div)
    68 
    69         ; Load the result (quotient).
    70         mov     eax, [ebp - 10h]
    71         mov     edx, [ebp - 10h + 4]
    72 
    73         leave
    74         ret     10h
    75 ENDPROC_RAW     __aulldiv
    76 
  • trunk/src/VBox/Runtime/common/compiler/vcc/x86-aulldvrm-core.mac

    r98508 r98509  
    4242
    4343
    44 ;*********************************************************************************************************************************
    45 ;*  External Symbols                                                                                                             *
    46 ;*********************************************************************************************************************************
    47 extern NAME(RTVccUInt64Div)
    48 
     44;;
     45; 64-bit unsigned division.
     46;
     47; @param    1   Function name.
     48; @param    2   dvrm=0, div=1, rem=1
     49;
     50%macro rtVccUnsignedDivision 2
    4951
    5052;;
     
    5759; @note     The remainder registers are swapped compared to Watcom's I8D and U8D.
    5860;
    59 BEGINPROC_RAW   __aulldvrm
     61BEGINPROC_RAW   %1
     62%if 1
     63        ;
     64        ; This code is duplicated in in x86-aulldiv.asm and x86-aulldvrm.asm.
     65        ; Apply fixes everywhere.
     66        ;
    6067        push    ebp
    6168        mov     ebp, esp
     69 %if %2 > 0
     70        push    ebx
     71 %endif
    6272
    6373%define DIVIDEND_LO ebp + 08h
     
    7888        xor     edx, edx
    7989        div     ebx
     90 %if %2 <= 1
    8091        mov     ecx, eax                    ; high quotient bits.
     92 %endif
    8193
    8294        ; step 2: (dividend_lo + step_1_remainder) / divisor
     
    8496        div     ebx                         ; -> eax = low quotient, edx = remainder.
    8597
     98 %if %2 <= 1
    8699        xchg    edx, ecx                    ; ecx = (low) remainder, edx = saved high quotient from step 1
     100  %if %2 == 0
    87101        xor     ebx, ebx                    ; ebx = high remainder is zero, since divisor is 32-bit.
    88 
     102  %endif
     103 %else
     104        mov     eax, edx
     105        xor     edx, edx                    ; edx:eax = remainder
     106 %endif
     107
     108 %if %2 > 0
     109        pop     ebx
     110 %endif
    89111        leave
    90112        ret     10h
    91113
    92 %if 1
    93114        ;
    94115        ; The divisor is larger than 32 bits.
     
    151172        jc      .quotient_is_one_above
    152173.done:
     174 %if %2 <= 1
    153175        mov     eax, edi
    154         xor     edx, edx
     176        xor     edx, edx                    ; edx:eax = quotient
     177 %else
     178        mov     eax, ecx
     179        mov     edx, ebx                    ; edx:eax = remainder
     180 %endif
    155181
    156182        pop     edi
     183 %if %2 > 0
     184        pop     ebx
     185 %endif
    157186        leave
    158187        ret     10h
    159188
    160189.quotient_is_one_above_and_calc_remainder:
     190 %if %2 != 1
    161191        sub     ecx, eax
    162192        sbb     ebx, edx
     193 %endif
    163194.quotient_is_one_above:
     195 %if %2 != 1
    164196        add     ecx, [DIVISOR_LO]
    165197        adc     ebx, [DIVISOR_HI]
     198 %endif
     199 %if %2 != 2
    166200        dec     edi
     201 %endif
    167202        jmp     .done
    168203
     
    171206        ; Fall back on a rather slow C implementation.
    172207        ;
    173 .full_64_bit_divisor:
     208        push    ebp
     209        mov     ebp, esp
     210
    174211        ; Call RTVccUInt64Div(RTUINT64U const *paDividendDivisor, RTUINT64U *paQuotientRemainder)
    175212        sub     esp, 10h                    ; space for quotient and remainder.
     
    178215        lea     ecx, [ebp + 8]
    179216        push    ecx
     217        extern  NAME(RTVccUInt64Div)
    180218        call    NAME(RTVccUInt64Div)
    181219
    182220        ; Load the result.
     221 %if %2 != 2
    183222        mov     eax, [ebp - 10h]
    184223        mov     edx, [ebp - 10h + 4]
    185224
     225  %if %2 != 1
    186226        mov     ecx, [ebp - 08h]
    187227        mov     ebx, [ebp - 08h + 4]
     228  %endif
     229 %else
     230        mov     eax, [ebp - 08h]
     231        mov     edx, [ebp - 08h + 4]
     232 %endif
    188233        leave
    189234        ret     10h
    190 
    191235%endif
    192 ENDPROC_RAW     __aulldvrm
    193 
     236ENDPROC_RAW     %1
     237%endm
  • trunk/src/VBox/Runtime/common/compiler/vcc/x86-aulldvrm.asm

    r98508 r98509  
    4040;*********************************************************************************************************************************
    4141%include "iprt/asmdefs.mac"
     42%include "x86-aulldvrm-core.mac"
    4243
    4344
    44 ;*********************************************************************************************************************************
    45 ;*  External Symbols                                                                                                             *
    46 ;*********************************************************************************************************************************
    47 extern NAME(RTVccUInt64Div)
     45rtVccUnsignedDivision __aulldvrm, 0
    4846
    49 
    50 ;;
    51 ; Division of unsigned 64-bit values, returning both quotient and remainder.
    52 ;
    53 ; @returns  Quotient in edx:eax, remainder in ebx:ecx.
    54 ; @param    [ebp+08h]   Dividend (64-bit)
    55 ; @param    [ebp+10h]   Divisor (64-bit)
    56 ;
    57 ; @note     The remainder registers are swapped compared to Watcom's I8D and U8D.
    58 ;
    59 BEGINPROC_RAW   __aulldvrm
    60         push    ebp
    61         mov     ebp, esp
    62 
    63 %define DIVIDEND_LO ebp + 08h
    64 %define DIVIDEND_HI ebp + 0ch
    65 %define DIVISOR_LO  ebp + 10h
    66 %define DIVISOR_HI  ebp + 14h
    67 
    68         ;
    69         ; If the divisor is only 32-bit wide as we can do a two-step division on 32-bit units.
    70         ;
    71         mov     ebx, [DIVISOR_HI]
    72         or      ebx, ebx
    73         jnz     .full_64_bit_divisor
    74 
    75         ; step 1: dividend_hi / divisor
    76         mov     ebx, [DIVISOR_LO]
    77         mov     eax, [DIVIDEND_HI]
    78         xor     edx, edx
    79         div     ebx
    80         mov     ecx, eax                    ; high quotient bits.
    81 
    82         ; step 2: (dividend_lo + step_1_remainder) / divisor
    83         mov     eax, [DIVIDEND_LO]          ; edx contains the remainder from the first step.
    84         div     ebx                         ; -> eax = low quotient, edx = remainder.
    85 
    86         xchg    edx, ecx                    ; ecx = (low) remainder, edx = saved high quotient from step 1
    87         xor     ebx, ebx                    ; ebx = high remainder is zero, since divisor is 32-bit.
    88 
    89         leave
    90         ret     10h
    91 
    92 %if 1
    93         ;
    94         ; The divisor is larger than 32 bits.
    95         ;
    96         ; We can approximate the quotient by reducing the divisor to 32 bits
    97         ; (reducing the dividend accordingly) and perform a 32-bit division.
    98         ; The result will be at most one off.
    99         ;
    100         ; The remainder has to be calculated using multiplication and
    101         ; subtraction.
    102         ;
    103 .full_64_bit_divisor:
    104         push    edi
    105 
    106         ; Find the shift count needed to reduce the divisor to 32-bit.
    107         bsr     ecx, ebx
    108         inc     cl
    109         test    cl, ~31
    110         jnz     .shift_32
    111 
    112         ; Shift the divisor into edi.
    113         mov     edi, [DIVISOR_LO]
    114         shrd    edi, ebx, cl                ; edi = reduced divisor
    115 
    116         ; Shift the dividend into edx:eax.
    117         mov     eax, [DIVIDEND_LO]
    118         mov     edx, [DIVIDEND_HI]
    119         shrd    eax, edx, cl
    120         shr     edx, cl
    121         jmp     .shifted
    122 
    123 .shift_32:  ; simplified version.
    124         mov     edi, ebx
    125         mov     eax, [DIVIDEND_HI]
    126         xor     edx, edx
    127 .shifted:
    128 
    129         ; Divide and save the approximate quotient (Qapprox) in edi.
    130         div     edi
    131         mov     edi, eax                    ; edi = Qapprox
    132 
    133         ; Now multiply Qapprox with the divisor.
    134         mul     dword [DIVISOR_HI]
    135         mov     ecx, eax                    ; temporary storage
    136         mov     eax, [DIVISOR_LO]
    137         mul     edi
    138         add     edx, ecx                    ; edx:eax = QapproxDividend = Qapprox * divisor
    139 
    140         ; Preload the dividend into ebx:ecx for remainder calculation and for adjusting Qapprox.
    141         mov     ecx, [DIVIDEND_LO]
    142         mov     ebx, [DIVIDEND_HI]
    143 
    144         ; If carry is set, the result overflowed 64 bits, so the quotient must be too large.
    145         jc      .quotient_is_one_above_and_calc_remainder
    146 
    147         ; Calculate the remainder, if this overflows (CF) it means Qapprox is
    148         ; one above and we need to reduce it and the adjust the remainder.
    149         sub     ecx, eax
    150         sbb     ebx, edx
    151         jc      .quotient_is_one_above
    152 .done:
    153         mov     eax, edi
    154         xor     edx, edx
    155 
    156         pop     edi
    157         leave
    158         ret     10h
    159 
    160 .quotient_is_one_above_and_calc_remainder:
    161         sub     ecx, eax
    162         sbb     ebx, edx
    163 .quotient_is_one_above:
    164         add     ecx, [DIVISOR_LO]
    165         adc     ebx, [DIVISOR_HI]
    166         dec     edi
    167         jmp     .done
    168 
    169 %else
    170         ;
    171         ; Fall back on a rather slow C implementation.
    172         ;
    173 .full_64_bit_divisor:
    174         ; Call RTVccUInt64Div(RTUINT64U const *paDividendDivisor, RTUINT64U *paQuotientRemainder)
    175         sub     esp, 10h                    ; space for quotient and remainder.
    176         mov     edx, esp
    177         push    edx
    178         lea     ecx, [ebp + 8]
    179         push    ecx
    180         call    NAME(RTVccUInt64Div)
    181 
    182         ; Load the result.
    183         mov     eax, [ebp - 10h]
    184         mov     edx, [ebp - 10h + 4]
    185 
    186         mov     ecx, [ebp - 08h]
    187         mov     ebx, [ebp - 08h + 4]
    188         leave
    189         ret     10h
    190 
    191 %endif
    192 ENDPROC_RAW     __aulldvrm
    193 
  • trunk/src/VBox/Runtime/common/compiler/vcc/x86-aullrem.asm

    r98508 r98509  
    4040;*********************************************************************************************************************************
    4141%include "iprt/asmdefs.mac"
     42%include "x86-aulldvrm-core.mac"
    4243
     44rtVccUnsignedDivision __aullrem, 2
    4345
    44 ;*********************************************************************************************************************************
    45 ;*  External Symbols                                                                                                             *
    46 ;*********************************************************************************************************************************
    47 extern NAME(RTVccUInt64Div)
    48 
    49 
    50 ;;
    51 ; Division of unsigned 64-bit values, returning the remainder.
    52 ;
    53 ; @returns  Remainder in edx:eax.
    54 ; @param    [ebp+08h]   Dividend (64-bit)
    55 ; @param    [ebp+10h]   Divisor (64-bit)
    56 ;
    57 BEGINPROC_RAW   __aullrem
    58         push    ebp
    59         mov     ebp, esp
    60         sub     esp, 10h                    ; space for quotient and remainder.
    61 
    62         ; Call RTVccUInt64Div(RTUINT64U const *paDividendDivisor, RTUINT64U *paQuotientRemainder)
    63         mov     edx, esp
    64         push    edx
    65         lea     ecx, [ebp + 8]
    66         push    ecx
    67         call    NAME(RTVccUInt64Div)
    68 
    69         ; Load the result (remainder).
    70         mov     eax, [ebp - 08h]
    71         mov     edx, [ebp - 08h + 4]
    72 
    73         leave
    74         ret     10h
    75 ENDPROC_RAW     __aullrem
    76 
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