Initial import.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
622
EdkModulePkg/Universal/Ebc/Dxe/Ia32/Ia32Math.asm
Normal file
622
EdkModulePkg/Universal/Ebc/Dxe/Ia32/Ia32Math.asm
Normal file
@@ -0,0 +1,622 @@
|
||||
TITLE Ia32math.asm: Generic math routines for EBC interpreter running on IA32 processor
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
;
|
||||
; Copyright (c) 2006, Intel Corporation
|
||||
; All rights reserved. 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:
|
||||
;
|
||||
; Ia32math.asm
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; Generic math routines for EBC interpreter running on IA32 processor
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
.686P
|
||||
.XMM
|
||||
.MODEL SMALL
|
||||
.CODE
|
||||
|
||||
LeftShiftU64 PROTO C Operand: QWORD, CountIn: QWORD
|
||||
RightShiftU64 PROTO C Operand: QWORD, CountIn: QWORD
|
||||
ARightShift64 PROTO C Operand: QWORD, CountIn: QWORD
|
||||
MulU64x64 PROTO C Value1: QWORD, Value2: QWORD, ResultHigh: DWORD
|
||||
MulS64x64 PROTO C Value1: QWORD, Value2: QWORD, ResultHigh: DWORD
|
||||
DivU64x64 PROTO C Dividend: QWORD, Divisor: QWORD, Remainder: DWORD, Error: DWORD
|
||||
DivS64x64 PROTO C Dividend: QWORD, Divisor: QWORD, Remainder: DWORD, Error: DWORD
|
||||
|
||||
|
||||
LeftShiftU64 PROC C Operand: QWORD, CountIn: QWORD
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; UINT64
|
||||
; LeftShiftU64 (
|
||||
; IN UINT64 Operand,
|
||||
; IN UINT64 CountIn
|
||||
; )
|
||||
;
|
||||
; Routine Description:
|
||||
;
|
||||
; Left-shift a 64-bit value.
|
||||
;
|
||||
; Arguments:
|
||||
;
|
||||
; Operand - the value to shift
|
||||
; Count - shift count
|
||||
;
|
||||
; Returns:
|
||||
;
|
||||
; Operand << Count
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
push ecx
|
||||
;
|
||||
; if (CountIn > 63) return 0;
|
||||
;
|
||||
cmp dword ptr CountIn[4], 0
|
||||
jne _LeftShiftU64_Overflow
|
||||
mov ecx, dword ptr CountIn[0]
|
||||
cmp ecx, 63
|
||||
jbe _LeftShiftU64_Calc
|
||||
|
||||
_LeftShiftU64_Overflow:
|
||||
xor eax, eax
|
||||
xor edx, edx
|
||||
jmp _LeftShiftU64_Done
|
||||
|
||||
_LeftShiftU64_Calc:
|
||||
mov eax, dword ptr Operand[0]
|
||||
mov edx, dword ptr Operand[4]
|
||||
|
||||
shld edx, eax, cl
|
||||
shl eax, cl
|
||||
cmp ecx, 32
|
||||
jc short _LeftShiftU64_Done
|
||||
|
||||
mov edx, eax
|
||||
xor eax, eax
|
||||
|
||||
_LeftShiftU64_Done:
|
||||
pop ecx
|
||||
ret
|
||||
|
||||
LeftShiftU64 ENDP
|
||||
|
||||
|
||||
RightShiftU64 PROC C Operand: QWORD, CountIn: QWORD
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; UINT64
|
||||
; RightShiftU64 (
|
||||
; IN UINT64 Operand,
|
||||
; IN UINT64 CountIn
|
||||
; )
|
||||
;
|
||||
; Routine Description:
|
||||
;
|
||||
; Right-shift an unsigned 64-bit value.
|
||||
;
|
||||
; Arguments:
|
||||
;
|
||||
; Operand - the value to shift
|
||||
; Count - shift count
|
||||
;
|
||||
; Returns:
|
||||
;
|
||||
; Operand >> Count
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
push ecx
|
||||
;
|
||||
; if (CountIn > 63) return 0;
|
||||
;
|
||||
cmp dword ptr CountIn[4], 0
|
||||
jne _RightShiftU64_Overflow
|
||||
mov ecx, dword ptr CountIn[0]
|
||||
cmp ecx, 63
|
||||
jbe _RightShiftU64_Calc
|
||||
|
||||
_RightShiftU64_Overflow:
|
||||
xor eax, eax
|
||||
xor edx, edx
|
||||
jmp _RightShiftU64_Done
|
||||
|
||||
_RightShiftU64_Calc:
|
||||
mov eax, dword ptr Operand[0]
|
||||
mov edx, dword ptr Operand[4]
|
||||
|
||||
shrd edx, eax, cl
|
||||
shr eax, cl
|
||||
cmp ecx, 32
|
||||
jc short _RightShiftU64_Done
|
||||
|
||||
mov eax, edx
|
||||
xor edx, edx
|
||||
|
||||
_RightShiftU64_Done:
|
||||
pop ecx
|
||||
ret
|
||||
|
||||
RightShiftU64 ENDP
|
||||
|
||||
|
||||
ARightShift64 PROC C Operand: QWORD, CountIn: QWORD
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; INT64
|
||||
; ARightShift64 (
|
||||
; IN INT64 Operand,
|
||||
; IN UINT64 CountIn
|
||||
; )
|
||||
;
|
||||
; Routine Description:
|
||||
;
|
||||
; Arithmatic shift a 64 bit signed value.
|
||||
;
|
||||
; Arguments:
|
||||
;
|
||||
; Operand - the value to shift
|
||||
; Count - shift count
|
||||
;
|
||||
; Returns:
|
||||
;
|
||||
; Operand >> Count
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
push ecx
|
||||
;
|
||||
; If they exceeded the max shift count, then return either 0 or all F's
|
||||
; depending on the sign bit.
|
||||
;
|
||||
cmp dword ptr CountIn[4], 0
|
||||
jne _ARightShiftU64_Overflow
|
||||
mov ecx, dword ptr CountIn[0]
|
||||
cmp ecx, 63
|
||||
jbe _ARightShiftU64_Calc
|
||||
|
||||
_ARightShiftU64_Overflow:
|
||||
;
|
||||
; Check the sign bit of Operand
|
||||
;
|
||||
bt dword ptr Operand[4], 31
|
||||
jnc _ARightShiftU64_Return_Zero
|
||||
;
|
||||
; return -1
|
||||
;
|
||||
or eax, 0FFFFFFFFh
|
||||
or edx, 0FFFFFFFFh
|
||||
jmp _ARightShiftU64_Done
|
||||
|
||||
_ARightShiftU64_Return_Zero:
|
||||
xor eax, eax
|
||||
xor edx, edx
|
||||
jmp _ARightShiftU64_Done
|
||||
|
||||
_ARightShiftU64_Calc:
|
||||
mov eax, dword ptr Operand[0]
|
||||
mov edx, dword ptr Operand[4]
|
||||
|
||||
shrd eax, edx, cl
|
||||
sar edx, cl
|
||||
cmp ecx, 32
|
||||
jc short _ARightShiftU64_Done
|
||||
|
||||
;
|
||||
; if ecx >= 32, then eax = edx, and edx = sign bit
|
||||
;
|
||||
mov eax, edx
|
||||
sar edx, 31
|
||||
|
||||
_ARightShiftU64_Done:
|
||||
pop ecx
|
||||
ret
|
||||
|
||||
ARightShift64 ENDP
|
||||
|
||||
|
||||
MulU64x64 PROC C Value1: QWORD, Value2: QWORD, ResultHigh: DWORD
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; UINT64
|
||||
; MulU64x64 (
|
||||
; UINT64 Value1,
|
||||
; UINT64 Value2,
|
||||
; UINT64 *ResultHigh
|
||||
; )
|
||||
;
|
||||
; Routine Description:
|
||||
;
|
||||
; Multiply two unsigned 64-bit values.
|
||||
;
|
||||
; Arguments:
|
||||
;
|
||||
; Value1 - first value to multiply
|
||||
; Value2 - value to multiply by Value1
|
||||
; ResultHigh - result to flag overflows
|
||||
;
|
||||
; Returns:
|
||||
;
|
||||
; Value1 * Value2
|
||||
; The 128-bit result is the concatenation of *ResultHigh and the return value
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
push ebx
|
||||
push ecx
|
||||
mov ebx, ResultHigh ; ebx points to the high 4 words of result
|
||||
;
|
||||
; The result consists of four double-words.
|
||||
; Here we assume their names from low to high: dw0, dw1, dw2, dw3
|
||||
;
|
||||
mov eax, dword ptr Value1[0]
|
||||
mul dword ptr Value2[0]
|
||||
push eax ; eax contains final result of dw0, push it
|
||||
mov ecx, edx ; ecx contains partial result of dw1
|
||||
|
||||
mov eax, dword ptr Value1[4]
|
||||
mul dword ptr Value2[0]
|
||||
add ecx, eax ; add eax to partial result of dw1
|
||||
adc edx, 0
|
||||
mov dword ptr [ebx], edx ; lower double-word of ResultHigh contains partial result of dw2
|
||||
|
||||
mov eax, dword ptr Value1[0]
|
||||
mul dword ptr Value2[4]
|
||||
add ecx, eax ; add eax to partial result of dw1
|
||||
push ecx ; ecx contains final result of dw1, push it
|
||||
adc edx, 0
|
||||
mov ecx, edx ; ecx contains partial result of dw2, together with ResultHigh
|
||||
|
||||
mov eax, dword ptr Value1[4]
|
||||
mul dword ptr Value2[4]
|
||||
add ecx, eax ; add eax to partial result of dw2
|
||||
adc edx, 0
|
||||
add dword ptr [ebx], ecx ; lower double-word of ResultHigh contains final result of dw2
|
||||
adc edx, 0
|
||||
mov dword ptr [ebx + 4], edx ; high double-word of ResultHigh contains final result of dw3
|
||||
|
||||
pop edx ; edx contains the final result of dw1
|
||||
pop eax ; edx contains the final result of dw0
|
||||
pop ecx
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
MulU64x64 ENDP
|
||||
|
||||
|
||||
MulS64x64 PROC C Value1: QWORD, Value2: QWORD, ResultHigh: DWORD
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; INT64
|
||||
; MulS64x64 (
|
||||
; INT64 Value1,
|
||||
; INT64 Value2,
|
||||
; INT64 *ResultHigh
|
||||
; )
|
||||
;
|
||||
; Routine Description:
|
||||
;
|
||||
; Multiply two signed 64-bit values.
|
||||
;
|
||||
; Arguments:
|
||||
;
|
||||
; Value1 - first value to multiply
|
||||
; Value2 - value to multiply by Value1
|
||||
; ResultHigh - result to flag overflows
|
||||
;
|
||||
; Returns:
|
||||
;
|
||||
; Value1 * Value2
|
||||
; The 128-bit result is the concatenation of *ResultHigh and the return value
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
push ebx
|
||||
push ecx
|
||||
mov ebx, ResultHigh ; ebx points to the high 4 words of result
|
||||
xor ecx, ecx ; the lowest bit of ecx flags the sign
|
||||
|
||||
mov edx, dword ptr Value1[4]
|
||||
bt edx, 31
|
||||
jnc short _MulS64x64_A_Positive
|
||||
;
|
||||
; a is negative
|
||||
;
|
||||
mov eax, dword ptr Value1[0]
|
||||
not edx
|
||||
not eax
|
||||
add eax, 1
|
||||
adc edx, 0
|
||||
mov dword ptr Value1[0], eax
|
||||
mov dword ptr Value1[4], edx
|
||||
btc ecx, 0
|
||||
|
||||
_MulS64x64_A_Positive:
|
||||
mov edx, dword ptr Value2[4]
|
||||
bt edx, 31
|
||||
jnc short _MulS64x64_B_Positive
|
||||
;
|
||||
; b is negative
|
||||
;
|
||||
mov eax, dword ptr Value2[0]
|
||||
not edx
|
||||
not eax
|
||||
add eax, 1
|
||||
adc edx, 0
|
||||
mov dword ptr Value2[0], eax
|
||||
mov dword ptr Value2[4], edx
|
||||
btc ecx, 0
|
||||
|
||||
_MulS64x64_B_Positive:
|
||||
invoke MulU64x64, Value1, Value2, ResultHigh
|
||||
bt ecx, 0
|
||||
jnc short _MulS64x64_Done
|
||||
;
|
||||
;negate the result
|
||||
;
|
||||
not eax
|
||||
not edx
|
||||
not dword ptr [ebx]
|
||||
not dword ptr [ebx + 4]
|
||||
add eax, 1
|
||||
adc edx, 0
|
||||
adc dword ptr [ebx], 0
|
||||
adc dword ptr [ebx + 4], 0
|
||||
|
||||
_MulS64x64_Done:
|
||||
pop ecx
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
MulS64x64 ENDP
|
||||
|
||||
|
||||
DivU64x64 PROC C Dividend: QWORD, Divisor: QWORD, Remainder: DWORD, Error: DWORD,
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; UINT64
|
||||
; DivU64x64 (
|
||||
; IN UINT64 Dividend,
|
||||
; IN UINT64 Divisor,
|
||||
; OUT UINT64 *Remainder OPTIONAL,
|
||||
; OUT UINT32 *Error
|
||||
; )
|
||||
;
|
||||
; Routine Description:
|
||||
;
|
||||
; This routine allows a 64 bit value to be divided with a 64 bit value returns
|
||||
; 64bit result and the Remainder
|
||||
;
|
||||
; Arguments:
|
||||
;
|
||||
; Dividend - dividend
|
||||
; Divisor - divisor
|
||||
; ResultHigh - result to flag overflows
|
||||
; Error - flag for error
|
||||
;
|
||||
; Returns:
|
||||
;
|
||||
; Dividend / Divisor
|
||||
; Remainder = Dividend mod Divisor
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
push ecx
|
||||
|
||||
mov eax, Error
|
||||
mov dword ptr [eax], 0
|
||||
|
||||
cmp dword ptr Divisor[0], 0
|
||||
jne _DivU64x64_Valid
|
||||
cmp dword ptr Divisor[4], 0
|
||||
jne _DivU64x64_Valid
|
||||
;
|
||||
; the divisor is zero
|
||||
;
|
||||
mov dword ptr [eax], 1
|
||||
cmp Remainder, 0
|
||||
je _DivU64x64_Invalid_Return
|
||||
;
|
||||
; fill the remainder if the pointer is not null
|
||||
;
|
||||
mov eax, Remainder
|
||||
mov dword ptr [eax], 0
|
||||
mov dword ptr [eax + 4], 80000000h
|
||||
|
||||
_DivU64x64_Invalid_Return:
|
||||
xor eax, eax
|
||||
mov edx, 80000000h
|
||||
jmp _DivU64x64_Done
|
||||
|
||||
_DivU64x64_Valid:
|
||||
;
|
||||
; let edx and eax contain the intermediate result of remainder
|
||||
;
|
||||
xor edx, edx
|
||||
xor eax, eax
|
||||
mov ecx, 64
|
||||
|
||||
_DivU64x64_Wend:
|
||||
;
|
||||
; shift dividend left one
|
||||
;
|
||||
shl dword ptr Dividend[0], 1
|
||||
rcl dword ptr Dividend[4], 1
|
||||
;
|
||||
; rotate intermediate result of remainder left one
|
||||
;
|
||||
rcl eax, 1
|
||||
rcl edx, 1
|
||||
|
||||
cmp edx, dword ptr Divisor[4]
|
||||
ja _DivU64x64_Sub_Divisor
|
||||
jb _DivU64x64_Cont
|
||||
cmp eax, dword ptr Divisor[0]
|
||||
jb _DivU64x64_Cont
|
||||
|
||||
_DivU64x64_Sub_Divisor:
|
||||
;
|
||||
; If intermediate result of remainder is larger than
|
||||
; or equal to divisor, then set the lowest bit of dividend,
|
||||
; and subtract divisor from intermediate remainder
|
||||
;
|
||||
bts dword ptr Dividend[0], 0
|
||||
sub eax, dword ptr Divisor[0]
|
||||
sbb edx, dword ptr Divisor[4]
|
||||
|
||||
_DivU64x64_Cont:
|
||||
loop _DivU64x64_Wend
|
||||
|
||||
cmp Remainder, 0
|
||||
je _DivU64x64_Assign
|
||||
mov ecx, Remainder
|
||||
mov dword ptr [ecx], eax
|
||||
mov dword ptr [ecx + 4], edx
|
||||
|
||||
_DivU64x64_Assign:
|
||||
mov eax, dword ptr Dividend[0]
|
||||
mov edx, dword ptr Dividend[4]
|
||||
|
||||
_DivU64x64_Done:
|
||||
pop ecx
|
||||
ret
|
||||
|
||||
DivU64x64 ENDP
|
||||
|
||||
DivS64x64 PROC C Dividend: QWORD, Divisor: QWORD, Remainder: DWORD, Error: DWORD,
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; INT64
|
||||
; DivU64x64 (
|
||||
; IN INT64 Dividend,
|
||||
; IN INT64 Divisor,
|
||||
; OUT UINT64 *Remainder OPTIONAL,
|
||||
; OUT UINT32 *Error
|
||||
; )
|
||||
;
|
||||
; Routine Description:
|
||||
;
|
||||
; This routine allows a 64 bit signed value to be divided with a 64 bit
|
||||
; signed value returns 64bit result and the Remainder.
|
||||
;
|
||||
; Arguments:
|
||||
;
|
||||
; Dividend - dividend
|
||||
; Divisor - divisor
|
||||
; ResultHigh - result to flag overflows
|
||||
; Error - flag for error
|
||||
;
|
||||
; Returns:
|
||||
;
|
||||
; Dividend / Divisor
|
||||
; Remainder = Dividend mod Divisor
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
push ecx
|
||||
|
||||
mov eax, Error
|
||||
mov dword ptr [eax], 0
|
||||
|
||||
cmp dword ptr Divisor[0], 0
|
||||
jne _DivS64x64_Valid
|
||||
cmp dword ptr Divisor[4], 0
|
||||
jne _DivS64x64_Valid
|
||||
;
|
||||
; the divisor is zero
|
||||
;
|
||||
mov dword ptr [eax], 1
|
||||
cmp Remainder, 0
|
||||
je _DivS64x64_Invalid_Return
|
||||
;
|
||||
; fill the remainder if the pointer is not null
|
||||
;
|
||||
mov eax, Remainder
|
||||
mov dword ptr [eax], 0
|
||||
mov dword ptr [eax + 4], 80000000h
|
||||
|
||||
_DivS64x64_Invalid_Return:
|
||||
xor eax, eax
|
||||
mov edx, 80000000h
|
||||
jmp _DivS64x64_Done
|
||||
|
||||
_DivS64x64_Valid:
|
||||
;
|
||||
; The lowest bit of ecx flags the sign of quotient,
|
||||
; The seconde lowest bit flags the sign of remainder
|
||||
;
|
||||
xor ecx, ecx
|
||||
|
||||
mov edx, dword ptr Dividend[4]
|
||||
bt edx, 31
|
||||
jnc short _DivS64x64_Dividend_Positive
|
||||
;
|
||||
; dividend is negative
|
||||
;
|
||||
mov eax, dword ptr Dividend[0]
|
||||
not edx
|
||||
not eax
|
||||
add eax, 1
|
||||
adc edx, 0
|
||||
mov dword ptr Dividend[0], eax
|
||||
mov dword ptr Dividend[4], edx
|
||||
;
|
||||
; set both the flags for signs of quotient and remainder
|
||||
;
|
||||
btc ecx, 0
|
||||
btc ecx, 1
|
||||
|
||||
_DivS64x64_Dividend_Positive:
|
||||
mov edx, dword ptr Divisor[4]
|
||||
bt edx, 31
|
||||
jnc short _DivS64x64_Divisor_Positive
|
||||
;
|
||||
; divisor is negative
|
||||
;
|
||||
mov eax, dword ptr Divisor[0]
|
||||
not edx
|
||||
not eax
|
||||
add eax, 1
|
||||
adc edx, 0
|
||||
mov dword ptr Divisor[0], eax
|
||||
mov dword ptr Divisor[4], edx
|
||||
;
|
||||
; just complement the flag for sign of quotient
|
||||
;
|
||||
btc ecx, 0
|
||||
|
||||
_DivS64x64_Divisor_Positive:
|
||||
invoke DivU64x64, Dividend, Divisor, Remainder, Error
|
||||
bt ecx, 0
|
||||
jnc short _DivS64x64_Remainder
|
||||
;
|
||||
; negate the quotient
|
||||
;
|
||||
not eax
|
||||
not edx
|
||||
add eax, 1
|
||||
adc edx, 0
|
||||
|
||||
_DivS64x64_Remainder:
|
||||
bt ecx, 1
|
||||
jnc short _DivS64x64_Done
|
||||
;
|
||||
; negate the remainder
|
||||
;
|
||||
mov ecx, remainder
|
||||
not dword ptr [ecx]
|
||||
not dword ptr [ecx + 4]
|
||||
add dword ptr [ecx], 1
|
||||
adc dword ptr [ecx + 4], 0
|
||||
|
||||
_DivS64x64_Done:
|
||||
pop ecx
|
||||
ret
|
||||
|
||||
DivS64x64 ENDP
|
||||
|
||||
END
|
Reference in New Issue
Block a user