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.nasm
     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     SECTION .text
     24 
     25 extern ASM_PFX(InternalMathDivRemU64x32)
     26 
     27 ;------------------------------------------------------------------------------
     28 ; UINT64
     29 ; EFIAPI
     30 ; InternalMathDivRemU64x64 (
     31 ;   IN      UINT64                    Dividend,
     32 ;   IN      UINT64                    Divisor,
     33 ;   OUT     UINT64                    *Remainder    OPTIONAL
     34 ;   );
     35 ;------------------------------------------------------------------------------
     36 global ASM_PFX(InternalMathDivRemU64x64)
     37 ASM_PFX(InternalMathDivRemU64x64):
     38     mov     ecx, [esp + 16]             ; ecx <- divisor[32..63]
     39     test    ecx, ecx
     40     jnz     _@DivRemU64x64              ; call _@DivRemU64x64 if Divisor > 2^32
     41     mov     ecx, [esp + 20]
     42     jecxz   .0
     43     and     dword [ecx + 4], 0      ; zero high dword of remainder
     44     mov     [esp + 16], ecx             ; set up stack frame to match DivRemU64x32
     45 .0:
     46     jmp     ASM_PFX(InternalMathDivRemU64x32)
     47 
     48 _@DivRemU64x64:
     49     push    ebx
     50     push    esi
     51     push    edi
     52     mov     edx, dword [esp + 20]
     53     mov     eax, dword [esp + 16]   ; edx:eax <- dividend
     54     mov     edi, edx
     55     mov     esi, eax                    ; edi:esi <- dividend
     56     mov     ebx, dword [esp + 24]   ; ecx:ebx <- divisor
     57 .1:
     58     shr     edx, 1
     59     rcr     eax, 1
     60     shrd    ebx, ecx, 1
     61     shr     ecx, 1
     62     jnz     .1
     63     div     ebx
     64     mov     ebx, eax                    ; ebx <- quotient
     65     mov     ecx, [esp + 28]             ; ecx <- high dword of divisor
     66     mul     dword [esp + 24]        ; edx:eax <- quotient * divisor[0..31]
     67     imul    ecx, ebx                    ; ecx <- quotient * divisor[32..63]
     68     add     edx, ecx                    ; edx <- (quotient * divisor)[32..63]
     69     mov     ecx, dword [esp + 32]   ; ecx <- addr for Remainder
     70     jc      @TooLarge                   ; product > 2^64
     71     cmp     edi, edx                    ; compare high 32 bits
     72     ja      @Correct
     73     jb      @TooLarge                   ; product > dividend
     74     cmp     esi, eax
     75     jae     @Correct                    ; product <= dividend
     76 @TooLarge:
     77     dec     ebx                         ; adjust quotient by -1
     78     jecxz   @Return                     ; return if Remainder == NULL
     79     sub     eax, dword [esp + 24]
     80     sbb     edx, dword [esp + 28]   ; edx:eax <- (quotient - 1) * divisor
     81 @Correct:
     82     jecxz   @Return
     83     sub     esi, eax
     84     sbb     edi, edx                    ; edi:esi <- remainder
     85     mov     [ecx], esi
     86     mov     [ecx + 4], edi
     87 @Return:
     88     mov     eax, ebx                    ; eax <- quotient
     89     xor     edx, edx                    ; quotient is 32 bits long
     90     pop     edi
     91     pop     esi
     92     pop     ebx
     93     ret
     94 
     95