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 23ASM_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#------------------------------------------------------------------------------ 34ASM_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 42L1: 43 jmp ASM_PFX(InternalMathDivRemU64x32) 44Hard: 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 53L2: 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 72TooLarge: 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 77Correct: 78 jecxz Return 79 subl %eax, %esi 80 sbbl %edx, %edi # edi:esi <- remainder 81 movl %esi, (%ecx) 82 movl %edi, 4(%ecx) 83Return: 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