[edk2-devel] [PATCH V2 17/29] CryptoPkg: Add instrinsics to support building openssl3 on IA32 windows

Li, Yi yi1.li at intel.com
Thu Aug 3 04:37:35 UTC 2023


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 <yi1.li at intel.com>
Cc: Jiewen Yao <jiewen.yao at intel.com>
Cc: Xiaoyu Lu <xiaoyu1.lu at intel.com>
Cc: Guomin Jiang <guomin.jiang at intel.com>
---
 .../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 (#107498): https://edk2.groups.io/g/devel/message/107498
Mute This Topic: https://groups.io/mt/100520600/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list