blob: fdec1b58d8a7bfdc27424bbc621cdcd6dee31adf [file] [log] [blame]
;****************************************************************************
;*
;* SciTech OS Portability Manager Library
;*
;* ========================================================================
;*
;* The contents of this file are subject to the SciTech MGL Public
;* License Version 1.0 (the "License"); you may not use this file
;* except in compliance with the License. You may obtain a copy of
;* the License at http://www.scitechsoft.com/mgl-license.txt
;*
;* Software distributed under the License is distributed on an
;* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
;* implied. See the License for the specific language governing
;* rights and limitations under the License.
;*
;* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
;*
;* The Initial Developer of the Original Code is SciTech Software, Inc.
;* All Rights Reserved.
;*
;* ========================================================================
;*
;* Language: NASM or TASM Assembler
;* Environment: Intel 32 bit Protected Mode.
;*
;* Description: Code for 64-bit arhithmetic
;*
;****************************************************************************
IDEAL
include "scitech.mac"
header _int64
begcodeseg _int64 ; Start of code segment
a_low EQU 04h ; Access a_low directly on stack
a_high EQU 08h ; Access a_high directly on stack
b_low EQU 0Ch ; Access b_low directly on stack
shift EQU 0Ch ; Access shift directly on stack
result_2 EQU 0Ch ; Access result directly on stack
b_high EQU 10h ; Access b_high directly on stack
result_3 EQU 10h ; Access result directly on stack
result_4 EQU 14h ; Access result directly on stack
;----------------------------------------------------------------------------
; void _PM_add64(u32 a_low,u32 a_high,u32 b_low,u32 b_high,__u64 *result);
;----------------------------------------------------------------------------
; Adds two 64-bit numbers.
;----------------------------------------------------------------------------
cprocstart _PM_add64
mov eax,[esp+a_low]
add eax,[esp+b_low]
mov edx,[esp+a_high]
adc edx,[esp+b_high]
mov ecx,[esp+result_4]
mov [ecx],eax
mov [ecx+4],edx
ret
cprocend
;----------------------------------------------------------------------------
; void _PM_sub64(u32 a_low,u32 a_high,u32 b_low,u32 b_high,__u64 *result);
;----------------------------------------------------------------------------
; Subtracts two 64-bit numbers.
;----------------------------------------------------------------------------
cprocstart _PM_sub64
mov eax,[esp+a_low]
sub eax,[esp+b_low]
mov edx,[esp+a_high]
sbb edx,[esp+b_high]
mov ecx,[esp+result_4]
mov [ecx],eax
mov [ecx+4],edx
ret
cprocend
;----------------------------------------------------------------------------
; void _PM_mul64(u32 a_high,u32 a_low,u32 b_high,u32 b_low,__u64 *result);
;----------------------------------------------------------------------------
; Multiples two 64-bit numbers.
;----------------------------------------------------------------------------
cprocstart _PM_mul64
mov eax,[esp+a_high]
mov ecx,[esp+b_high]
or ecx,eax
mov ecx,[esp+b_low]
jnz @@FullMultiply
mov eax,[esp+a_low] ; EDX:EAX = b.low * a.low
mul ecx
mov ecx,[esp+result_4]
mov [ecx],eax
mov [ecx+4],edx
ret
@@FullMultiply:
push ebx
mul ecx ; EDX:EAX = a.high * b.low
mov ebx,eax
mov eax,[esp+a_low+4]
mul [DWORD esp+b_high+4] ; EDX:EAX = b.high * a.low
add ebx,eax
mov eax,[esp+a_low+4]
mul ecx ; EDX:EAX = a.low * b.low
add edx,ebx
pop ebx
mov ecx,[esp+result_4]
mov [ecx],eax
mov [ecx+4],edx
ret
cprocend
;----------------------------------------------------------------------------
; void _PM_div64(u32 a_low,u32 a_high,u32 b_low,u32 b_high,__u64 *result);
;----------------------------------------------------------------------------
; Divides two 64-bit numbers.
;----------------------------------------------------------------------------
cprocstart _PM_div64
push edi
push esi
push ebx
xor edi,edi
mov eax,[esp+a_high+0Ch]
or eax,eax
jns @@ANotNeg
; Dividend is negative, so negate it and save result for later
inc edi
mov edx,[esp+a_low+0Ch]
neg eax
neg edx
sbb eax,0
mov [esp+a_high+0Ch],eax
mov [esp+a_low+0Ch],edx
@@ANotNeg:
mov eax,[esp+b_high+0Ch]
or eax,eax
jns @@BNotNeg
; Divisor is negative, so negate it and save result for later
inc edi
mov edx,[esp+b_low+0Ch]
neg eax
neg edx
sbb eax,0
mov [esp+b_high+0Ch],eax
mov [esp+b_low+0Ch],edx
@@BNotNeg:
or eax,eax
jnz @@BHighNotZero
; b.high is zero, so handle this faster
mov ecx,[esp+b_low+0Ch]
mov eax,[esp+a_high+0Ch]
xor edx,edx
div ecx
mov ebx,eax
mov eax,[esp+a_low+0Ch]
div ecx
mov edx,ebx
jmp @@BHighZero
@@BHighNotZero:
mov ebx,eax
mov ecx,[esp+b_low+0Ch]
mov edx,[esp+a_high+0Ch]
mov eax,[esp+a_low+0Ch]
; Shift values right until b.high becomes zero
@@ShiftLoop:
shr ebx,1
rcr ecx,1
shr edx,1
rcr eax,1
or ebx,ebx
jnz @@ShiftLoop
; Now complete the divide process
div ecx
mov esi,eax
mul [DWORD esp+b_high+0Ch]
mov ecx,eax
mov eax,[esp+b_low+0Ch]
mul esi
add edx,ecx
jb @@8
cmp edx,[esp+a_high+0Ch]
ja @@8
jb @@9
cmp eax,[esp+a_low+0Ch]
jbe @@9
@@8: dec esi
@@9: xor edx,edx
mov eax,esi
@@BHighZero:
dec edi
jnz @@Done
; The result needs to be negated as either a or b was negative
neg edx
neg eax
sbb edx,0
@@Done: pop ebx
pop esi
pop edi
mov ecx,[esp+result_4]
mov [ecx],eax
mov [ecx+4],edx
ret
cprocend
;----------------------------------------------------------------------------
; __i64 _PM_shr64(u32 a_low,s32 a_high,s32 shift,__u64 *result);
;----------------------------------------------------------------------------
; Shift a 64-bit number right
;----------------------------------------------------------------------------
cprocstart _PM_shr64
mov eax,[esp+a_low]
mov edx,[esp+a_high]
mov cl,[esp+shift]
shrd edx,eax,cl
mov ecx,[esp+result_3]
mov [ecx],eax
mov [ecx+4],edx
ret
cprocend
;----------------------------------------------------------------------------
; __i64 _PM_sar64(u32 a_low,s32 a_high,s32 shift,__u64 *result);
;----------------------------------------------------------------------------
; Shift a 64-bit number right (signed)
;----------------------------------------------------------------------------
cprocstart _PM_sar64
mov eax,[esp+a_low]
mov edx,[esp+a_high]
mov cl,[esp+shift]
sar edx,cl
rcr eax,cl
mov ecx,[esp+result_3]
mov [ecx],eax
mov [ecx+4],edx
ret
cprocend
;----------------------------------------------------------------------------
; __i64 _PM_shl64(u32 a_low,s32 a_high,s32 shift,__u64 *result);
;----------------------------------------------------------------------------
; Shift a 64-bit number left
;----------------------------------------------------------------------------
cprocstart _PM_shl64
mov eax,[esp+a_low]
mov edx,[esp+a_high]
mov cl,[esp+shift]
shld edx,eax,cl
mov ecx,[esp+result_3]
mov [ecx],eax
mov [ecx+4],edx
ret
cprocend
;----------------------------------------------------------------------------
; __i64 _PM_neg64(u32 a_low,s32 a_high,__u64 *result);
;----------------------------------------------------------------------------
; Shift a 64-bit number left
;----------------------------------------------------------------------------
cprocstart _PM_neg64
mov eax,[esp+a_low]
mov edx,[esp+a_high]
neg eax
neg edx
sbb eax,0
mov ecx,[esp+result_2]
mov [ecx],eax
mov [ecx+4],edx
ret
cprocend
endcodeseg _int64
END