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