Home | History | Annotate | Download | only in Ia32
      1 #------------------------------------------------------------------------------
      2 #
      3 # Copyright (c) 2006 - 2008, 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.S
     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 ASM_GLOBAL ASM_PFX(InternalMathDivRemU64x32), ASM_PFX(InternalMathDivRemU64x64)
     24 
     25 #------------------------------------------------------------------------------
     26 # UINT64
     27 # EFIAPI
     28 # InternalMathDivRemU64x64 (
     29 #   IN      UINT64                    Dividend,
     30 #   IN      UINT64                    Divisor,
     31 #   OUT     UINT64                    *Remainder    OPTIONAL
     32 #   );
     33 #------------------------------------------------------------------------------
     34 ASM_PFX(InternalMathDivRemU64x64):
     35     movl    16(%esp), %ecx              # ecx <- divisor[32..63]
     36     testl   %ecx, %ecx
     37     jnz     Hard                        # call _@DivRemU64x64 if Divisor > 2^32
     38     movl    20(%esp), %ecx
     39     jecxz   L1
     40     andl     $0, 4(%ecx)                # zero high dword of remainder
     41     movl    %ecx, 16(%esp)              # set up stack frame to match DivRemU64x32
     42 L1:
     43     jmp     ASM_PFX(InternalMathDivRemU64x32)
     44 Hard:
     45     push    %ebx
     46     push    %esi
     47     push    %edi
     48     mov     20(%esp), %edx
     49     mov     16(%esp), %eax              # edx:eax <- dividend
     50     movl    %edx, %edi
     51     movl    %eax, %esi                  # edi:esi <- dividend
     52     mov     24(%esp), %ebx              # ecx:ebx <- divisor
     53 L2:
     54     shrl    %edx
     55     rcrl    $1, %eax
     56     shrdl   $1, %ecx, %ebx
     57     shrl    %ecx
     58     jnz     L2
     59     divl    %ebx
     60     movl    %eax, %ebx                  # ebx <- quotient
     61     movl    28(%esp), %ecx              # ecx <- high dword of divisor
     62     mull    24(%esp)                    # edx:eax <- quotient * divisor[0..31]
     63     imull   %ebx, %ecx                  # ecx <- quotient * divisor[32..63]
     64     addl    %ecx, %edx                  # edx <- (quotient * divisor)[32..63]
     65     mov     32(%esp), %ecx              # ecx <- addr for Remainder
     66     jc      TooLarge                    # product > 2^64
     67     cmpl    %edx, %edi                  # compare high 32 bits
     68     ja      Correct
     69     jb      TooLarge                    # product > dividend
     70     cmpl    %eax, %esi
     71     jae     Correct                     # product <= dividend
     72 TooLarge:
     73     decl    %ebx                        # adjust quotient by -1
     74     jecxz   Return                      # return if Remainder == NULL
     75     sub     24(%esp), %eax
     76     sbb     28(%esp), %edx              # edx:eax <- (quotient - 1) * divisor
     77 Correct:
     78     jecxz   Return
     79     subl    %eax, %esi
     80     sbbl    %edx, %edi                  # edi:esi <- remainder
     81     movl    %esi, (%ecx)
     82     movl    %edi, 4(%ecx)
     83 Return:
     84     movl    %ebx, %eax                  # eax <- quotient
     85     xorl    %edx, %edx                  # quotient is 32 bits long
     86     pop     %edi
     87     pop     %esi
     88     pop     %ebx
     89     ret
     90