kernel/eka/euser/epoc/win32/uc_i64.cpp
changeset 9 96e5fb8b040d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/euser/epoc/win32/uc_i64.cpp	Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,235 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\euser\epoc\win32\uc_i64.cpp
+// 
+//
+
+#include "u32std.h"
+#include <e32math.h>
+
+#pragma warning ( disable : 4100 )	// unreferenced formal parameter
+#pragma warning ( disable : 4414 )  // short jump to function converted to near
+
+extern "C" void UDiv64();
+
+
+
+
+EXPORT_C __NAKED__ void Math::Mul64(Int64 /*aX*/, Int64 /*aY*/, Int64& /*aOutH*/, Uint64& /*aOutL*/)
+/**
+Multiply aX by aY to generate a 128 bit result.
+
+The high order 64 bits of this calculation are stored in aOutH,
+and the low order 64 bits are stored in aOutL.
+
+@param aX     The first 64-bit operand.
+@param aY     The second 64-bit operand.
+@param aOutH  The high order 64 bits of the result.
+@param aOutL  The low order  64 bits of the result.
+*/
+	{
+	_asm mov eax, [esp+4]
+	_asm mul dword ptr [esp+12]		// edx:eax = x0*y0
+	_asm push edi
+	_asm push esi
+	_asm push ebx					// [esp+16]=&aX, [esp+24]=&aY, [esp+32]=&aOutH, [esp+36]=&aOutL
+	_asm mov ecx, eax
+	_asm mov ebx, edx				// ebx:ecx = x0*y0
+	_asm mov eax, [esp+16]
+	_asm mul dword ptr [esp+28]		// edx:eax = x0*y1
+	_asm xor esi, esi
+	_asm add ebx, eax
+	_asm adc esi, edx				// esi:ebx:ecx = x0*y
+	_asm mov eax, [esp+20]			// eax=x1
+	_asm imul dword ptr [esp+28]	// edx:eax = x1*y1
+	_asm mov edi, edx
+	_asm add esi, eax
+	_asm adc edi, 0					// partial result in edi:esi:ebx:ecx
+	_asm cmp dword ptr [esp+28], 0	// y<0 ?
+	_asm jns mul64_ypos
+	_asm sub esi, [esp+16]			// if so, subtract x0<<64
+	_asm sbb edi, 0
+	mul64_ypos:
+	_asm mov eax, [esp+20]			// eax=x1
+	_asm cmp eax, 0					// x<0 ?
+	_asm jns mul64_xpos
+	_asm sub esi, [esp+24]			// if so, subtract y0<<64
+	_asm sbb edi, 0
+	mul64_xpos:
+	_asm mul dword ptr [esp+24]		// edx:eax = x1*y0
+	_asm add ebx, eax
+	_asm mov eax, [esp+32]			// eax=&aOutH
+	_asm adc esi, edx
+	_asm mov edx, [esp+36]			// edx=&aOutL
+	_asm adc edi, 0					// full result now in edi:esi:ebx:ecx
+	_asm mov [eax], esi
+	_asm mov [eax+4], edi			// store high 64
+	_asm mov [edx], ecx
+	_asm mov [edx+4], ebx			// store low 64
+	_asm pop ebx
+	_asm pop esi
+	_asm pop edi
+	_asm ret
+	}
+
+
+
+
+EXPORT_C __NAKED__ void Math::UMul64(Uint64 /*aX*/, Uint64 /*aY*/, Uint64& /*aOutH*/, Uint64& /*aOutL*/)
+/**
+Multiply aX by aY to generate a 128 bit result.
+
+The high order 64 bits of this calculation are stored in aOutH,
+and the low order 64 bits are stored in aOutL.
+
+@param aX     The first 64-bit operand.
+@param aY     The second 64-bit operand.
+@param aOutH  The high order 64 bits of the result.
+@param aOutL  The low order  64 bits of the result.
+*/
+	{
+	_asm mov eax, [esp+4]
+	_asm mul dword ptr [esp+12]		// edx:eax = x0*y0
+	_asm push edi
+	_asm push esi
+	_asm push ebx					// [esp+16]=&aX, [esp+24]=&aY, [esp+32]=&aOutH, [esp+36]=&aOutL
+	_asm mov ecx, eax
+	_asm mov ebx, edx				// ebx:ecx = x0*y0
+	_asm mov eax, [esp+16]
+	_asm mul dword ptr [esp+28]		// edx:eax = x0*y1
+	_asm xor esi, esi
+	_asm add ebx, eax
+	_asm adc esi, edx				// esi:ebx:ecx = x0*y
+	_asm mov eax, [esp+20]			// eax=x1
+	_asm mul dword ptr [esp+28]		// edx:eax = x1*y1
+	_asm mov edi, edx
+	_asm add esi, eax
+	_asm adc edi, 0					// partial result in edi:esi:ebx:ecx
+	_asm mov eax, [esp+20]
+	_asm mul dword ptr [esp+24]		// edx:eax = x1*y0
+	_asm add ebx, eax
+	_asm mov eax, [esp+32]			// eax=&aOutH
+	_asm adc esi, edx
+	_asm mov edx, [esp+36]			// edx=&aOutL
+	_asm adc edi, 0					// full result now in edi:esi:ebx:ecx
+	_asm mov [eax], esi
+	_asm mov [eax+4], edi			// store high 64
+	_asm mov [edx], ecx
+	_asm mov [edx+4], ebx			// store low 64
+	_asm pop ebx
+	_asm pop esi
+	_asm pop edi
+	_asm ret
+	}
+
+
+
+
+EXPORT_C __NAKED__ Int64 Math::DivMod64(Int64 /*aDividend*/, Int64 /*aDivisor*/, Int64& /*aRemainder*/)
+/**
+Divides aDividend by aDivisor.
+
+The quotient is returned, and the remainder is stored in aRemainder.
+The remainder has same sign as the dividend.
+
+@param aDividend The 64-bit dividend.
+@param aDivisor  The 64-bit divisor.
+@param aRemainder The 64-bit remainder.
+
+@return The 64-bit quotient.
+*/
+	{
+	_asm mov eax, [esp+4]
+	_asm mov edx, [esp+8]			// edx:eax = dividend
+	_asm cmp edx, 0
+	_asm jns divmod64_0
+	_asm neg edx
+	_asm neg eax
+	_asm sbb edx, 0
+	divmod64_0:						// edx:eax = ABS(dividend)
+	_asm push edi
+	_asm push esi
+	_asm push ebx
+	_asm push ebp
+	_asm mov esi, [esp+28]
+	_asm mov edi, [esp+32]			// edi:esi = dividend
+	_asm cmp edi, 0
+	_asm jns divmod64_1
+	_asm neg edi
+	_asm neg esi
+	_asm sbb edi, 0					// edi:esi = ABS(dividend)
+	divmod64_1:
+	_asm call UDiv64				// do division, quotient in ebx:eax remainder in edi:edx
+	_asm xchg ebx, edx				// quotient in edx:eax, remainder in edi:ebx
+	_asm mov ecx, [esp+24]			// ecx=dividend high
+	_asm xor ecx, [esp+32]			// ecx=dividend high ^ divisor high
+	_asm jns divmod64_2
+	_asm neg edx
+	_asm neg eax
+	_asm sbb edx, 0
+	divmod64_2:						// edx:eax = quotient with correct sign
+	_asm cmp dword ptr [esp+24], 0
+	_asm jns divmod64_3
+	_asm neg edi
+	_asm neg ebx
+	_asm sbb edi, 0
+	divmod64_3:						// edi:ebx = remainder with correct sign
+	_asm mov ecx, [esp+36]			// ecx=&aRemainder
+	_asm mov [ecx], ebx
+	_asm mov [ecx+4], edi
+	_asm pop ebp
+	_asm pop ebx
+	_asm pop esi
+	_asm pop edi
+	_asm ret
+	}
+
+
+
+
+EXPORT_C __NAKED__ Uint64 Math::UDivMod64(Uint64 /*aDividend*/, Uint64 /*aDivisor*/, Uint64& /*aRemainder*/)
+/**
+Divides aDividend by aDivisor.
+
+The quotient is returned, and the remainder is stored in aRemainder.
+
+@param aDividend The 64-bit dividend.
+@param aDivisor  The 64-bit divisor.
+@param aRemainder The 64-bit remainder.
+
+@return The 64-bit quotient.
+*/
+	{
+	_asm mov eax, [esp+4]
+	_asm mov edx, [esp+8]			// edx:eax = dividend
+	_asm push edi
+	_asm push esi
+	_asm push ebx
+	_asm push ebp
+	_asm mov esi, [esp+28]
+	_asm mov edi, [esp+32]			// edi:esi = dividend
+	_asm call UDiv64				// do division, quotient in ebx:eax remainder in edi:edx
+	_asm xchg ebx, edx				// quotient in edx:eax, remainder in edi:ebx
+	_asm mov ecx, [esp+36]			// ecx=&aRemainder
+	_asm mov [ecx], ebx
+	_asm mov [ecx+4], edi
+	_asm pop ebp
+	_asm pop ebx
+	_asm pop esi
+	_asm pop edi
+	_asm ret
+	}
+
+#pragma warning ( default : 4100 )
+#pragma warning ( default : 4414 )