Home | History | Annotate | Download | only in Ia32
      1 ;------------------------------------------------------------------------------
      2 ;
      3 ; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
      4 ; This program and the accompanying materials
      5 ; are licensed and made available under the terms and conditions of the BSD License
      6 ; which accompanies this distribution.  The full text of the license may be found at
      7 ; http://opensource.org/licenses/bsd-license.php.
      8 ;
      9 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 ;
     12 ; Module Name:
     13 ;
     14 ;   DivU64x64Remainder.asm
     15 ;
     16 ; Abstract:
     17 ;
     18 ;   Calculate the quotient of a 64-bit integer by a 64-bit integer and returns
     19 ;   both the quotient and the remainder
     20 ;
     21 ;------------------------------------------------------------------------------
     22 
     23     .386
     24     .model  flat,C
     25     .code
     26 
     27 EXTERN  InternalMathDivRemU64x32:PROC
     28 
     29 ;------------------------------------------------------------------------------
     30 ; UINT64
     31 ; EFIAPI
     32 ; InternalMathDivRemU64x64 (
     33 ;   IN      UINT64                    Dividend,
     34 ;   IN      UINT64                    Divisor,
     35 ;   OUT     UINT64                    *Remainder    OPTIONAL
     36 ;   );
     37 ;------------------------------------------------------------------------------
     38 InternalMathDivRemU64x64    PROC
     39     mov     ecx, [esp + 16]             ; ecx <- divisor[32..63]
     40     test    ecx, ecx
     41     jnz     _@DivRemU64x64              ; call _@DivRemU64x64 if Divisor > 2^32
     42     mov     ecx, [esp + 20]
     43     jecxz   @F
     44     and     dword ptr [ecx + 4], 0      ; zero high dword of remainder
     45     mov     [esp + 16], ecx             ; set up stack frame to match DivRemU64x32
     46 @@:
     47     jmp     InternalMathDivRemU64x32
     48 InternalMathDivRemU64x64    ENDP
     49 
     50 _@DivRemU64x64  PROC PRIVATE    USES    ebx esi edi
     51     mov     edx, dword ptr [esp + 20]
     52     mov     eax, dword ptr [esp + 16]   ; edx:eax <- dividend
     53     mov     edi, edx
     54     mov     esi, eax                    ; edi:esi <- dividend
     55     mov     ebx, dword ptr [esp + 24]   ; ecx:ebx <- divisor
     56 @@:
     57     shr     edx, 1
     58     rcr     eax, 1
     59     shrd    ebx, ecx, 1
     60     shr     ecx, 1
     61     jnz     @B
     62     div     ebx
     63     mov     ebx, eax                    ; ebx <- quotient
     64     mov     ecx, [esp + 28]             ; ecx <- high dword of divisor
     65     mul     dword ptr [esp + 24]        ; edx:eax <- quotient * divisor[0..31]
     66     imul    ecx, ebx                    ; ecx <- quotient * divisor[32..63]
     67     add     edx, ecx                    ; edx <- (quotient * divisor)[32..63]
     68     mov     ecx, dword ptr [esp + 32]   ; ecx <- addr for Remainder
     69     jc      @TooLarge                   ; product > 2^64
     70     cmp     edi, edx                    ; compare high 32 bits
     71     ja      @Correct
     72     jb      @TooLarge                   ; product > dividend
     73     cmp     esi, eax
     74     jae     @Correct                    ; product <= dividend
     75 @TooLarge:
     76     dec     ebx                         ; adjust quotient by -1
     77     jecxz   @Return                     ; return if Remainder == NULL
     78     sub     eax, dword ptr [esp + 24]
     79     sbb     edx, dword ptr [esp + 28]   ; edx:eax <- (quotient - 1) * divisor
     80 @Correct:
     81     jecxz   @Return
     82     sub     esi, eax
     83     sbb     edi, edx                    ; edi:esi <- remainder
     84     mov     [ecx], esi
     85     mov     [ecx + 4], edi
     86 @Return:
     87     mov     eax, ebx                    ; eax <- quotient
     88     xor     edx, edx                    ; quotient is 32 bits long
     89     ret
     90 _@DivRemU64x64  ENDP
     91 
     92     END
     93