First public contribution.
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\euser\epoc\x86\uc_i64.cia
21 extern "C" void UDiv64();
23 EXPORT_C __NAKED__ void Math::Mul64(Int64 /*aX*/, Int64 /*aY*/, Int64& /*aOutH*/, Uint64& /*aOutL*/)
25 Multiply aX by aY to generate a 128 bit result.
27 The high order 64 bits of this calculation are stored in aOutH,
28 and the low order 64 bits are stored in aOutL.
30 @param aX The first 64-bit operand.
31 @param aY The second 64-bit operand.
32 @param aOutH The high order 64 bits of the result.
33 @param aOutL The low order 64 bits of the result.
36 asm("mov eax, [esp+4]");
37 asm("mul dword ptr [esp+12]"); // edx:eax = x0*y0
40 asm("push ebx"); // [esp+16]=&aX, [esp+24]=&aY, [esp+32]=&aOutH, [esp+36]=&aOutL
42 asm("mov ebx, edx"); // ebx:ecx = x0*y0
43 asm("mov eax, [esp+16]");
44 asm("mul dword ptr [esp+28]"); // edx:eax = x0*y1
47 asm("adc esi, edx"); // esi:ebx:ecx = x0*y
48 asm("mov eax, [esp+20]"); // eax=x1
49 asm("imul dword ptr [esp+28]"); // edx:eax = x1*y1
52 asm("adc edi, 0"); // partial result in edi:esi:ebx:ecx
53 asm("cmp dword ptr [esp+28],0");// y<0 ?
54 asm("jns mul64_ypos");
55 asm("sub esi, [esp+16]"); // if so, subtract x0<<64
58 asm("mov eax, [esp+20]"); // eax=x1
59 asm("cmp eax, 0"); // x<0 ?
60 asm("jns mul64_xpos");
61 asm("sub esi, [esp+24]"); // if so, subtract y0<<64
64 asm("mul dword ptr [esp+24]"); // edx:eax = x1*y0
66 asm("mov eax, [esp+32]"); // eax=&aOutH
68 asm("mov edx, [esp+36]"); // edx=&aOutL
69 asm("adc edi, 0"); // full result now in edi:esi:ebx:ecx
70 asm("mov [eax], esi");
71 asm("mov [eax+4], edi"); // store high 64
72 asm("mov [edx], ecx");
73 asm("mov [edx+4], ebx"); // store low 64
83 EXPORT_C __NAKED__ void Math::UMul64(Uint64 /*aX*/, Uint64 /*aY*/, Uint64& /*aOutH*/, Uint64& /*aOutL*/)
85 Multiply aX by aY to generate a 128 bit result.
87 The high order 64 bits of this calculation are stored in aOutH,
88 and the low order 64 bits are stored in aOutL.
90 @param aX The first 64-bit operand.
91 @param aY The second 64-bit operand.
92 @param aOutH The high order 64 bits of the result.
93 @param aOutL The low order 64 bits of the result.
96 asm("mov eax, [esp+4]");
97 asm("mul dword ptr [esp+12]"); // edx:eax = x0*y0
100 asm("push ebx"); // [esp+16]=&aX, [esp+24]=&aY, [esp+32]=&aOutH, [esp+36]=&aOutL
102 asm("mov ebx, edx"); // ebx:ecx = x0*y0
103 asm("mov eax, [esp+16]");
104 asm("mul dword ptr [esp+28]"); // edx:eax = x0*y1
107 asm("adc esi, edx"); // esi:ebx:ecx = x0*y
108 asm("mov eax, [esp+20]"); // eax=x1
109 asm("mul dword ptr [esp+28]"); // edx:eax = x1*y1
112 asm("adc edi, 0"); // partial result in edi:esi:ebx:ecx
113 asm("mov eax, [esp+20]");
114 asm("mul dword ptr [esp+24]"); // edx:eax = x1*y0
116 asm("mov eax, [esp+32]"); // eax=&aOutH
118 asm("mov edx, [esp+36]"); // edx=&aOutL
119 asm("adc edi, 0"); // full result now in edi:esi:ebx:ecx
120 asm("mov [eax], esi");
121 asm("mov [eax+4], edi"); // store high 64
122 asm("mov [edx], ecx");
123 asm("mov [edx+4], ebx"); // store low 64
133 EXPORT_C __NAKED__ Int64 Math::DivMod64(Int64 /*aDividend*/, Int64 /*aDivisor*/, Int64& /*aRemainder*/)
135 Divides aDividend by aDivisor.
137 The quotient is returned, and the remainder is stored in aRemainder.
138 The remainder has same sign as the dividend.
140 @param aDividend The 64-bit dividend.
141 @param aDivisor The 64-bit divisor.
142 @param aRemainder The 64-bit remainder.
144 @return The 64-bit quotient.
147 asm("mov eax, [esp+4]");
148 asm("mov edx, [esp+8]"); // edx:eax = dividend
150 asm("jns divmod64_0");
154 asm("divmod64_0:"); // edx:eax = ABS{dividend}
159 asm("mov esi, [esp+28]");
160 asm("mov edi, [esp+32]"); // edi:esi = dividend
162 asm("jns divmod64_1");
165 asm("sbb edi, 0"); // edi:esi = ABS{dividend}
167 asm("call %a0": : "i"(&UDiv64)); // do division, quotient in ebx:eax remainder in edi:edx
168 asm("xchg ebx, edx"); // quotient in edx:eax, remainder in edi:ebx
169 asm("mov ecx, [esp+24]"); // ecx=dividend high
170 asm("xor ecx, [esp+32]"); // ecx=dividend high ^ divisor high
171 asm("jns divmod64_2");
175 asm("divmod64_2:"); // edx:eax = quotient with correct sign
176 asm("cmp dword ptr [esp+24], 0");
177 asm("jns divmod64_3");
181 asm("divmod64_3:"); // edi:ebx = remainder with correct sign
182 asm("mov ecx, [esp+36]"); // ecx=&aRemainder
183 asm("mov [ecx], ebx");
184 asm("mov [ecx+4], edi");
195 EXPORT_C __NAKED__ Uint64 Math::UDivMod64(Uint64 /*aDividend*/, Uint64 /*aDivisor*/, Uint64& /*aRemainder*/)
197 Divides aDividend by aDivisor.
199 The quotient is returned, and the remainder is stored in aRemainder.
201 @param aDividend The 64-bit dividend.
202 @param aDivisor The 64-bit divisor.
203 @param aRemainder The 64-bit remainder.
205 @return The 64-bit quotient.
208 asm("mov eax, [esp+4]");
209 asm("mov edx, [esp+8]"); // edx:eax = dividend
214 asm("mov esi, [esp+28]");
215 asm("mov edi, [esp+32]"); // edi:esi = dividend
216 asm("call %a0": : "i"(&UDiv64)); // do division, quotient in ebx:eax remainder in edi:edx
217 asm("xchg ebx, edx"); // quotient in edx:eax, remainder in edi:ebx
218 asm("mov ecx, [esp+36]"); // ecx=&aRemainder
219 asm("mov [ecx], ebx");
220 asm("mov [ecx+4], edi");