From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id 20480AC0A89 for ; Fri, 28 Jul 2023 06:41:59 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=mwBsMhdypstUX1bnglIPfc04mSMLxxAHjd/SKPhvboY=; c=relaxed/simple; d=groups.io; h=X-Received:X-Received:X-IronPort-AV:X-IronPort-AV:X-Received:X-ExtLoop1:X-IronPort-AV:X-IronPort-AV:X-Received:From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:X-Gm-Message-State:Content-Transfer-Encoding; s=20140610; t=1690526518; v=1; b=g+syvsc7YBiwNI39SLKc3NSHYkmb0Dt1oNaGKtpn5HL4zlfPXEJu2iyVB2ws6gfyIaNRKj2y NuECJbghovc0gX6fik602QKYrE/O2ZMbh8ZpdzK9jpLomXfQyc4l+3vs7AGqNQ9Zr7dH9mMWXcn 5Q+dvv4Z5fIEN8CqNSS3mbgE= X-Received: by 127.0.0.2 with SMTP id VA1pYY7687511xkXF0cuL3ki; Thu, 27 Jul 2023 23:41:58 -0700 X-Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.100]) by mx.groups.io with SMTP id smtpd.web10.27098.1690526516535632107 for ; Thu, 27 Jul 2023 23:41:56 -0700 X-IronPort-AV: E=McAfee;i="6600,9927,10784"; a="434804356" X-IronPort-AV: E=Sophos;i="6.01,236,1684825200"; d="scan'208";a="434804356" X-Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Jul 2023 23:41:17 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10784"; a="762496153" X-IronPort-AV: E=Sophos;i="6.01,236,1684825200"; d="scan'208";a="762496153" X-Received: from liyi4-desktop.ccr.corp.intel.com ([10.239.153.10]) by orsmga001-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Jul 2023 23:41:16 -0700 From: "Li, Yi" To: devel@edk2.groups.io Cc: Yi Li , Jiewen Yao , Xiaoyu Lu , Guomin Jiang Subject: [edk2-devel] [PATCH 17/29] CryptoPkg: Add instrinsics to support building openssl3 on IA32 windows Date: Fri, 28 Jul 2023 14:40:03 +0800 Message-Id: <8e22689f3db534155c00d9906c450a61fa3eecef.1690444292.git.yi1.li@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,yi1.li@intel.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: YtHfsNZNLmJIFcICXQEx1HMFx7686176AA= Content-Transfer-Encoding: 8bit X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20140610 header.b=g+syvsc7; dmarc=fail reason="SPF not aligned (relaxed), DKIM not aligned (relaxed)" header.from=intel.com (policy=none); spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io This dependency is needed to build openssl lib with openssl3 under IA32 Windows, so added implementation for _alldiv, _aulldiv, _aullrem and _alldvrm instrinsics. Signed-off-by: Yi Li Cc: Jiewen Yao Cc: Xiaoyu Lu Cc: Guomin Jiang --- .../Library/IntrinsicLib/Ia32/MathLldiv.asm | 203 ++++++++++++++++++ .../Library/IntrinsicLib/Ia32/MathUlldiv.asm | 157 ++++++++++++++ .../Library/IntrinsicLib/Ia32/MathUlldvrm.asm | 184 ++++++++++++++++ .../Library/IntrinsicLib/Ia32/MathUllrem.asm | 163 ++++++++++++++ .../Library/IntrinsicLib/IntrinsicLib.inf | 4 + 5 files changed, 711 insertions(+) create mode 100644 CryptoPkg/Library/IntrinsicLib/Ia32/MathLldiv.asm create mode 100644 CryptoPkg/Library/IntrinsicLib/Ia32/MathUlldiv.asm create mode 100644 CryptoPkg/Library/IntrinsicLib/Ia32/MathUlldvrm.asm create mode 100644 CryptoPkg/Library/IntrinsicLib/Ia32/MathUllrem.asm diff --git a/CryptoPkg/Library/IntrinsicLib/Ia32/MathLldiv.asm b/CryptoPkg/Library/IntrinsicLib/Ia32/MathLldiv.asm new file mode 100644 index 0000000000..2fccfd6dc0 --- /dev/null +++ b/CryptoPkg/Library/IntrinsicLib/Ia32/MathLldiv.asm @@ -0,0 +1,203 @@ +;*** +;lldiv.asm - signed long divide routine +; +; Copyright (c) Microsoft Corporation. All rights reserved. +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;Purpose: +; defines the signed long divide routine +; __alldiv +; +;Original Implemenation: MSVC 14.29.30133 +; +;******************************************************************************* + .686 + .model flat,C + .code + + + +;*** +;lldiv - signed long divide +; +;Purpose: +; Does a signed long divide of the arguments. Arguments are +; not changed. +; +;Entry: +; Arguments are passed on the stack: +; 1st pushed: divisor (QWORD) +; 2nd pushed: dividend (QWORD) +; +;Exit: +; EDX:EAX contains the quotient (dividend/divisor) +; NOTE: this routine removes the parameters from the stack. +; +;Uses: +; ECX +; +;Exceptions: +; +;******************************************************************************* +_alldiv PROC NEAR + +HIWORD EQU [4] ; +LOWORD EQU [0] + + push edi + push esi + push ebx + +; Set up the local stack and save the index registers. When this is done +; the stack frame will look as follows (assuming that the expression a/b will +; generate a call to lldiv(a, b)): +; +; ----------------- +; | | +; |---------------| +; | | +; |--divisor (b)--| +; | | +; |---------------| +; | | +; |--dividend (a)-| +; | | +; |---------------| +; | return addr** | +; |---------------| +; | EDI | +; |---------------| +; | ESI | +; |---------------| +; ESP---->| EBX | +; ----------------- +; + +DVND equ [esp + 16] ; stack address of dividend (a) +DVSR equ [esp + 24] ; stack address of divisor (b) + + +; Determine sign of the result (edi = 0 if result is positive, non-zero +; otherwise) and make operands positive. + + xor edi,edi ; result sign assumed positive + + mov eax,HIWORD(DVND) ; hi word of a + or eax,eax ; test to see if signed + jge short L1 ; skip rest if a is already positive + inc edi ; complement result sign flag + mov edx,LOWORD(DVND) ; lo word of a + neg eax ; make a positive + neg edx + sbb eax,0 + mov HIWORD(DVND),eax ; save positive value + mov LOWORD(DVND),edx +L1: + mov eax,HIWORD(DVSR) ; hi word of b + or eax,eax ; test to see if signed + jge short L2 ; skip rest if b is already positive + inc edi ; complement the result sign flag + mov edx,LOWORD(DVSR) ; lo word of a + neg eax ; make b positive + neg edx + sbb eax,0 + mov HIWORD(DVSR),eax ; save positive value + mov LOWORD(DVSR),edx +L2: + +; +; Now do the divide. First look to see if the divisor is less than 4194304K. +; If so, then we can use a simple algorithm with word divides, otherwise +; things get a little more complex. +; +; NOTE - eax currently contains the high order word of DVSR +; + + or eax,eax ; check to see if divisor < 4194304K + jnz short L3 ; nope, gotta do this the hard way + mov ecx,LOWORD(DVSR) ; load divisor + mov eax,HIWORD(DVND) ; load high word of dividend + xor edx,edx + div ecx ; eax <- high order bits of quotient + mov ebx,eax ; save high bits of quotient + mov eax,LOWORD(DVND) ; edx:eax <- remainder:lo word of dividend + div ecx ; eax <- low order bits of quotient + mov edx,ebx ; edx:eax <- quotient + jmp short L4 ; set sign, restore stack and return + +; +; Here we do it the hard way. Remember, eax contains the high word of DVSR +; + +L3: + mov ebx,eax ; ebx:ecx <- divisor + mov ecx,LOWORD(DVSR) + mov edx,HIWORD(DVND) ; edx:eax <- dividend + mov eax,LOWORD(DVND) +L5: + shr ebx,1 ; shift divisor right one bit + rcr ecx,1 + shr edx,1 ; shift dividend right one bit + rcr eax,1 + or ebx,ebx + jnz short L5 ; loop until divisor < 4194304K + div ecx ; now divide, ignore remainder + mov esi,eax ; save quotient + +; +; We may be off by one, so to check, we will multiply the quotient +; by the divisor and check the result against the orignal dividend +; Note that we must also check for overflow, which can occur if the +; dividend is close to 2**64 and the quotient is off by 1. +; + + mul dword ptr HIWORD(DVSR) ; QUOT * HIWORD(DVSR) + mov ecx,eax + mov eax,LOWORD(DVSR) + mul esi ; QUOT * LOWORD(DVSR) + add edx,ecx ; EDX:EAX = QUOT * DVSR + jc short L6 ; carry means Quotient is off by 1 + +; +; do long compare here between original dividend and the result of the +; multiply in edx:eax. If original is larger or equal, we are ok, otherwise +; subtract one (1) from the quotient. +; + + cmp edx,HIWORD(DVND) ; compare hi words of result and original + ja short L6 ; if result > original, do subtract + jb short L7 ; if result < original, we are ok + cmp eax,LOWORD(DVND) ; hi words are equal, compare lo words + jbe short L7 ; if less or equal we are ok, else subtract +L6: + dec esi ; subtract 1 from quotient +L7: + xor edx,edx ; edx:eax <- quotient + mov eax,esi + +; +; Just the cleanup left to do. edx:eax contains the quotient. Set the sign +; according to the save value, cleanup the stack, and return. +; + +L4: + dec edi ; check to see if result is negative + jnz short L8 ; if EDI == 0, result should be negative + neg edx ; otherwise, negate the result + neg eax + sbb edx,0 + +; +; Restore the saved registers and return. +; + +L8: + pop ebx + pop esi + pop edi + + ret 16 + +_alldiv ENDP + +end diff --git a/CryptoPkg/Library/IntrinsicLib/Ia32/MathUlldiv.asm b/CryptoPkg/Library/IntrinsicLib/Ia32/MathUlldiv.asm new file mode 100644 index 0000000000..c9f07e3666 --- /dev/null +++ b/CryptoPkg/Library/IntrinsicLib/Ia32/MathUlldiv.asm @@ -0,0 +1,157 @@ +;*** +;ulldiv.asm - unsigned long divide routine +; +; Copyright (c) Microsoft Corporation. All rights reserved. +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;Purpose: +; defines the unsigned long divide routine +; __aulldiv +; +;Original Implemenation: MSVC 14.29.30133 +; +;******************************************************************************* + .686 + .model flat,C + .code + +;*** +;ulldiv - unsigned long divide +; +;Purpose: +; Does a unsigned long divide of the arguments. Arguments are +; not changed. +; +;Entry: +; Arguments are passed on the stack: +; 1st pushed: divisor (QWORD) +; 2nd pushed: dividend (QWORD) +; +;Exit: +; EDX:EAX contains the quotient (dividend/divisor) +; NOTE: this routine removes the parameters from the stack. +; +;Uses: +; ECX +; +;Exceptions: +; +;******************************************************************************* +_aulldiv PROC NEAR + +HIWORD EQU [4] ; +LOWORD EQU [0] + + push ebx + push esi + +; Set up the local stack and save the index registers. When this is done +; the stack frame will look as follows (assuming that the expression a/b will +; generate a call to uldiv(a, b)): +; +; ----------------- +; | | +; |---------------| +; | | +; |--divisor (b)--| +; | | +; |---------------| +; | | +; |--dividend (a)-| +; | | +; |---------------| +; | return addr** | +; |---------------| +; | EBX | +; |---------------| +; ESP---->| ESI | +; ----------------- +; + +DVND equ [esp + 12] ; stack address of dividend (a) +DVSR equ [esp + 20] ; stack address of divisor (b) + +; +; Now do the divide. First look to see if the divisor is less than 4194304K. +; If so, then we can use a simple algorithm with word divides, otherwise +; things get a little more complex. +; + + mov eax,HIWORD(DVSR) ; check to see if divisor < 4194304K + or eax,eax + jnz short L1 ; nope, gotta do this the hard way + mov ecx,LOWORD(DVSR) ; load divisor + mov eax,HIWORD(DVND) ; load high word of dividend + xor edx,edx + div ecx ; get high order bits of quotient + mov ebx,eax ; save high bits of quotient + mov eax,LOWORD(DVND) ; edx:eax <- remainder:lo word of dividend + div ecx ; get low order bits of quotient + mov edx,ebx ; edx:eax <- quotient hi:quotient lo + jmp short L2 ; restore stack and return + +; +; Here we do it the hard way. Remember, eax contains DVSRHI +; + +L1: + mov ecx,eax ; ecx:ebx <- divisor + mov ebx,LOWORD(DVSR) + mov edx,HIWORD(DVND) ; edx:eax <- dividend + mov eax,LOWORD(DVND) +L3: + shr ecx,1 ; shift divisor right one bit; hi bit <- 0 + rcr ebx,1 + shr edx,1 ; shift dividend right one bit; hi bit <- 0 + rcr eax,1 + or ecx,ecx + jnz short L3 ; loop until divisor < 4194304K + div ebx ; now divide, ignore remainder + mov esi,eax ; save quotient + +; +; We may be off by one, so to check, we will multiply the quotient +; by the divisor and check the result against the original dividend +; Note that we must also check for overflow, which can occur if the +; dividend is close to 2**64 and the quotient is off by 1. +; + + mul dword ptr HIWORD(DVSR) ; QUOT * HIWORD(DVSR) + mov ecx,eax + mov eax,LOWORD(DVSR) + mul esi ; QUOT * LOWORD(DVSR) + add edx,ecx ; EDX:EAX = QUOT * DVSR + jc short L4 ; carry means Quotient is off by 1 + +; +; do long compare here between original dividend and the result of the +; multiply in edx:eax. If original is larger or equal, we are ok, otherwise +; subtract one (1) from the quotient. +; + + cmp edx,HIWORD(DVND) ; compare hi words of result and original + ja short L4 ; if result > original, do subtract + jb short L5 ; if result < original, we are ok + cmp eax,LOWORD(DVND) ; hi words are equal, compare lo words + jbe short L5 ; if less or equal we are ok, else subtract +L4: + dec esi ; subtract 1 from quotient +L5: + xor edx,edx ; edx:eax <- quotient + mov eax,esi + +; +; Just the cleanup left to do. edx:eax contains the quotient. +; Restore the saved registers and return. +; + +L2: + + pop esi + pop ebx + + ret 16 + +_aulldiv ENDP + + end diff --git a/CryptoPkg/Library/IntrinsicLib/Ia32/MathUlldvrm.asm b/CryptoPkg/Library/IntrinsicLib/Ia32/MathUlldvrm.asm new file mode 100644 index 0000000000..fc3a479e8a --- /dev/null +++ b/CryptoPkg/Library/IntrinsicLib/Ia32/MathUlldvrm.asm @@ -0,0 +1,184 @@ +;*** +;ulldvrm.asm - unsigned long divide and remainder routine +; +; Copyright (c) Microsoft Corporation. All rights reserved. +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;Purpose: +; defines the unsigned long divide and remainder routine +; __aulldvrm +; +;Original Implemenation: MSVC 14.29.30133 +; +;******************************************************************************* + .686 + .model flat,C + .code + + +;*** +;ulldvrm - unsigned long divide and remainder +; +;Purpose: +; Does a unsigned long divide and remainder of the arguments. Arguments +; are not changed. +; +;Entry: +; Arguments are passed on the stack: +; 1st pushed: divisor (QWORD) +; 2nd pushed: dividend (QWORD) +; +;Exit: +; EDX:EAX contains the quotient (dividend/divisor) +; EBX:ECX contains the remainder (divided % divisor) +; NOTE: this routine removes the parameters from the stack. +; +;Uses: +; ECX +; +;Exceptions: +; +;******************************************************************************* +_aulldvrm PROC NEAR + +HIWORD EQU [4] ; +LOWORD EQU [0] + push esi + +; Set up the local stack and save the index registers. When this is done +; the stack frame will look as follows (assuming that the expression a/b will +; generate a call to aulldvrm(a, b)): +; +; ----------------- +; | | +; |---------------| +; | | +; |--divisor (b)--| +; | | +; |---------------| +; | | +; |--dividend (a)-| +; | | +; |---------------| +; | return addr** | +; |---------------| +; ESP---->| ESI | +; ----------------- +; + +DVND equ [esp + 8] ; stack address of dividend (a) +DVSR equ [esp + 16] ; stack address of divisor (b) + +; +; Now do the divide. First look to see if the divisor is less than 4194304K. +; If so, then we can use a simple algorithm with word divides, otherwise +; things get a little more complex. +; + + mov eax,HIWORD(DVSR) ; check to see if divisor < 4194304K + or eax,eax + jnz short L1 ; nope, gotta do this the hard way + mov ecx,LOWORD(DVSR) ; load divisor + mov eax,HIWORD(DVND) ; load high word of dividend + xor edx,edx + div ecx ; get high order bits of quotient + mov ebx,eax ; save high bits of quotient + mov eax,LOWORD(DVND) ; edx:eax <- remainder:lo word of dividend + div ecx ; get low order bits of quotient + mov esi,eax ; ebx:esi <- quotient + +; +; Now we need to do a multiply so that we can compute the remainder. +; + mov eax,ebx ; set up high word of quotient + mul dword ptr LOWORD(DVSR) ; HIWORD(QUOT) * DVSR + mov ecx,eax ; save the result in ecx + mov eax,esi ; set up low word of quotient + mul dword ptr LOWORD(DVSR) ; LOWORD(QUOT) * DVSR + add edx,ecx ; EDX:EAX = QUOT * DVSR + jmp short L2 ; complete remainder calculation + +; +; Here we do it the hard way. Remember, eax contains DVSRHI +; + +L1: + mov ecx,eax ; ecx:ebx <- divisor + mov ebx,LOWORD(DVSR) + mov edx,HIWORD(DVND) ; edx:eax <- dividend + mov eax,LOWORD(DVND) +L3: + shr ecx,1 ; shift divisor right one bit; hi bit <- 0 + rcr ebx,1 + shr edx,1 ; shift dividend right one bit; hi bit <- 0 + rcr eax,1 + or ecx,ecx + jnz short L3 ; loop until divisor < 4194304K + div ebx ; now divide, ignore remainder + mov esi,eax ; save quotient + +; +; We may be off by one, so to check, we will multiply the quotient +; by the divisor and check the result against the original dividend +; Note that we must also check for overflow, which can occur if the +; dividend is close to 2**64 and the quotient is off by 1. +; + + mul dword ptr HIWORD(DVSR) ; QUOT * HIWORD(DVSR) + mov ecx,eax + mov eax,LOWORD(DVSR) + mul esi ; QUOT * LOWORD(DVSR) + add edx,ecx ; EDX:EAX = QUOT * DVSR + jc short L4 ; carry means Quotient is off by 1 + +; +; do long compare here between original dividend and the result of the +; multiply in edx:eax. If original is larger or equal, we are ok, otherwise +; subtract one (1) from the quotient. +; + + cmp edx,HIWORD(DVND) ; compare hi words of result and original + ja short L4 ; if result > original, do subtract + jb short L5 ; if result < original, we are ok + cmp eax,LOWORD(DVND) ; hi words are equal, compare lo words + jbe short L5 ; if less or equal we are ok, else subtract +L4: + dec esi ; subtract 1 from quotient + sub eax,LOWORD(DVSR) ; subtract divisor from result + sbb edx,HIWORD(DVSR) +L5: + xor ebx,ebx ; ebx:esi <- quotient + +L2: +; +; Calculate remainder by subtracting the result from the original dividend. +; Since the result is already in a register, we will do the subtract in the +; opposite direction and negate the result. +; + + sub eax,LOWORD(DVND) ; subtract dividend from result + sbb edx,HIWORD(DVND) + neg edx ; otherwise, negate the result + neg eax + sbb edx,0 + +; +; Now we need to get the quotient into edx:eax and the remainder into ebx:ecx. +; + mov ecx,edx + mov edx,ebx + mov ebx,ecx + mov ecx,eax + mov eax,esi +; +; Just the cleanup left to do. edx:eax contains the quotient. +; Restore the saved registers and return. +; + + pop esi + + ret 16 + +_aulldvrm ENDP + + end diff --git a/CryptoPkg/Library/IntrinsicLib/Ia32/MathUllrem.asm b/CryptoPkg/Library/IntrinsicLib/Ia32/MathUllrem.asm new file mode 100644 index 0000000000..755fef24d0 --- /dev/null +++ b/CryptoPkg/Library/IntrinsicLib/Ia32/MathUllrem.asm @@ -0,0 +1,163 @@ +;*** +;ullrem.asm - unsigned long remainder routine +; +; Copyright (c) Microsoft Corporation. All rights reserved. +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;Purpose: +; defines the unsigned long remainder routine +; __aullrem +; +;Original Implemenation: MSVC 14.29.30133 +; +;******************************************************************************* + .686 + .model flat,C + .code + + +;*** +;ullrem - unsigned long remainder +; +;Purpose: +; Does a unsigned long remainder of the arguments. Arguments are +; not changed. +; +;Entry: +; Arguments are passed on the stack: +; 1st pushed: divisor (QWORD) +; 2nd pushed: dividend (QWORD) +; +;Exit: +; EDX:EAX contains the remainder (dividend%divisor) +; NOTE: this routine removes the parameters from the stack. +; +;Uses: +; ECX +; +;Exceptions: +; +;******************************************************************************* +_aullrem PROC NEAR + +HIWORD EQU [4] ; +LOWORD EQU [0] + + push ebx + +; Set up the local stack and save the index registers. When this is done +; the stack frame will look as follows (assuming that the expression a%b will +; generate a call to ullrem(a, b)): +; +; ----------------- +; | | +; |---------------| +; | | +; |--divisor (b)--| +; | | +; |---------------| +; | | +; |--dividend (a)-| +; | | +; |---------------| +; | return addr** | +; |---------------| +; ESP---->| EBX | +; ----------------- +; + +DVND equ [esp + 8] ; stack address of dividend (a) +DVSR equ [esp + 16] ; stack address of divisor (b) + +; Now do the divide. First look to see if the divisor is less than 4194304K. +; If so, then we can use a simple algorithm with word divides, otherwise +; things get a little more complex. +; + + mov eax,HIWORD(DVSR) ; check to see if divisor < 4194304K + or eax,eax + jnz short L1 ; nope, gotta do this the hard way + mov ecx,LOWORD(DVSR) ; load divisor + mov eax,HIWORD(DVND) ; load high word of dividend + xor edx,edx + div ecx ; edx <- remainder, eax <- quotient + mov eax,LOWORD(DVND) ; edx:eax <- remainder:lo word of dividend + div ecx ; edx <- final remainder + mov eax,edx ; edx:eax <- remainder + xor edx,edx + jmp short L2 ; restore stack and return + +; +; Here we do it the hard way. Remember, eax contains DVSRHI +; + +L1: + mov ecx,eax ; ecx:ebx <- divisor + mov ebx,LOWORD(DVSR) + mov edx,HIWORD(DVND) ; edx:eax <- dividend + mov eax,LOWORD(DVND) +L3: + shr ecx,1 ; shift divisor right one bit; hi bit <- 0 + rcr ebx,1 + shr edx,1 ; shift dividend right one bit; hi bit <- 0 + rcr eax,1 + or ecx,ecx + jnz short L3 ; loop until divisor < 4194304K + div ebx ; now divide, ignore remainder + +; +; We may be off by one, so to check, we will multiply the quotient +; by the divisor and check the result against the orignal dividend +; Note that we must also check for overflow, which can occur if the +; dividend is close to 2**64 and the quotient is off by 1. +; + + mov ecx,eax ; save a copy of quotient in ECX + mul dword ptr HIWORD(DVSR) + xchg ecx,eax ; put partial product in ECX, get quotient in EAX + mul dword ptr LOWORD(DVSR) + add edx,ecx ; EDX:EAX = QUOT * DVSR + jc short L4 ; carry means Quotient is off by 1 + +; +; do long compare here between original dividend and the result of the +; multiply in edx:eax. If original is larger or equal, we're ok, otherwise +; subtract the original divisor from the result. +; + + cmp edx,HIWORD(DVND) ; compare hi words of result and original + ja short L4 ; if result > original, do subtract + jb short L5 ; if result < original, we're ok + cmp eax,LOWORD(DVND) ; hi words are equal, compare lo words + jbe short L5 ; if less or equal we're ok, else subtract +L4: + sub eax,LOWORD(DVSR) ; subtract divisor from result + sbb edx,HIWORD(DVSR) +L5: + +; +; Calculate remainder by subtracting the result from the original dividend. +; Since the result is already in a register, we will perform the subtract in +; the opposite direction and negate the result to make it positive. +; + + sub eax,LOWORD(DVND) ; subtract original dividend from result + sbb edx,HIWORD(DVND) + neg edx ; and negate it + neg eax + sbb edx,0 + +; +; Just the cleanup left to do. dx:ax contains the remainder. +; Restore the saved registers and return. +; + +L2: + + pop ebx + + ret 16 + +_aullrem ENDP + + end diff --git a/CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf b/CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf index 86e74b57b1..2ec987b260 100644 --- a/CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf +++ b/CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf @@ -32,6 +32,10 @@ Ia32/MathFtol.c | MSFT Ia32/MathLlmul.asm | MSFT Ia32/MathLlshr.asm | MSFT + Ia32/MathUlldiv.asm | MSFT + Ia32/MathUlldvrm.asm | MSFT + Ia32/MathLldiv.asm | MSFT + Ia32/MathUllrem.asm | MSFT Ia32/MathLShiftS64.c | INTEL Ia32/MathRShiftU64.c | INTEL -- 2.31.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#107356): https://edk2.groups.io/g/devel/message/107356 Mute This Topic: https://groups.io/mt/100406063/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-