Changeset 98509 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Feb 8, 2023 4:01:15 PM (2 years ago)
- 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 40 40 ;********************************************************************************************************************************* 41 41 %include "iprt/asmdefs.mac" 42 %include "x86-aulldvrm-core.mac" 42 43 43 44 44 ;********************************************************************************************************************************* 45 ;* External Symbols * 46 ;********************************************************************************************************************************* 47 extern NAME(RTVccUInt64Div) 45 rtVccUnsignedDivision __aulldiv, 1 48 46 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 __aulldiv58 push ebp59 mov ebp, esp60 sub esp, 10h ; space for quotient and remainder.61 62 ; Call RTVccUInt64Div(RTUINT64U const *paDividendDivisor, RTUINT64U *paQuotientRemainder)63 mov edx, esp64 push edx65 lea ecx, [ebp + 8]66 push ecx67 call NAME(RTVccUInt64Div)68 69 ; Load the result (quotient).70 mov eax, [ebp - 10h]71 mov edx, [ebp - 10h + 4]72 73 leave74 ret 10h75 ENDPROC_RAW __aulldiv76 -
trunk/src/VBox/Runtime/common/compiler/vcc/x86-aulldvrm-core.mac
r98508 r98509 42 42 43 43 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 49 51 50 52 ;; … … 57 59 ; @note The remainder registers are swapped compared to Watcom's I8D and U8D. 58 60 ; 59 BEGINPROC_RAW __aulldvrm 61 BEGINPROC_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 ; 60 67 push ebp 61 68 mov ebp, esp 69 %if %2 > 0 70 push ebx 71 %endif 62 72 63 73 %define DIVIDEND_LO ebp + 08h … … 78 88 xor edx, edx 79 89 div ebx 90 %if %2 <= 1 80 91 mov ecx, eax ; high quotient bits. 92 %endif 81 93 82 94 ; step 2: (dividend_lo + step_1_remainder) / divisor … … 84 96 div ebx ; -> eax = low quotient, edx = remainder. 85 97 98 %if %2 <= 1 86 99 xchg edx, ecx ; ecx = (low) remainder, edx = saved high quotient from step 1 100 %if %2 == 0 87 101 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 89 111 leave 90 112 ret 10h 91 113 92 %if 193 114 ; 94 115 ; The divisor is larger than 32 bits. … … 151 172 jc .quotient_is_one_above 152 173 .done: 174 %if %2 <= 1 153 175 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 155 181 156 182 pop edi 183 %if %2 > 0 184 pop ebx 185 %endif 157 186 leave 158 187 ret 10h 159 188 160 189 .quotient_is_one_above_and_calc_remainder: 190 %if %2 != 1 161 191 sub ecx, eax 162 192 sbb ebx, edx 193 %endif 163 194 .quotient_is_one_above: 195 %if %2 != 1 164 196 add ecx, [DIVISOR_LO] 165 197 adc ebx, [DIVISOR_HI] 198 %endif 199 %if %2 != 2 166 200 dec edi 201 %endif 167 202 jmp .done 168 203 … … 171 206 ; Fall back on a rather slow C implementation. 172 207 ; 173 .full_64_bit_divisor: 208 push ebp 209 mov ebp, esp 210 174 211 ; Call RTVccUInt64Div(RTUINT64U const *paDividendDivisor, RTUINT64U *paQuotientRemainder) 175 212 sub esp, 10h ; space for quotient and remainder. … … 178 215 lea ecx, [ebp + 8] 179 216 push ecx 217 extern NAME(RTVccUInt64Div) 180 218 call NAME(RTVccUInt64Div) 181 219 182 220 ; Load the result. 221 %if %2 != 2 183 222 mov eax, [ebp - 10h] 184 223 mov edx, [ebp - 10h + 4] 185 224 225 %if %2 != 1 186 226 mov ecx, [ebp - 08h] 187 227 mov ebx, [ebp - 08h + 4] 228 %endif 229 %else 230 mov eax, [ebp - 08h] 231 mov edx, [ebp - 08h + 4] 232 %endif 188 233 leave 189 234 ret 10h 190 191 235 %endif 192 ENDPROC_RAW __aulldvrm193 236 ENDPROC_RAW %1 237 %endm -
trunk/src/VBox/Runtime/common/compiler/vcc/x86-aulldvrm.asm
r98508 r98509 40 40 ;********************************************************************************************************************************* 41 41 %include "iprt/asmdefs.mac" 42 %include "x86-aulldvrm-core.mac" 42 43 43 44 44 ;********************************************************************************************************************************* 45 ;* External Symbols * 46 ;********************************************************************************************************************************* 47 extern NAME(RTVccUInt64Div) 45 rtVccUnsignedDivision __aulldvrm, 0 48 46 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 __aulldvrm60 push ebp61 mov ebp, esp62 63 %define DIVIDEND_LO ebp + 08h64 %define DIVIDEND_HI ebp + 0ch65 %define DIVISOR_LO ebp + 10h66 %define DIVISOR_HI ebp + 14h67 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, ebx73 jnz .full_64_bit_divisor74 75 ; step 1: dividend_hi / divisor76 mov ebx, [DIVISOR_LO]77 mov eax, [DIVIDEND_HI]78 xor edx, edx79 div ebx80 mov ecx, eax ; high quotient bits.81 82 ; step 2: (dividend_lo + step_1_remainder) / divisor83 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 187 xor ebx, ebx ; ebx = high remainder is zero, since divisor is 32-bit.88 89 leave90 ret 10h91 92 %if 193 ;94 ; The divisor is larger than 32 bits.95 ;96 ; We can approximate the quotient by reducing the divisor to 32 bits97 ; (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 and101 ; subtraction.102 ;103 .full_64_bit_divisor:104 push edi105 106 ; Find the shift count needed to reduce the divisor to 32-bit.107 bsr ecx, ebx108 inc cl109 test cl, ~31110 jnz .shift_32111 112 ; Shift the divisor into edi.113 mov edi, [DIVISOR_LO]114 shrd edi, ebx, cl ; edi = reduced divisor115 116 ; Shift the dividend into edx:eax.117 mov eax, [DIVIDEND_LO]118 mov edx, [DIVIDEND_HI]119 shrd eax, edx, cl120 shr edx, cl121 jmp .shifted122 123 .shift_32: ; simplified version.124 mov edi, ebx125 mov eax, [DIVIDEND_HI]126 xor edx, edx127 .shifted:128 129 ; Divide and save the approximate quotient (Qapprox) in edi.130 div edi131 mov edi, eax ; edi = Qapprox132 133 ; Now multiply Qapprox with the divisor.134 mul dword [DIVISOR_HI]135 mov ecx, eax ; temporary storage136 mov eax, [DIVISOR_LO]137 mul edi138 add edx, ecx ; edx:eax = QapproxDividend = Qapprox * divisor139 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_remainder146 147 ; Calculate the remainder, if this overflows (CF) it means Qapprox is148 ; one above and we need to reduce it and the adjust the remainder.149 sub ecx, eax150 sbb ebx, edx151 jc .quotient_is_one_above152 .done:153 mov eax, edi154 xor edx, edx155 156 pop edi157 leave158 ret 10h159 160 .quotient_is_one_above_and_calc_remainder:161 sub ecx, eax162 sbb ebx, edx163 .quotient_is_one_above:164 add ecx, [DIVISOR_LO]165 adc ebx, [DIVISOR_HI]166 dec edi167 jmp .done168 169 %else170 ;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, esp177 push edx178 lea ecx, [ebp + 8]179 push ecx180 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 leave189 ret 10h190 191 %endif192 ENDPROC_RAW __aulldvrm193 -
trunk/src/VBox/Runtime/common/compiler/vcc/x86-aullrem.asm
r98508 r98509 40 40 ;********************************************************************************************************************************* 41 41 %include "iprt/asmdefs.mac" 42 %include "x86-aulldvrm-core.mac" 42 43 44 rtVccUnsignedDivision __aullrem, 2 43 45 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 __aullrem58 push ebp59 mov ebp, esp60 sub esp, 10h ; space for quotient and remainder.61 62 ; Call RTVccUInt64Div(RTUINT64U const *paDividendDivisor, RTUINT64U *paQuotientRemainder)63 mov edx, esp64 push edx65 lea ecx, [ebp + 8]66 push ecx67 call NAME(RTVccUInt64Div)68 69 ; Load the result (remainder).70 mov eax, [ebp - 08h]71 mov edx, [ebp - 08h + 4]72 73 leave74 ret 10h75 ENDPROC_RAW __aullrem76
Note:
See TracChangeset
for help on using the changeset viewer.