;**************************************************************************** ;* ;* 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