#------------------------------------------------------------------------------ | |
# | |
# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> | |
# This program and the accompanying materials | |
# are licensed and made available under the terms and conditions of the BSD License | |
# which accompanies this distribution. The full text of the license may be found at | |
# http://opensource.org/licenses/bsd-license.php. | |
# | |
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
# | |
# Module Name: | |
# | |
# DivU64x64Remainder.S | |
# | |
# Abstract: | |
# | |
# Calculate the quotient of a 64-bit integer by a 64-bit integer and returns | |
# both the quotient and the remainder | |
# | |
#------------------------------------------------------------------------------ | |
ASM_GLOBAL ASM_PFX(InternalMathDivRemU64x32), ASM_PFX(InternalMathDivRemU64x64) | |
#------------------------------------------------------------------------------ | |
# UINT64 | |
# EFIAPI | |
# InternalMathDivRemU64x64 ( | |
# IN UINT64 Dividend, | |
# IN UINT64 Divisor, | |
# OUT UINT64 *Remainder OPTIONAL | |
# ); | |
#------------------------------------------------------------------------------ | |
ASM_PFX(InternalMathDivRemU64x64): | |
movl 16(%esp), %ecx # ecx <- divisor[32..63] | |
testl %ecx, %ecx | |
jnz Hard # call _@DivRemU64x64 if Divisor > 2^32 | |
movl 20(%esp), %ecx | |
jecxz L1 | |
andl $0, 4(%ecx) # zero high dword of remainder | |
movl %ecx, 16(%esp) # set up stack frame to match DivRemU64x32 | |
L1: | |
jmp ASM_PFX(InternalMathDivRemU64x32) | |
Hard: | |
push %ebx | |
push %esi | |
push %edi | |
mov 20(%esp), %edx | |
mov 16(%esp), %eax # edx:eax <- dividend | |
movl %edx, %edi | |
movl %eax, %esi # edi:esi <- dividend | |
mov 24(%esp), %ebx # ecx:ebx <- divisor | |
L2: | |
shrl %edx | |
rcrl $1, %eax | |
shrdl $1, %ecx, %ebx | |
shrl %ecx | |
jnz L2 | |
divl %ebx | |
movl %eax, %ebx # ebx <- quotient | |
movl 28(%esp), %ecx # ecx <- high dword of divisor | |
mull 24(%esp) # edx:eax <- quotient * divisor[0..31] | |
imull %ebx, %ecx # ecx <- quotient * divisor[32..63] | |
addl %ecx, %edx # edx <- (quotient * divisor)[32..63] | |
mov 32(%esp), %ecx # ecx <- addr for Remainder | |
jc TooLarge # product > 2^64 | |
cmpl %edx, %edi # compare high 32 bits | |
ja Correct | |
jb TooLarge # product > dividend | |
cmpl %eax, %esi | |
jae Correct # product <= dividend | |
TooLarge: | |
decl %ebx # adjust quotient by -1 | |
jecxz Return # return if Remainder == NULL | |
sub 24(%esp), %eax | |
sbb 28(%esp), %edx # edx:eax <- (quotient - 1) * divisor | |
Correct: | |
jecxz Return | |
subl %eax, %esi | |
sbbl %edx, %edi # edi:esi <- remainder | |
movl %esi, (%ecx) | |
movl %edi, 4(%ecx) | |
Return: | |
movl %ebx, %eax # eax <- quotient | |
xorl %edx, %edx # quotient is 32 bits long | |
pop %edi | |
pop %esi | |
pop %ebx | |
ret |