1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/euser/epoc/win32/uc_i64.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,235 @@
1.4 +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\euser\epoc\win32\uc_i64.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include "u32std.h"
1.22 +#include <e32math.h>
1.23 +
1.24 +#pragma warning ( disable : 4100 ) // unreferenced formal parameter
1.25 +#pragma warning ( disable : 4414 ) // short jump to function converted to near
1.26 +
1.27 +extern "C" void UDiv64();
1.28 +
1.29 +
1.30 +
1.31 +
1.32 +EXPORT_C __NAKED__ void Math::Mul64(Int64 /*aX*/, Int64 /*aY*/, Int64& /*aOutH*/, Uint64& /*aOutL*/)
1.33 +/**
1.34 +Multiply aX by aY to generate a 128 bit result.
1.35 +
1.36 +The high order 64 bits of this calculation are stored in aOutH,
1.37 +and the low order 64 bits are stored in aOutL.
1.38 +
1.39 +@param aX The first 64-bit operand.
1.40 +@param aY The second 64-bit operand.
1.41 +@param aOutH The high order 64 bits of the result.
1.42 +@param aOutL The low order 64 bits of the result.
1.43 +*/
1.44 + {
1.45 + _asm mov eax, [esp+4]
1.46 + _asm mul dword ptr [esp+12] // edx:eax = x0*y0
1.47 + _asm push edi
1.48 + _asm push esi
1.49 + _asm push ebx // [esp+16]=&aX, [esp+24]=&aY, [esp+32]=&aOutH, [esp+36]=&aOutL
1.50 + _asm mov ecx, eax
1.51 + _asm mov ebx, edx // ebx:ecx = x0*y0
1.52 + _asm mov eax, [esp+16]
1.53 + _asm mul dword ptr [esp+28] // edx:eax = x0*y1
1.54 + _asm xor esi, esi
1.55 + _asm add ebx, eax
1.56 + _asm adc esi, edx // esi:ebx:ecx = x0*y
1.57 + _asm mov eax, [esp+20] // eax=x1
1.58 + _asm imul dword ptr [esp+28] // edx:eax = x1*y1
1.59 + _asm mov edi, edx
1.60 + _asm add esi, eax
1.61 + _asm adc edi, 0 // partial result in edi:esi:ebx:ecx
1.62 + _asm cmp dword ptr [esp+28], 0 // y<0 ?
1.63 + _asm jns mul64_ypos
1.64 + _asm sub esi, [esp+16] // if so, subtract x0<<64
1.65 + _asm sbb edi, 0
1.66 + mul64_ypos:
1.67 + _asm mov eax, [esp+20] // eax=x1
1.68 + _asm cmp eax, 0 // x<0 ?
1.69 + _asm jns mul64_xpos
1.70 + _asm sub esi, [esp+24] // if so, subtract y0<<64
1.71 + _asm sbb edi, 0
1.72 + mul64_xpos:
1.73 + _asm mul dword ptr [esp+24] // edx:eax = x1*y0
1.74 + _asm add ebx, eax
1.75 + _asm mov eax, [esp+32] // eax=&aOutH
1.76 + _asm adc esi, edx
1.77 + _asm mov edx, [esp+36] // edx=&aOutL
1.78 + _asm adc edi, 0 // full result now in edi:esi:ebx:ecx
1.79 + _asm mov [eax], esi
1.80 + _asm mov [eax+4], edi // store high 64
1.81 + _asm mov [edx], ecx
1.82 + _asm mov [edx+4], ebx // store low 64
1.83 + _asm pop ebx
1.84 + _asm pop esi
1.85 + _asm pop edi
1.86 + _asm ret
1.87 + }
1.88 +
1.89 +
1.90 +
1.91 +
1.92 +EXPORT_C __NAKED__ void Math::UMul64(Uint64 /*aX*/, Uint64 /*aY*/, Uint64& /*aOutH*/, Uint64& /*aOutL*/)
1.93 +/**
1.94 +Multiply aX by aY to generate a 128 bit result.
1.95 +
1.96 +The high order 64 bits of this calculation are stored in aOutH,
1.97 +and the low order 64 bits are stored in aOutL.
1.98 +
1.99 +@param aX The first 64-bit operand.
1.100 +@param aY The second 64-bit operand.
1.101 +@param aOutH The high order 64 bits of the result.
1.102 +@param aOutL The low order 64 bits of the result.
1.103 +*/
1.104 + {
1.105 + _asm mov eax, [esp+4]
1.106 + _asm mul dword ptr [esp+12] // edx:eax = x0*y0
1.107 + _asm push edi
1.108 + _asm push esi
1.109 + _asm push ebx // [esp+16]=&aX, [esp+24]=&aY, [esp+32]=&aOutH, [esp+36]=&aOutL
1.110 + _asm mov ecx, eax
1.111 + _asm mov ebx, edx // ebx:ecx = x0*y0
1.112 + _asm mov eax, [esp+16]
1.113 + _asm mul dword ptr [esp+28] // edx:eax = x0*y1
1.114 + _asm xor esi, esi
1.115 + _asm add ebx, eax
1.116 + _asm adc esi, edx // esi:ebx:ecx = x0*y
1.117 + _asm mov eax, [esp+20] // eax=x1
1.118 + _asm mul dword ptr [esp+28] // edx:eax = x1*y1
1.119 + _asm mov edi, edx
1.120 + _asm add esi, eax
1.121 + _asm adc edi, 0 // partial result in edi:esi:ebx:ecx
1.122 + _asm mov eax, [esp+20]
1.123 + _asm mul dword ptr [esp+24] // edx:eax = x1*y0
1.124 + _asm add ebx, eax
1.125 + _asm mov eax, [esp+32] // eax=&aOutH
1.126 + _asm adc esi, edx
1.127 + _asm mov edx, [esp+36] // edx=&aOutL
1.128 + _asm adc edi, 0 // full result now in edi:esi:ebx:ecx
1.129 + _asm mov [eax], esi
1.130 + _asm mov [eax+4], edi // store high 64
1.131 + _asm mov [edx], ecx
1.132 + _asm mov [edx+4], ebx // store low 64
1.133 + _asm pop ebx
1.134 + _asm pop esi
1.135 + _asm pop edi
1.136 + _asm ret
1.137 + }
1.138 +
1.139 +
1.140 +
1.141 +
1.142 +EXPORT_C __NAKED__ Int64 Math::DivMod64(Int64 /*aDividend*/, Int64 /*aDivisor*/, Int64& /*aRemainder*/)
1.143 +/**
1.144 +Divides aDividend by aDivisor.
1.145 +
1.146 +The quotient is returned, and the remainder is stored in aRemainder.
1.147 +The remainder has same sign as the dividend.
1.148 +
1.149 +@param aDividend The 64-bit dividend.
1.150 +@param aDivisor The 64-bit divisor.
1.151 +@param aRemainder The 64-bit remainder.
1.152 +
1.153 +@return The 64-bit quotient.
1.154 +*/
1.155 + {
1.156 + _asm mov eax, [esp+4]
1.157 + _asm mov edx, [esp+8] // edx:eax = dividend
1.158 + _asm cmp edx, 0
1.159 + _asm jns divmod64_0
1.160 + _asm neg edx
1.161 + _asm neg eax
1.162 + _asm sbb edx, 0
1.163 + divmod64_0: // edx:eax = ABS(dividend)
1.164 + _asm push edi
1.165 + _asm push esi
1.166 + _asm push ebx
1.167 + _asm push ebp
1.168 + _asm mov esi, [esp+28]
1.169 + _asm mov edi, [esp+32] // edi:esi = dividend
1.170 + _asm cmp edi, 0
1.171 + _asm jns divmod64_1
1.172 + _asm neg edi
1.173 + _asm neg esi
1.174 + _asm sbb edi, 0 // edi:esi = ABS(dividend)
1.175 + divmod64_1:
1.176 + _asm call UDiv64 // do division, quotient in ebx:eax remainder in edi:edx
1.177 + _asm xchg ebx, edx // quotient in edx:eax, remainder in edi:ebx
1.178 + _asm mov ecx, [esp+24] // ecx=dividend high
1.179 + _asm xor ecx, [esp+32] // ecx=dividend high ^ divisor high
1.180 + _asm jns divmod64_2
1.181 + _asm neg edx
1.182 + _asm neg eax
1.183 + _asm sbb edx, 0
1.184 + divmod64_2: // edx:eax = quotient with correct sign
1.185 + _asm cmp dword ptr [esp+24], 0
1.186 + _asm jns divmod64_3
1.187 + _asm neg edi
1.188 + _asm neg ebx
1.189 + _asm sbb edi, 0
1.190 + divmod64_3: // edi:ebx = remainder with correct sign
1.191 + _asm mov ecx, [esp+36] // ecx=&aRemainder
1.192 + _asm mov [ecx], ebx
1.193 + _asm mov [ecx+4], edi
1.194 + _asm pop ebp
1.195 + _asm pop ebx
1.196 + _asm pop esi
1.197 + _asm pop edi
1.198 + _asm ret
1.199 + }
1.200 +
1.201 +
1.202 +
1.203 +
1.204 +EXPORT_C __NAKED__ Uint64 Math::UDivMod64(Uint64 /*aDividend*/, Uint64 /*aDivisor*/, Uint64& /*aRemainder*/)
1.205 +/**
1.206 +Divides aDividend by aDivisor.
1.207 +
1.208 +The quotient is returned, and the remainder is stored in aRemainder.
1.209 +
1.210 +@param aDividend The 64-bit dividend.
1.211 +@param aDivisor The 64-bit divisor.
1.212 +@param aRemainder The 64-bit remainder.
1.213 +
1.214 +@return The 64-bit quotient.
1.215 +*/
1.216 + {
1.217 + _asm mov eax, [esp+4]
1.218 + _asm mov edx, [esp+8] // edx:eax = dividend
1.219 + _asm push edi
1.220 + _asm push esi
1.221 + _asm push ebx
1.222 + _asm push ebp
1.223 + _asm mov esi, [esp+28]
1.224 + _asm mov edi, [esp+32] // edi:esi = dividend
1.225 + _asm call UDiv64 // do division, quotient in ebx:eax remainder in edi:edx
1.226 + _asm xchg ebx, edx // quotient in edx:eax, remainder in edi:ebx
1.227 + _asm mov ecx, [esp+36] // ecx=&aRemainder
1.228 + _asm mov [ecx], ebx
1.229 + _asm mov [ecx+4], edi
1.230 + _asm pop ebp
1.231 + _asm pop ebx
1.232 + _asm pop esi
1.233 + _asm pop edi
1.234 + _asm ret
1.235 + }
1.236 +
1.237 +#pragma warning ( default : 4100 )
1.238 +#pragma warning ( default : 4414 )