|
1 // Copyright (c) 1997-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". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32\euser\epoc\win32\uc_i64.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include "u32std.h" |
|
19 #include <e32math.h> |
|
20 |
|
21 #pragma warning ( disable : 4100 ) // unreferenced formal parameter |
|
22 #pragma warning ( disable : 4414 ) // short jump to function converted to near |
|
23 |
|
24 extern "C" void UDiv64(); |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 EXPORT_C __NAKED__ void Math::Mul64(Int64 /*aX*/, Int64 /*aY*/, Int64& /*aOutH*/, Uint64& /*aOutL*/) |
|
30 /** |
|
31 Multiply aX by aY to generate a 128 bit result. |
|
32 |
|
33 The high order 64 bits of this calculation are stored in aOutH, |
|
34 and the low order 64 bits are stored in aOutL. |
|
35 |
|
36 @param aX The first 64-bit operand. |
|
37 @param aY The second 64-bit operand. |
|
38 @param aOutH The high order 64 bits of the result. |
|
39 @param aOutL The low order 64 bits of the result. |
|
40 */ |
|
41 { |
|
42 _asm mov eax, [esp+4] |
|
43 _asm mul dword ptr [esp+12] // edx:eax = x0*y0 |
|
44 _asm push edi |
|
45 _asm push esi |
|
46 _asm push ebx // [esp+16]=&aX, [esp+24]=&aY, [esp+32]=&aOutH, [esp+36]=&aOutL |
|
47 _asm mov ecx, eax |
|
48 _asm mov ebx, edx // ebx:ecx = x0*y0 |
|
49 _asm mov eax, [esp+16] |
|
50 _asm mul dword ptr [esp+28] // edx:eax = x0*y1 |
|
51 _asm xor esi, esi |
|
52 _asm add ebx, eax |
|
53 _asm adc esi, edx // esi:ebx:ecx = x0*y |
|
54 _asm mov eax, [esp+20] // eax=x1 |
|
55 _asm imul dword ptr [esp+28] // edx:eax = x1*y1 |
|
56 _asm mov edi, edx |
|
57 _asm add esi, eax |
|
58 _asm adc edi, 0 // partial result in edi:esi:ebx:ecx |
|
59 _asm cmp dword ptr [esp+28], 0 // y<0 ? |
|
60 _asm jns mul64_ypos |
|
61 _asm sub esi, [esp+16] // if so, subtract x0<<64 |
|
62 _asm sbb edi, 0 |
|
63 mul64_ypos: |
|
64 _asm mov eax, [esp+20] // eax=x1 |
|
65 _asm cmp eax, 0 // x<0 ? |
|
66 _asm jns mul64_xpos |
|
67 _asm sub esi, [esp+24] // if so, subtract y0<<64 |
|
68 _asm sbb edi, 0 |
|
69 mul64_xpos: |
|
70 _asm mul dword ptr [esp+24] // edx:eax = x1*y0 |
|
71 _asm add ebx, eax |
|
72 _asm mov eax, [esp+32] // eax=&aOutH |
|
73 _asm adc esi, edx |
|
74 _asm mov edx, [esp+36] // edx=&aOutL |
|
75 _asm adc edi, 0 // full result now in edi:esi:ebx:ecx |
|
76 _asm mov [eax], esi |
|
77 _asm mov [eax+4], edi // store high 64 |
|
78 _asm mov [edx], ecx |
|
79 _asm mov [edx+4], ebx // store low 64 |
|
80 _asm pop ebx |
|
81 _asm pop esi |
|
82 _asm pop edi |
|
83 _asm ret |
|
84 } |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 EXPORT_C __NAKED__ void Math::UMul64(Uint64 /*aX*/, Uint64 /*aY*/, Uint64& /*aOutH*/, Uint64& /*aOutL*/) |
|
90 /** |
|
91 Multiply aX by aY to generate a 128 bit result. |
|
92 |
|
93 The high order 64 bits of this calculation are stored in aOutH, |
|
94 and the low order 64 bits are stored in aOutL. |
|
95 |
|
96 @param aX The first 64-bit operand. |
|
97 @param aY The second 64-bit operand. |
|
98 @param aOutH The high order 64 bits of the result. |
|
99 @param aOutL The low order 64 bits of the result. |
|
100 */ |
|
101 { |
|
102 _asm mov eax, [esp+4] |
|
103 _asm mul dword ptr [esp+12] // edx:eax = x0*y0 |
|
104 _asm push edi |
|
105 _asm push esi |
|
106 _asm push ebx // [esp+16]=&aX, [esp+24]=&aY, [esp+32]=&aOutH, [esp+36]=&aOutL |
|
107 _asm mov ecx, eax |
|
108 _asm mov ebx, edx // ebx:ecx = x0*y0 |
|
109 _asm mov eax, [esp+16] |
|
110 _asm mul dword ptr [esp+28] // edx:eax = x0*y1 |
|
111 _asm xor esi, esi |
|
112 _asm add ebx, eax |
|
113 _asm adc esi, edx // esi:ebx:ecx = x0*y |
|
114 _asm mov eax, [esp+20] // eax=x1 |
|
115 _asm mul dword ptr [esp+28] // edx:eax = x1*y1 |
|
116 _asm mov edi, edx |
|
117 _asm add esi, eax |
|
118 _asm adc edi, 0 // partial result in edi:esi:ebx:ecx |
|
119 _asm mov eax, [esp+20] |
|
120 _asm mul dword ptr [esp+24] // edx:eax = x1*y0 |
|
121 _asm add ebx, eax |
|
122 _asm mov eax, [esp+32] // eax=&aOutH |
|
123 _asm adc esi, edx |
|
124 _asm mov edx, [esp+36] // edx=&aOutL |
|
125 _asm adc edi, 0 // full result now in edi:esi:ebx:ecx |
|
126 _asm mov [eax], esi |
|
127 _asm mov [eax+4], edi // store high 64 |
|
128 _asm mov [edx], ecx |
|
129 _asm mov [edx+4], ebx // store low 64 |
|
130 _asm pop ebx |
|
131 _asm pop esi |
|
132 _asm pop edi |
|
133 _asm ret |
|
134 } |
|
135 |
|
136 |
|
137 |
|
138 |
|
139 EXPORT_C __NAKED__ Int64 Math::DivMod64(Int64 /*aDividend*/, Int64 /*aDivisor*/, Int64& /*aRemainder*/) |
|
140 /** |
|
141 Divides aDividend by aDivisor. |
|
142 |
|
143 The quotient is returned, and the remainder is stored in aRemainder. |
|
144 The remainder has same sign as the dividend. |
|
145 |
|
146 @param aDividend The 64-bit dividend. |
|
147 @param aDivisor The 64-bit divisor. |
|
148 @param aRemainder The 64-bit remainder. |
|
149 |
|
150 @return The 64-bit quotient. |
|
151 */ |
|
152 { |
|
153 _asm mov eax, [esp+4] |
|
154 _asm mov edx, [esp+8] // edx:eax = dividend |
|
155 _asm cmp edx, 0 |
|
156 _asm jns divmod64_0 |
|
157 _asm neg edx |
|
158 _asm neg eax |
|
159 _asm sbb edx, 0 |
|
160 divmod64_0: // edx:eax = ABS(dividend) |
|
161 _asm push edi |
|
162 _asm push esi |
|
163 _asm push ebx |
|
164 _asm push ebp |
|
165 _asm mov esi, [esp+28] |
|
166 _asm mov edi, [esp+32] // edi:esi = dividend |
|
167 _asm cmp edi, 0 |
|
168 _asm jns divmod64_1 |
|
169 _asm neg edi |
|
170 _asm neg esi |
|
171 _asm sbb edi, 0 // edi:esi = ABS(dividend) |
|
172 divmod64_1: |
|
173 _asm call UDiv64 // do division, quotient in ebx:eax remainder in edi:edx |
|
174 _asm xchg ebx, edx // quotient in edx:eax, remainder in edi:ebx |
|
175 _asm mov ecx, [esp+24] // ecx=dividend high |
|
176 _asm xor ecx, [esp+32] // ecx=dividend high ^ divisor high |
|
177 _asm jns divmod64_2 |
|
178 _asm neg edx |
|
179 _asm neg eax |
|
180 _asm sbb edx, 0 |
|
181 divmod64_2: // edx:eax = quotient with correct sign |
|
182 _asm cmp dword ptr [esp+24], 0 |
|
183 _asm jns divmod64_3 |
|
184 _asm neg edi |
|
185 _asm neg ebx |
|
186 _asm sbb edi, 0 |
|
187 divmod64_3: // edi:ebx = remainder with correct sign |
|
188 _asm mov ecx, [esp+36] // ecx=&aRemainder |
|
189 _asm mov [ecx], ebx |
|
190 _asm mov [ecx+4], edi |
|
191 _asm pop ebp |
|
192 _asm pop ebx |
|
193 _asm pop esi |
|
194 _asm pop edi |
|
195 _asm ret |
|
196 } |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 EXPORT_C __NAKED__ Uint64 Math::UDivMod64(Uint64 /*aDividend*/, Uint64 /*aDivisor*/, Uint64& /*aRemainder*/) |
|
202 /** |
|
203 Divides aDividend by aDivisor. |
|
204 |
|
205 The quotient is returned, and the remainder is stored in aRemainder. |
|
206 |
|
207 @param aDividend The 64-bit dividend. |
|
208 @param aDivisor The 64-bit divisor. |
|
209 @param aRemainder The 64-bit remainder. |
|
210 |
|
211 @return The 64-bit quotient. |
|
212 */ |
|
213 { |
|
214 _asm mov eax, [esp+4] |
|
215 _asm mov edx, [esp+8] // edx:eax = dividend |
|
216 _asm push edi |
|
217 _asm push esi |
|
218 _asm push ebx |
|
219 _asm push ebp |
|
220 _asm mov esi, [esp+28] |
|
221 _asm mov edi, [esp+32] // edi:esi = dividend |
|
222 _asm call UDiv64 // do division, quotient in ebx:eax remainder in edi:edx |
|
223 _asm xchg ebx, edx // quotient in edx:eax, remainder in edi:ebx |
|
224 _asm mov ecx, [esp+36] // ecx=&aRemainder |
|
225 _asm mov [ecx], ebx |
|
226 _asm mov [ecx+4], edi |
|
227 _asm pop ebp |
|
228 _asm pop ebx |
|
229 _asm pop esi |
|
230 _asm pop edi |
|
231 _asm ret |
|
232 } |
|
233 |
|
234 #pragma warning ( default : 4100 ) |
|
235 #pragma warning ( default : 4414 ) |