|
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". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32\euser\epoc\x86\uc_realx.cia |
|
15 // |
|
16 // |
|
17 |
|
18 |
|
19 #include "u32std.h" |
|
20 #include <e32math.h> |
|
21 |
|
22 |
|
23 void TRealXPanic(TInt aErr); |
|
24 |
|
25 LOCAL_C __NAKED__ void TRealXPanicEax(void) |
|
26 { |
|
27 asm("push eax"); |
|
28 asm("call %a0": : "i"(&TRealXPanic)); |
|
29 } |
|
30 |
|
31 LOCAL_C __NAKED__ void TRealXRealIndefinite(void) |
|
32 { |
|
33 // return 'real indefinite' NaN in ecx,edx:ebx |
|
34 asm("mov ecx, 0xFFFF0001"); // exponent=FFFF, sign negative |
|
35 asm("mov edx, 0xC0000000"); // mantissa=C0000000 00000000 |
|
36 asm("xor ebx, ebx"); |
|
37 asm("mov eax, -6"); // return KErrArgument |
|
38 asm("ret"); |
|
39 } |
|
40 |
|
41 LOCAL_C __NAKED__ void TRealXBinOpNaN(void) |
|
42 { |
|
43 // generic routine to process NaN's in binary operations |
|
44 // destination operand in ecx,edx:eax |
|
45 // source operand at [esi] |
|
46 |
|
47 asm("mov eax, [esi+8]"); // source operand into eax,edi:ebp |
|
48 asm("mov edi, [esi+4]"); |
|
49 asm("mov ebp, [esi]"); |
|
50 asm("cmp ecx, 0xFFFF0000"); // check if dest is a NaN |
|
51 asm("jb short TRealXBinOpNaN1"); // if not, swap them |
|
52 asm("cmp edx, 0x80000000"); |
|
53 asm("jne short TRealXBinOpNaN2"); |
|
54 asm("test ebx, ebx"); |
|
55 asm("jne short TRealXBinOpNaN2"); |
|
56 asm("TRealXBinOpNaN1:"); // swap the operands |
|
57 asm("xchg ecx, eax"); |
|
58 asm("xchg edx, edi"); |
|
59 asm("xchg ebx, ebp"); |
|
60 asm("TRealXBinOpNaN2:"); |
|
61 asm("cmp eax, 0xFFFF0000"); // check if both operands are NaNs |
|
62 asm("jb short TRealXBinOpNaN4"); // if not, ignore non-NaN operand |
|
63 asm("cmp edi, 0x80000000"); |
|
64 asm("jne short TRealXBinOpNaN3"); |
|
65 asm("test ebp, ebp"); |
|
66 asm("je short TRealXBinOpNaN4"); |
|
67 asm("TRealXBinOpNaN3:"); // if both operands are NaN's, compare significands |
|
68 asm("cmp edx, edi"); |
|
69 asm("ja short TRealXBinOpNaN4"); |
|
70 asm("jb short TRealXBinOpNaN5"); |
|
71 asm("cmp ebx, ebp"); |
|
72 asm("jae short TRealXBinOpNaN4"); |
|
73 asm("TRealXBinOpNaN5:"); // come here if dest is smaller - copy source to dest |
|
74 asm("mov ecx, eax"); |
|
75 asm("mov edx, edi"); |
|
76 asm("mov ebx, ebp"); |
|
77 asm("TRealXBinOpNaN4:"); // NaN with larger significand is in ecx,edx:ebx |
|
78 asm("or edx, 0x40000000"); // convert an SNaN to a QNaN |
|
79 asm("mov eax, -6"); // return KErrArgument |
|
80 asm("ret"); |
|
81 } |
|
82 |
|
83 // Add TRealX at [esi] + ecx,edx:ebx |
|
84 // Result in ecx,edx:ebx |
|
85 // Error code in eax |
|
86 // Note: +0 + +0 = +0, -0 + -0 = -0, +0 + -0 = -0 + +0 = +0, |
|
87 // +/-0 + X = X + +/-0 = X, X + -X = -X + X = +0 |
|
88 LOCAL_C __NAKED__ void TRealXAdd() |
|
89 { |
|
90 asm("xor ch, ch"); // clear rounding flags |
|
91 asm("cmp ecx, 0xFFFF0000"); // check if dest=NaN or infinity |
|
92 asm("jnc addfpsd"); // branch if it is |
|
93 asm("mov eax, [esi+8]"); // fetch sign/exponent of source |
|
94 asm("cmp eax, 0xFFFF0000"); // check if source=NaN or infinity |
|
95 asm("jnc addfpss"); // branch if it is |
|
96 asm("cmp eax, 0x10000"); // check if source=0 |
|
97 asm("jc addfp0s"); // branch if it is |
|
98 asm("cmp ecx, 0x10000"); // check if dest=0 |
|
99 asm("jc addfp0d"); // branch if it is |
|
100 asm("and cl, 1"); // clear bits 1-7 of ecx |
|
101 asm("and al, 1"); // clear bits 1-7 of eax |
|
102 asm("mov ch, cl"); |
|
103 asm("xor ch, al"); // xor of signs into ch bit 0 |
|
104 asm("add ch, ch"); |
|
105 asm("or cl, ch"); // and into cl bit 1 |
|
106 asm("or al, ch"); // and al bit 1 |
|
107 asm("xor ch, ch"); // clear rounding flags |
|
108 asm("mov ebp, [esi]"); // fetch source mantissa 0-31 |
|
109 asm("mov edi, [esi+4]"); // fetch source mantissa 32-63 |
|
110 asm("ror ecx, 16"); // dest exponent into cx |
|
111 asm("ror eax, 16"); // source exponent into ax |
|
112 asm("push ecx"); // push dest exponent/sign |
|
113 asm("sub cx, ax"); // cx = dest exponent - source exponent |
|
114 asm("je short addfp3b"); // if equal, no shifting required |
|
115 asm("ja short addfp1"); // branch if dest exponent >= source exponent |
|
116 asm("xchg ebx, ebp"); // make sure edi:ebp contains the mantissa to be shifted |
|
117 asm("xchg edx, edi"); |
|
118 asm("xchg eax, [esp]"); // and larger exponent and corresponding sign is on the stack |
|
119 asm("neg cx"); // make cx positive = number of right shifts needed |
|
120 asm("addfp1:"); |
|
121 asm("cmp cx, 64"); // if more than 64 shifts needed |
|
122 asm("ja addfp2"); // branch to output larger number |
|
123 asm("jb addfp3"); // branch if <64 shifts |
|
124 asm("mov eax, edi"); // exactly 64 shifts needed - rounding word=mant high |
|
125 asm("test ebp, ebp"); // check bits lost |
|
126 asm("jz short addfp3a"); |
|
127 asm("or ch, 1"); // if not all zero, set rounded-down flag |
|
128 asm("addfp3a:"); |
|
129 asm("xor edi, edi"); // clear edx:ebx |
|
130 asm("xor ebp, ebp"); |
|
131 asm("jmp short addfp5"); // finished shifting |
|
132 asm("addfp3b:"); // exponents equal |
|
133 asm("xor eax, eax"); // set rounding word=0 |
|
134 asm("jmp short addfp5"); |
|
135 asm("addfp3:"); |
|
136 asm("cmp cl, 32"); // 32 or more shifts needed ? |
|
137 asm("jb short addfp4"); // skip if <32 |
|
138 asm("mov eax, ebp"); // rounding word=mant low |
|
139 asm("mov ebp, edi"); // mant low=mant high |
|
140 asm("xor edi, edi"); // mant high=0 |
|
141 asm("sub cl, 32"); // reduce count by 32 |
|
142 asm("jz short addfp5"); // if now zero, finished shifting |
|
143 asm("shrd edi, eax, cl"); // shift ebp:eax:edi right by cl bits |
|
144 asm("shrd eax, ebp, cl"); // |
|
145 asm("shr ebp, cl"); // |
|
146 asm("test edi, edi"); // check bits lost in shift |
|
147 asm("jz short addfp5"); // if all zero, finished |
|
148 asm("or ch, 1"); // else set rounded-down flag |
|
149 asm("xor edi, edi"); // clear edx again |
|
150 asm("jmp short addfp5"); // finished shifting |
|
151 asm("addfp4:"); // <32 shifts needed now |
|
152 asm("xor eax, eax"); // clear rounding word initially |
|
153 asm("shrd eax, ebp, cl"); // shift edi:ebp:eax right by cl bits |
|
154 asm("shrd ebp, edi, cl"); // |
|
155 asm("shr edi, cl"); // |
|
156 |
|
157 asm("addfp5:"); |
|
158 asm("mov [esp+3], ch"); // rounding flag into ch image on stack |
|
159 asm("pop ecx"); // recover sign and exponent into ecx, with rounding flag |
|
160 asm("ror ecx, 16"); // into normal position |
|
161 asm("test cl, 2"); // addition or subtraction needed ? |
|
162 asm("jnz short subfp1"); // branch if subtraction |
|
163 asm("add ebx,ebp"); // addition required - add mantissas |
|
164 asm("adc edx,edi"); // |
|
165 asm("jnc short roundfp"); // branch if no carry |
|
166 asm("rcr edx,1"); // shift carry right into mantissa |
|
167 asm("rcr ebx,1"); // |
|
168 asm("rcr eax,1"); // and into rounding word |
|
169 asm("jnc short addfp5a"); |
|
170 asm("or ch, 1"); // if 1 shifted out, set rounded-down flag |
|
171 asm("addfp5a:"); |
|
172 asm("add ecx, 0x10000"); // and increment exponent |
|
173 |
|
174 // perform rounding based on rounding word in eax and rounding flag in ch |
|
175 asm("roundfp:"); |
|
176 asm("cmp eax, 0x80000000"); |
|
177 asm("jc roundfp0"); // if rounding word<80000000, round down |
|
178 asm("ja roundfp1"); // if >80000000, round up |
|
179 asm("test ch, 1"); |
|
180 asm("jnz short roundfp1"); // if rounded-down flag set, round up |
|
181 asm("test ch, 2"); |
|
182 asm("jnz short roundfp0"); // if rounded-up flag set, round down |
|
183 asm("test bl, 1"); // else test mantissa lsb |
|
184 asm("jz short roundfp0"); // round down if 0, up if 1 [round to even] |
|
185 asm("roundfp1:"); // Come here to round up |
|
186 asm("add ebx, 1"); // increment mantissa |
|
187 asm("adc edx,0"); // |
|
188 asm("jnc roundfp1a"); // if no carry OK |
|
189 asm("rcr edx,1"); // else shift carry into mantissa [edx:ebx=0 here] |
|
190 asm("add ecx, 0x10000"); // and increment exponent |
|
191 asm("roundfp1a:"); |
|
192 asm("cmp ecx, 0xFFFF0000"); // check for overflow |
|
193 asm("jae short addfpovfw"); // jump if overflow |
|
194 asm("mov ch, 2"); // else set rounded-up flag |
|
195 asm("xor eax, eax"); // return KErrNone |
|
196 asm("ret"); |
|
197 |
|
198 asm("roundfp0:"); // Come here to round down |
|
199 asm("cmp ecx, 0xFFFF0000"); // check for overflow |
|
200 asm("jae short addfpovfw"); // jump if overflow |
|
201 asm("test eax, eax"); // else check if rounding word zero |
|
202 asm("jz short roundfp0a"); // if so, leave rounding flags as they are |
|
203 asm("mov ch, 1"); // else set rounded-down flag |
|
204 asm("roundfp0a:"); |
|
205 asm("xor eax, eax"); // return KErrNone |
|
206 asm("ret"); |
|
207 |
|
208 asm("addfpovfw:"); // Come here if overflow occurs |
|
209 asm("xor ch, ch"); // clear rounding flags, exponent=FFFF |
|
210 asm("xor ebx, ebx"); |
|
211 asm("mov edx, 0x80000000"); // mantissa=80000000 00000000 for infinity |
|
212 asm("mov eax, -9"); // return KErrOverflow |
|
213 asm("ret"); |
|
214 |
|
215 // exponents differ by more than 64 - output larger number |
|
216 asm("addfp2:"); |
|
217 asm("pop ecx"); // recover exponent and sign |
|
218 asm("ror ecx, 16"); // into normal position |
|
219 asm("or ch, 1"); // set rounded-down flag |
|
220 asm("test cl, 2"); // check if signs the same |
|
221 asm("jz addfp2a"); |
|
222 asm("xor ch, 3"); // if not, set rounded-up flag |
|
223 asm("addfp2a:"); |
|
224 asm("xor eax, eax"); // return KErrNone |
|
225 asm("ret"); |
|
226 |
|
227 // signs differ, so must subtract mantissas |
|
228 asm("subfp1:"); |
|
229 asm("add ch, ch"); // if rounded-down flag set, change it to rounded-up |
|
230 asm("neg eax"); // subtract rounding word from 0 |
|
231 asm("sbb ebx, ebp"); // and subtract mantissas with borrow |
|
232 asm("sbb edx, edi"); // |
|
233 asm("jnc short subfp2"); // if no borrow, sign is correct |
|
234 asm("xor cl, 1"); // else change sign of result |
|
235 asm("shr ch, 1"); // change rounding back to rounded-down |
|
236 asm("not eax"); // negate rounding word |
|
237 asm("not ebx"); // and mantissa |
|
238 asm("not edx"); // |
|
239 asm("add eax,1"); // two's complement negation |
|
240 asm("adc ebx,0"); // |
|
241 asm("adc edx,0"); // |
|
242 asm("subfp2:"); |
|
243 asm("jnz short subfp3"); // branch if edx non-zero at this point |
|
244 asm("mov edx, ebx"); // else shift ebx into edx |
|
245 asm("or edx, edx"); // |
|
246 asm("jz short subfp4"); // if still zero, branch |
|
247 asm("mov ebx, eax"); // else shift rounding word into ebx |
|
248 asm("xor eax, eax"); // and zero rounding word |
|
249 asm("sub ecx, 0x200000"); // decrease exponent by 32 due to shift |
|
250 asm("jnc short subfp3"); // if no borrow, carry on |
|
251 asm("jmp short subfpundflw"); // if borrow here, underflow |
|
252 asm("subfp4:"); |
|
253 asm("mov edx, eax"); // move rounding word into edx |
|
254 asm("or edx, edx"); // is edx still zero ? |
|
255 asm("jz short subfp0"); // if so, result is precisely zero |
|
256 asm("xor ebx, ebx"); // else zero ebx and rounding word |
|
257 asm("xor eax, eax"); // |
|
258 asm("sub ecx, 0x400000"); // and decrease exponent by 64 due to shift |
|
259 asm("jc short subfpundflw"); // if borrow, underflow |
|
260 asm("subfp3:"); |
|
261 asm("mov edi, ecx"); // preserve sign and exponent |
|
262 asm("bsr ecx, edx"); // position of most significant 1 into ecx |
|
263 asm("neg ecx"); // |
|
264 asm("add ecx, 31"); // cl = 31-position of MS 1 = number of shifts to normalise |
|
265 asm("shld edx, ebx, cl"); // shift edx:ebx:eax left by cl bits |
|
266 asm("shld ebx, eax, cl"); // |
|
267 asm("shl eax, cl"); // |
|
268 asm("mov ebp, ecx"); // bit count into ebp for subtraction |
|
269 asm("shl ebp, 16"); // shift left by 16 to align with exponent |
|
270 asm("mov ecx, edi"); // exponent, sign, rounding flags back into ecx |
|
271 asm("sub ecx, ebp"); // subtract shift count from exponent |
|
272 asm("jc short subfpundflw"); // if borrow, underflow |
|
273 asm("cmp ecx, 0x10000"); // check if exponent 0 |
|
274 asm("jnc roundfp"); // if not, jump to round result, else underflow |
|
275 |
|
276 // come here if underflow |
|
277 asm("subfpundflw:"); |
|
278 asm("and ecx, 1"); // set exponent to zero, leave sign |
|
279 asm("xor edx, edx"); |
|
280 asm("xor ebx, ebx"); |
|
281 asm("mov eax, -10"); // return KErrUnderflow |
|
282 asm("ret"); |
|
283 |
|
284 // come here to return zero result |
|
285 asm("subfp0:"); |
|
286 asm("xor ecx, ecx"); // set exponent to zero, positive sign |
|
287 asm("xor edx, edx"); |
|
288 asm("xor ebx, ebx"); |
|
289 asm("addfp0snzd:"); |
|
290 asm("xor eax, eax"); // return KErrNone |
|
291 asm("ret"); |
|
292 |
|
293 // come here if source=0 - eax=source exponent/sign |
|
294 asm("addfp0s:"); |
|
295 asm("cmp ecx, 0x10000"); // check if dest=0 |
|
296 asm("jnc addfp0snzd"); // if not, return dest unaltered |
|
297 asm("and ecx, eax"); // else both zero, result negative iff both zeros negative |
|
298 asm("and ecx, 1"); |
|
299 asm("xor eax, eax"); // return KErrNone |
|
300 asm("ret"); |
|
301 |
|
302 // come here if dest=0, source nonzero |
|
303 asm("addfp0d:"); |
|
304 asm("mov ebx, [esi]"); // return source unaltered |
|
305 asm("mov edx, [esi+4]"); |
|
306 asm("mov ecx, [esi+8]"); |
|
307 asm("xor eax, eax"); // return KErrNone |
|
308 asm("ret"); |
|
309 |
|
310 // come here if dest=NaN or infinity |
|
311 asm("addfpsd:"); |
|
312 asm("cmp edx, 0x80000000"); // check for infinity |
|
313 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN |
|
314 asm("test ebx, ebx"); |
|
315 _ASM_jn(e,TRealXBinOpNaN) |
|
316 asm("mov eax, [esi+8]"); // eax=second operand exponent |
|
317 asm("cmp eax, 0xFFFF0000"); // check second operand for NaN or infinity |
|
318 asm("jae short addfpsd1"); // branch if NaN or infinity |
|
319 asm("addfpsd2:"); |
|
320 asm("mov eax, -9"); // else return dest unaltered [infinity] and KErrOverflow |
|
321 asm("ret"); |
|
322 asm("addfpsd1:"); |
|
323 asm("mov ebp, [esi]"); // source mantissa into edi:ebp |
|
324 asm("mov edi, [esi+4]"); |
|
325 asm("cmp edi, 0x80000000"); // check for infinity |
|
326 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN |
|
327 asm("test ebp, ebp"); |
|
328 _ASM_jn(e,TRealXBinOpNaN) |
|
329 asm("xor al, cl"); // both operands are infinity - check signs |
|
330 asm("test al, 1"); |
|
331 asm("jz short addfpsd2"); // if both the same, return KErrOverflow |
|
332 asm("jmp %a0": : "i"(&TRealXRealIndefinite)); // else return 'real indefinite' |
|
333 |
|
334 // come here if source=NaN or infinity, dest finite |
|
335 asm("addfpss:"); |
|
336 asm("mov ebp, [esi]"); // source mantissa into edi:ebp |
|
337 asm("mov edi, [esi+4]"); |
|
338 asm("cmp edi, 0x80000000"); // check for infinity |
|
339 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN |
|
340 asm("test ebp, ebp"); |
|
341 _ASM_jn(e,TRealXBinOpNaN) |
|
342 asm("mov ecx, eax"); // if source=infinity, return source unaltered |
|
343 asm("mov edx, edi"); |
|
344 asm("mov ebx, ebp"); |
|
345 asm("mov eax, -9"); // return KErrOverflow |
|
346 asm("ret"); |
|
347 } |
|
348 |
|
349 // Subtract TRealX at [esi] - ecx,edx:ebx |
|
350 // Result in ecx,edx:ebx |
|
351 // Error code in eax |
|
352 LOCAL_C __NAKED__ void TRealXSubtract() |
|
353 { |
|
354 asm("xor cl, 1"); // negate subtrahend |
|
355 asm("jmp %a0": :"i"(&TRealXAdd)); |
|
356 } |
|
357 |
|
358 // Multiply TRealX at [esi] * ecx,edx:ebx |
|
359 // Result in ecx,edx:ebx |
|
360 // Error code in eax |
|
361 LOCAL_C __NAKED__ void TRealXMultiply() |
|
362 { |
|
363 asm("xor ch, ch"); // clear rounding flags |
|
364 asm("mov eax, [esi+8]"); // fetch sign/exponent of source |
|
365 asm("xor cl, al"); // xor signs |
|
366 asm("cmp ecx, 0xFFFF0000"); // check if dest=NaN or infinity |
|
367 asm("jnc mulfpsd"); // branch if it is |
|
368 asm("cmp eax, 0xFFFF0000"); // check if source=NaN or infinity |
|
369 asm("jnc mulfpss"); // branch if it is |
|
370 asm("cmp eax, 0x10000"); // check if source=0 |
|
371 asm("jc mulfp0"); // branch if it is |
|
372 asm("cmp ecx, 0x10000"); // check if dest=0 |
|
373 asm("jc mulfp0"); // branch if it is |
|
374 asm("push ecx"); // save result sign |
|
375 asm("shr ecx, 16"); // dest exponent into cx |
|
376 asm("shr eax, 16"); // source exponent into ax |
|
377 asm("add eax, ecx"); // add exponents |
|
378 asm("sub eax, 0x7FFE"); // eax now contains result exponent |
|
379 asm("push eax"); // save it |
|
380 asm("mov edi, edx"); // save dest mantissa high |
|
381 asm("mov eax, ebx"); // dest mantissa low -> eax |
|
382 asm("mul dword ptr [esi]"); // dest mantissa low * source mantissa low -> edx:eax |
|
383 asm("xchg ebx, eax"); // result dword 0 -> ebx, dest mant low -> eax |
|
384 asm("mov ebp, edx"); // result dword 1 -> ebp |
|
385 asm("mul dword ptr [esi+4]"); // dest mant low * src mant high -> edx:eax |
|
386 asm("add ebp, eax"); // add in partial product to dwords 1 and 2 |
|
387 asm("adc edx, 0"); // |
|
388 asm("mov ecx, edx"); // result dword 2 -> ecx |
|
389 asm("mov eax, edi"); // dest mant high -> eax |
|
390 asm("mul dword ptr [esi+4]"); // dest mant high * src mant high -> edx:eax |
|
391 asm("add ecx, eax"); // add in partial product to dwords 2, 3 |
|
392 asm("adc edx, 0"); // |
|
393 asm("mov eax, edi"); // dest mant high -> eax |
|
394 asm("mov edi, edx"); // result dword 3 -> edi |
|
395 asm("mul dword ptr [esi]"); // dest mant high * src mant low -> edx:eax |
|
396 asm("add ebp, eax"); // add in partial product to dwords 1, 2 |
|
397 asm("adc ecx, edx"); // |
|
398 asm("adc edi, 0"); // 128-bit mantissa product is now in edi:ecx:ebp:ebx |
|
399 asm("mov edx, edi"); // top 64 bits into edx:ebx |
|
400 asm("mov edi, ebx"); |
|
401 asm("mov ebx, ecx"); // bottom 64 bits now in ebp:edi |
|
402 asm("pop ecx"); // recover exponent |
|
403 asm("js short mulfp1"); // skip if mantissa normalised |
|
404 asm("add edi, edi"); // else shift left [only one shift will be needed] |
|
405 asm("adc ebp, ebp"); |
|
406 asm("adc ebx, ebx"); |
|
407 asm("adc edx, edx"); |
|
408 asm("dec ecx"); // and decrement exponent |
|
409 asm("mulfp1:"); |
|
410 asm("cmp ebp, 0x80000000"); // compare bottom 64 bits with 80000000 00000000 for rounding |
|
411 asm("ja short mulfp2"); // branch to round up |
|
412 asm("jb short mulfp3"); // branch to round down |
|
413 asm("test edi, edi"); |
|
414 asm("jnz short mulfp2"); // branch to round up |
|
415 asm("test bl, 1"); // if exactly half-way, test LSB of result mantissa |
|
416 asm("jz short mulfp4"); // if LSB=0, round down [round to even] |
|
417 asm("mulfp2:"); |
|
418 asm("add ebx, 1"); // round up - increment mantissa |
|
419 asm("adc edx, 0"); |
|
420 asm("jnc short mulfp2a"); |
|
421 asm("rcr edx, 1"); |
|
422 asm("inc ecx"); |
|
423 asm("mulfp2a:"); |
|
424 asm("mov al, 2"); // set rounded-up flag |
|
425 asm("jmp short mulfp5"); |
|
426 asm("mulfp3:"); // round down |
|
427 asm("xor al, al"); // clear rounding flags |
|
428 asm("or ebp, edi"); // check for exact result |
|
429 asm("jz short mulfp5"); // skip if exact |
|
430 asm("mulfp4:"); // come here to round down when we know result inexact |
|
431 asm("mov al, 1"); // else set rounded-down flag |
|
432 asm("mulfp5:"); // final mantissa now in edx:ebx, exponent in ecx |
|
433 asm("cmp ecx, 0xFFFF"); // check for overflow |
|
434 asm("jge short mulfp6"); // branch if overflow |
|
435 asm("cmp ecx, 0"); // check for underflow |
|
436 asm("jle short mulfp7"); // branch if underflow |
|
437 asm("shl ecx, 16"); // else exponent up to top end of ecx |
|
438 asm("mov ch, al"); // rounding flags into ch |
|
439 asm("pop eax"); // recover result sign |
|
440 asm("mov cl, al"); // into cl |
|
441 asm("xor eax, eax"); // return KErrNone |
|
442 asm("ret"); |
|
443 |
|
444 // come here if overflow |
|
445 asm("mulfp6:"); |
|
446 asm("pop eax"); // recover result sign |
|
447 asm("mov ecx, 0xFFFF0000"); // exponent=FFFF |
|
448 asm("mov cl, al"); // sign into cl |
|
449 asm("mov edx, 0x80000000"); // set mantissa to 80000000 00000000 for infinity |
|
450 asm("xor ebx, ebx"); |
|
451 asm("mov eax, -9"); // return KErrOverflow |
|
452 asm("ret"); |
|
453 |
|
454 // come here if underflow |
|
455 asm("mulfp7:"); |
|
456 asm("pop eax"); // recover result sign |
|
457 asm("xor ecx, ecx"); // exponent=0 |
|
458 asm("mov cl, al"); // sign into cl |
|
459 asm("xor edx, edx"); |
|
460 asm("xor ebx, ebx"); |
|
461 asm("mov eax, -10"); // return KErrUnderflow |
|
462 asm("ret"); |
|
463 |
|
464 // come here if either operand zero |
|
465 asm("mulfp0:"); |
|
466 asm("and ecx, 1"); // set exponent=0, keep sign |
|
467 asm("xor edx, edx"); |
|
468 asm("xor ebx, ebx"); |
|
469 asm("xor eax, eax"); // return KErrNone |
|
470 asm("ret"); |
|
471 |
|
472 // come here if destination operand NaN or infinity |
|
473 asm("mulfpsd:"); |
|
474 asm("cmp edx, 0x80000000"); // check for infinity |
|
475 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN |
|
476 asm("test ebx, ebx"); |
|
477 _ASM_jn(e,TRealXBinOpNaN) |
|
478 asm("cmp eax, 0xFFFF0000"); // check second operand for NaN or infinity |
|
479 asm("jae short mulfpsd1"); // branch if NaN or infinity |
|
480 asm("cmp eax, 0x10000"); // check if second operand zero |
|
481 _ASM_j(c,TRealXRealIndefinite) // if so, return 'real indefinite' |
|
482 asm("mov eax, -9"); // else return dest [infinity] with xor sign and KErrOverflow |
|
483 asm("ret"); |
|
484 asm("mulfpsd1:"); |
|
485 asm("mov ebp, [esi]"); // source mantissa into edi:ebp |
|
486 asm("mov edi, [esi+4]"); |
|
487 asm("cmp edi, 0x80000000"); // check for infinity |
|
488 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN |
|
489 asm("test ebp, ebp"); |
|
490 _ASM_jn(e,TRealXBinOpNaN) |
|
491 asm("mov eax, -9"); // both operands infinity - return infinity with xor sign |
|
492 asm("ret"); // and KErrOverflow |
|
493 |
|
494 // come here if source operand NaN or infinity, destination finite |
|
495 asm("mulfpss:"); |
|
496 asm("mov ebp, [esi]"); // source mantissa into edi:ebp |
|
497 asm("mov edi, [esi+4]"); |
|
498 asm("cmp edi, 0x80000000"); // check for infinity |
|
499 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN |
|
500 asm("test ebp, ebp"); |
|
501 _ASM_jn(e,TRealXBinOpNaN) |
|
502 asm("cmp ecx, 0x10000"); // source=infinity, check if dest=0 |
|
503 _ASM_j(c,TRealXRealIndefinite) // if so, return 'real indefinite' |
|
504 asm("or ecx, 0xFFFF0000"); // set exp=FFFF, leave xor sign in cl |
|
505 asm("mov edx, edi"); // set mantissa for infinity |
|
506 asm("mov ebx, ebp"); |
|
507 asm("mov eax, -9"); // return KErrOverflow |
|
508 asm("ret"); |
|
509 } |
|
510 |
|
511 // Divide 96-bit unsigned dividend EDX:EAX:0 by 64-bit unsigned divisor ECX:EBX |
|
512 // Assume ECX bit 31 = 1, ie 2^63 <= divisor < 2^64 |
|
513 // Assume the quotient fits in 32 bits |
|
514 // Return 32 bit quotient in EDI |
|
515 // Return 64 bit remainder in EBP:ESI |
|
516 LOCAL_C __NAKED__ void LongDivide(void) |
|
517 { |
|
518 asm("push edx"); // save dividend |
|
519 asm("push eax"); // |
|
520 asm("cmp edx, ecx"); // check if truncation of divisor will overflow DIV instruction |
|
521 asm("jb short longdiv1"); // skip if not |
|
522 asm("xor eax, eax"); // else return quotient of 0xFFFFFFFF |
|
523 asm("dec eax"); // |
|
524 asm("jmp short longdiv2"); // |
|
525 asm("longdiv1:"); |
|
526 asm("div ecx"); // divide EDX:EAX by ECX to give approximate quotient in EAX |
|
527 asm("longdiv2:"); |
|
528 asm("mov edi, eax"); // save approx quotient |
|
529 asm("mul ebx"); // multiply approx quotient by full divisor ECX:EBX |
|
530 asm("mov esi, eax"); // first partial product into EBP:ESI |
|
531 asm("mov ebp, edx"); // |
|
532 asm("mov eax, edi"); // approx quotient back into eax |
|
533 asm("mul ecx"); // upper partial product now in EDX:EAX |
|
534 asm("add eax, ebp"); // add to form 96-bit product in EDX:EAX:ESI |
|
535 asm("adc edx, 0"); // |
|
536 asm("neg esi"); // remainder = dividend - approx quotient * divisor |
|
537 asm("mov ebp, [esp]"); // fetch dividend bits 32-63 |
|
538 asm("sbb ebp, eax"); // |
|
539 asm("mov eax, [esp+4]"); // fetch dividend bits 64-95 |
|
540 asm("sbb eax, edx"); // remainder is now in EAX:EBP:ESI |
|
541 asm("jns short longdiv4"); // if remainder positive, quotient is correct, so exit |
|
542 asm("longdiv3:"); |
|
543 asm("dec edi"); // else quotient is too big, so decrement it |
|
544 asm("add esi, ebx"); // and add divisor to remainder |
|
545 asm("adc ebp, ecx"); // |
|
546 asm("adc eax, 0"); // |
|
547 asm("js short longdiv3"); // if still negative, repeat [requires <4 iterations] |
|
548 asm("longdiv4:"); |
|
549 asm("add esp, 8"); // remove dividend from stack |
|
550 asm("ret"); // return with quotient in EDI, remainder in EBP:ESI |
|
551 } |
|
552 |
|
553 // Divide TRealX at [esi] / ecx,edx:ebx |
|
554 // Result in ecx,edx:ebx |
|
555 // Error code in eax |
|
556 LOCAL_C __NAKED__ void TRealXDivide(void) |
|
557 { |
|
558 asm("xor ch, ch"); // clear rounding flags |
|
559 asm("mov eax, [esi+8]"); // fetch sign/exponent of dividend |
|
560 asm("xor cl, al"); // xor signs |
|
561 asm("cmp eax, 0xFFFF0000"); // check if dividend=NaN or infinity |
|
562 asm("jnc divfpss"); // branch if it is |
|
563 asm("cmp ecx, 0xFFFF0000"); // check if divisor=NaN or infinity |
|
564 asm("jnc divfpsd"); // branch if it is |
|
565 asm("cmp ecx, 0x10000"); // check if divisor=0 |
|
566 asm("jc divfpdv0"); // branch if it is |
|
567 asm("cmp eax, 0x10000"); // check if dividend=0 |
|
568 asm("jc divfpdd0"); // branch if it is |
|
569 asm("push esi"); // save pointer to dividend |
|
570 asm("push ecx"); // save result sign |
|
571 asm("shr ecx, 16"); // divisor exponent into cx |
|
572 asm("shr eax, 16"); // dividend exponent into ax |
|
573 asm("sub eax, ecx"); // subtract exponents |
|
574 asm("add eax, 0x7FFE"); // eax now contains result exponent |
|
575 asm("push eax"); // save it |
|
576 asm("mov ecx, edx"); // divisor mantissa into ecx:ebx |
|
577 asm("mov edx, [esi+4]"); // dividend mantissa into edx:eax |
|
578 asm("mov eax, [esi]"); |
|
579 asm("xor edi, edi"); // clear edi initially |
|
580 asm("cmp edx, ecx"); // compare EDX:EAX with ECX:EBX |
|
581 asm("jb short divfp1"); // if EDX:EAX < ECX:EBX, leave everything as is |
|
582 asm("ja short divfp2"); // |
|
583 asm("cmp eax, ebx"); // if EDX=ECX, then compare ls dwords |
|
584 asm("jb short divfp1"); // if dividend mant < divisor mant, leave everything as is |
|
585 asm("divfp2:"); |
|
586 asm("sub eax, ebx"); // else dividend mant -= divisor mant |
|
587 asm("sbb edx, ecx"); // |
|
588 asm("inc edi"); // and EDI=1 [bit 0 of EDI is the integer part of the result] |
|
589 asm("inc dword ptr [esp]"); // also increment result exponent |
|
590 asm("divfp1:"); |
|
591 asm("push edi"); // save top bit of result |
|
592 asm("call %a0": : "i"(&LongDivide)); // divide EDX:EAX:0 by ECX:EBX to give next 32 bits of result in EDI |
|
593 asm("push edi"); // save next 32 bits of result |
|
594 asm("mov edx, ebp"); // remainder from EBP:ESI into EDX:EAX |
|
595 asm("mov eax, esi"); // |
|
596 asm("call %a0": : "i"(&LongDivide)); // divide EDX:EAX:0 by ECX:EBX to give next 32 bits of result in EDI |
|
597 asm("test byte ptr [esp+4], 1"); // test integer bit of result |
|
598 asm("jnz short divfp4"); // if set, no need to calculate another bit |
|
599 asm("xor eax, eax"); // |
|
600 asm("add esi, esi"); // 2*remainder into EAX:EBP:ESI |
|
601 asm("adc ebp, ebp"); // |
|
602 asm("adc eax, eax"); // |
|
603 asm("sub esi, ebx"); // subtract divisor to generate final quotient bit |
|
604 asm("sbb ebp, ecx"); // |
|
605 asm("sbb eax, 0"); // |
|
606 asm("jnc short divfp3"); // skip if no borrow - in this case eax=0 |
|
607 asm("add esi, ebx"); // if borrow add back - final remainder now in EBP:ESI |
|
608 asm("adc ebp, ecx"); // |
|
609 asm("adc eax, 0"); // eax will be zero after this and carry will be set |
|
610 asm("divfp3:"); |
|
611 asm("cmc"); // final bit = 1-C |
|
612 asm("rcr eax, 1"); // shift it into eax bit 31 |
|
613 asm("mov ebx, edi"); // result into EDX:EBX:EAX, remainder in EBP:ESI |
|
614 asm("pop edx"); |
|
615 asm("add esp, 4"); // discard integer bit [zero] |
|
616 asm("jmp short divfp5"); // branch to round |
|
617 |
|
618 asm("divfp4:"); // integer bit was set |
|
619 asm("mov ebx, edi"); // result into EDX:EBX:EAX |
|
620 asm("pop edx"); // |
|
621 asm("pop eax"); // integer part of result into eax [=1] |
|
622 asm("stc"); // shift a 1 into top end of mantissa |
|
623 asm("rcr edx,1"); // |
|
624 asm("rcr ebx,1"); // |
|
625 asm("rcr eax,1"); // bottom bit into eax bit 31 |
|
626 |
|
627 // when we get to here we have 65 bits of quotient mantissa in |
|
628 // EDX:EBX:EAX (bottom bit in eax bit 31) |
|
629 // and the remainder is in EBP:ESI |
|
630 asm("divfp5:"); |
|
631 asm("pop ecx"); // recover result exponent |
|
632 asm("add eax, eax"); // test rounding bit |
|
633 asm("jnc short divfp6"); // branch to round down |
|
634 asm("or ebp, esi"); // test remainder to see if we are exactly half-way |
|
635 asm("jnz short divfp7"); // if not, round up |
|
636 asm("test bl, 1"); // exactly halfway - test LSB of mantissa |
|
637 asm("jz short divfp8"); // round down if LSB=0 [round to even] |
|
638 asm("divfp7:"); |
|
639 asm("add ebx, 1"); // round up - increment mantissa |
|
640 asm("adc edx, 0"); |
|
641 asm("jnc short divfp7a"); |
|
642 asm("rcr edx, 1"); // if carry, shift 1 into mantissa MSB |
|
643 asm("inc ecx"); // and increment exponent |
|
644 asm("divfp7a:"); |
|
645 asm("mov al, 2"); // set rounded-up flag |
|
646 asm("jmp short divfp9"); |
|
647 asm("divfp6:"); |
|
648 asm("xor al, al"); // round down - first clear rounding flags |
|
649 asm("or ebp, esi"); // test if result exact |
|
650 asm("jz short divfp9"); // skip if exact |
|
651 asm("divfp8:"); // come here to round down when we know result is inexact |
|
652 asm("mov al, 1"); // set rounded-down flag |
|
653 asm("divfp9:"); // final mantissa now in edx:ebx, exponent in ecx |
|
654 asm("cmp ecx, 0xFFFF"); // check for overflow |
|
655 asm("jge short divfp10"); // branch if overflow |
|
656 asm("cmp ecx, 0"); // check for underflow |
|
657 asm("jle short divfp11"); // branch if underflow |
|
658 asm("shl ecx, 16"); // else exponent up to top end of ecx |
|
659 asm("mov ch, al"); // rounding flags into ch |
|
660 asm("pop eax"); // recover result sign |
|
661 asm("mov cl, al"); // into cl |
|
662 asm("pop esi"); // recover dividend pointer |
|
663 asm("xor eax, eax"); // return KErrNone |
|
664 asm("ret"); |
|
665 |
|
666 // come here if overflow |
|
667 asm("divfp10:"); |
|
668 asm("pop eax"); // recover result sign |
|
669 asm("mov ecx, 0xFFFF0000"); // exponent=FFFF |
|
670 asm("mov cl, al"); // sign into cl |
|
671 asm("mov edx, 0x80000000"); // set mantissa to 80000000 00000000 for infinity |
|
672 asm("xor ebx, ebx"); |
|
673 asm("mov eax, -9"); // return KErrOverflow |
|
674 asm("pop esi"); // recover dividend pointer |
|
675 asm("ret"); |
|
676 |
|
677 // come here if underflow |
|
678 asm("divfp11:"); |
|
679 asm("pop eax"); // recover result sign |
|
680 asm("xor ecx, ecx"); // exponent=0 |
|
681 asm("mov cl, al"); // sign into cl |
|
682 asm("xor edx, edx"); |
|
683 asm("xor ebx, ebx"); |
|
684 asm("mov eax, -10"); // return KErrUnderflow |
|
685 asm("pop esi"); // recover dividend pointer |
|
686 asm("ret"); |
|
687 |
|
688 |
|
689 // come here if divisor=0, dividend finite |
|
690 asm("divfpdv0:"); |
|
691 asm("cmp eax, 0x10000"); // check if dividend also zero |
|
692 _ASM_j(c,TRealXRealIndefinite) // if so, return 'real indefinite' |
|
693 asm("or ecx, 0xFFFF0000"); // else set exponent=FFFF, leave xor sign in cl |
|
694 asm("mov edx, 0x80000000"); // set mantissa for infinity |
|
695 asm("xor ebx, ebx"); |
|
696 asm("mov eax, -41"); // return KErrDivideByZero |
|
697 asm("ret"); |
|
698 |
|
699 // come here if dividend=0, divisor finite and nonzero |
|
700 asm("divfpdd0:"); |
|
701 asm("and ecx, 1"); // exponent=0, leave xor sign in cl |
|
702 asm("xor eax, eax"); // return KErrNone |
|
703 asm("ret"); |
|
704 |
|
705 // come here if dividend is a NaN or infinity |
|
706 asm("divfpss:"); |
|
707 asm("mov ebp, [esi]"); // dividend mantissa into edi:ebp |
|
708 asm("mov edi, [esi+4]"); |
|
709 asm("cmp edi, 0x80000000"); // check for infinity |
|
710 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN |
|
711 asm("test ebp, ebp"); |
|
712 _ASM_jn(e,TRealXBinOpNaN) |
|
713 asm("cmp ecx, 0xFFFF0000"); // check divisor for NaN or infinity |
|
714 asm("jae short divfpss1"); // branch if NaN or infinity |
|
715 asm("or ecx, 0xFFFF0000"); // infinity/finite - return infinity with xor sign |
|
716 asm("mov edx, 0x80000000"); |
|
717 asm("xor ebx, ebx"); |
|
718 asm("mov eax, -9"); // return KErrOverflow |
|
719 asm("ret"); |
|
720 asm("divfpss1:"); |
|
721 asm("cmp edx, 0x80000000"); // check for infinity |
|
722 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN |
|
723 asm("test ebx, ebx"); |
|
724 _ASM_jn(e,TRealXBinOpNaN) |
|
725 asm("jmp %a0": : "i"(&TRealXRealIndefinite)); // if both operands infinite, return 'real indefinite' |
|
726 |
|
727 // come here if divisor is a NaN or infinity, dividend finite |
|
728 asm("divfpsd:"); |
|
729 asm("cmp edx, 0x80000000"); // check for infinity |
|
730 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN |
|
731 asm("test ebx, ebx"); |
|
732 _ASM_jn(e,TRealXBinOpNaN) |
|
733 asm("and ecx, 1"); // dividend is finite, divisor=infinity, so return 0 with xor sign |
|
734 asm("xor edx, edx"); |
|
735 asm("xor ebx, ebx"); |
|
736 asm("xor eax, eax"); // return KErrNone |
|
737 asm("ret"); |
|
738 } |
|
739 |
|
740 // TRealX modulo - dividend at [esi], divisor in ecx,edx:ebx |
|
741 // Result in ecx,edx:ebx |
|
742 // Error code in eax |
|
743 LOCAL_C __NAKED__ void TRealXModulo(void) |
|
744 { |
|
745 asm("mov eax, [esi+8]"); // fetch sign/exponent of dividend |
|
746 asm("mov cl, al"); // result sign=dividend sign |
|
747 asm("xor ch, ch"); // clear rounding flags |
|
748 asm("cmp eax, 0xFFFF0000"); // check if dividend=NaN or infinity |
|
749 asm("jnc short modfpss"); // branch if it is |
|
750 asm("cmp ecx, 0xFFFF0000"); // check if divisor=NaN or infinity |
|
751 asm("jnc short modfpsd"); // branch if it is |
|
752 asm("cmp ecx, 0x10000"); // check if divisor=0 |
|
753 _ASM_j(c,TRealXRealIndefinite) // if so, return 'real indefinite' |
|
754 asm("shr eax, 16"); // ax=dividend exponent |
|
755 asm("ror ecx, 16"); // cx=divisor exponent |
|
756 asm("sub ax, cx"); // ax=dividend exponent-divisor exponent |
|
757 asm("jc short modfpdd0"); // if dividend exponent is smaller, return dividend |
|
758 asm("cmp ax, 64"); // check if exponents differ by >= 64 bits |
|
759 asm("jnc short modfplp"); // if so, underflow |
|
760 asm("mov ah, 0"); // ah bit 0 acts as 65th accumulator bit |
|
761 asm("mov ebp, [esi]"); // edi:ebp=dividend mantissa |
|
762 asm("mov edi, [esi+4]"); // |
|
763 asm("jmp short modfp2"); // skip left shift on first iteration |
|
764 asm("modfp1:"); |
|
765 asm("add ebp, ebp"); // shift accumulator left [65 bits] |
|
766 asm("adc edi, edi"); |
|
767 asm("adc ah, ah"); |
|
768 asm("modfp2:"); |
|
769 asm("sub ebp, ebx"); // subtract divisor from dividend |
|
770 asm("sbb edi, edx"); |
|
771 asm("sbb ah, 0"); |
|
772 asm("jnc short modfp3"); // skip if no borrow |
|
773 asm("add ebp, ebx"); // else add back |
|
774 asm("adc edi, edx"); |
|
775 asm("adc ah, 0"); |
|
776 asm("modfp3:"); |
|
777 asm("dec al"); // any more bits to do? |
|
778 asm("jns short modfp1"); // loop if there are |
|
779 asm("mov edx, edi"); // result mantissa [not yet normalised] into edx:ebx |
|
780 asm("mov ebx, ebp"); |
|
781 asm("or edi, ebx"); // check for zero |
|
782 asm("jz short modfp0"); // jump if result zero |
|
783 asm("or edx, edx"); // check if ms dword zero |
|
784 asm("jnz short modfp4"); |
|
785 asm("mov edx, ebx"); // if so, shift left by 32 |
|
786 asm("xor ebx, ebx"); |
|
787 asm("sub cx, 32"); // and decrement exponent by 32 |
|
788 asm("jbe short modfpund"); // if borrow or exponent zero, underflow |
|
789 asm("modfp4:"); |
|
790 asm("mov edi, ecx"); // preserve sign and exponent |
|
791 asm("bsr ecx, edx"); // position of most significant 1 into ecx |
|
792 asm("neg ecx"); // |
|
793 asm("add ecx, 31"); // cl = 31-position of MS 1 = number of shifts to normalise |
|
794 asm("shld edx, ebx, cl"); // shift edx:ebx left by cl bits |
|
795 asm("shl ebx, cl"); // |
|
796 asm("mov ebp, ecx"); // bit count into ebp for subtraction |
|
797 asm("mov ecx, edi"); // exponent & sign back into ecx |
|
798 asm("sub cx, bp"); // subtract shift count from exponent |
|
799 asm("jbe short modfpund"); // if borrow or exponent 0, underflow |
|
800 asm("rol ecx, 16"); // else ecx=exponent:sign |
|
801 asm("xor eax, eax"); // normal exit, result in ecx,edx:ebx |
|
802 asm("ret"); |
|
803 |
|
804 // dividend=NaN or infinity |
|
805 asm("modfpss:"); |
|
806 asm("mov ebp, [esi]"); // dividend mantissa into edi:ebp |
|
807 asm("mov edi, [esi+4]"); |
|
808 asm("cmp edi, 0x80000000"); // check for infinity |
|
809 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN |
|
810 asm("test ebp, ebp"); |
|
811 _ASM_jn(e,TRealXBinOpNaN) |
|
812 asm("cmp ecx, 0xFFFF0000"); // check divisor for NaN or infinity |
|
813 _ASM_j(b,TRealXRealIndefinite) // infinity%finite - return 'real indefinite' |
|
814 asm("cmp edx, 0x80000000"); // check for divisor=infinity |
|
815 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN |
|
816 asm("test ebx, ebx"); |
|
817 _ASM_jn(e,TRealXBinOpNaN) |
|
818 asm("jmp %a0": : "i"(&TRealXRealIndefinite)); // if both operands infinite, return 'real indefinite' |
|
819 |
|
820 // divisor=NaN or infinity, dividend finite |
|
821 asm("modfpsd:"); |
|
822 asm("cmp edx, 0x80000000"); // check for infinity |
|
823 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN |
|
824 asm("test ebx, ebx"); |
|
825 _ASM_jn(e,TRealXBinOpNaN) |
|
826 // finite%infinity - return dividend unaltered |
|
827 |
|
828 asm("modfpdd0:"); |
|
829 asm("mov ebx, [esi]"); // normal exit, return dividend unaltered |
|
830 asm("mov edx, [esi+4]"); |
|
831 asm("mov ecx, [esi+8]"); |
|
832 asm("xor eax, eax"); |
|
833 asm("ret"); |
|
834 |
|
835 asm("modfp0:"); |
|
836 asm("shr ecx, 16"); // normal exit, result 0 |
|
837 asm("xor eax, eax"); |
|
838 asm("ret"); |
|
839 |
|
840 asm("modfpund:"); |
|
841 asm("shr ecx, 16"); // underflow, result 0 |
|
842 asm("mov eax, -10"); // return KErrUnderflow |
|
843 asm("ret"); |
|
844 |
|
845 asm("modfplp:"); |
|
846 asm("shr ecx, 16"); // loss of precision, result 0 |
|
847 asm("mov eax, -7"); // return KErrTotalLossOfPrecision |
|
848 asm("ret"); |
|
849 } |
|
850 |
|
851 |
|
852 |
|
853 |
|
854 __NAKED__ EXPORT_C TRealX::TRealX() |
|
855 /** |
|
856 Constructs a default extended precision object. |
|
857 |
|
858 This sets the value to zero. |
|
859 */ |
|
860 { |
|
861 THISCALL_PROLOG0() |
|
862 asm("xor eax, eax"); |
|
863 asm("mov [ecx], eax"); // set value to zero |
|
864 asm("mov [ecx+4], eax"); |
|
865 asm("mov [ecx+8], eax"); |
|
866 asm("mov eax, ecx"); // must return this |
|
867 THISCALL_EPILOG0() |
|
868 } |
|
869 |
|
870 |
|
871 |
|
872 |
|
873 __NAKED__ EXPORT_C TRealX::TRealX(TUint /*aExp*/, TUint /*aMantHi*/, TUint /*aMantLo*/) |
|
874 /** |
|
875 Constructs an extended precision object from an explicit exponent and |
|
876 a 64 bit mantissa. |
|
877 |
|
878 @param aExp The exponent |
|
879 @param aMantHi The high order 32 bits of the 64 bit mantissa |
|
880 @param aMantLo The low order 32 bits of the 64 bit mantissa |
|
881 */ |
|
882 { |
|
883 THISCALL_PROLOG3() |
|
884 asm("mov eax, [esp+4]"); // eax=aExp |
|
885 asm("mov [ecx+8], eax"); |
|
886 asm("mov eax, [esp+8]"); // eax=aMantHi |
|
887 asm("mov [ecx+4], eax"); |
|
888 asm("mov eax, [esp+12]"); // eax=aMantLo |
|
889 asm("mov [ecx], eax"); |
|
890 asm("mov eax, ecx"); // must return this |
|
891 THISCALL_EPILOG3() |
|
892 } |
|
893 |
|
894 |
|
895 __NAKED__ EXPORT_C TInt TRealX::Set(TInt /*aInt*/) |
|
896 /** |
|
897 Gives this extended precision object a new value taken |
|
898 from a signed integer. |
|
899 |
|
900 @param aInt The signed integer value. |
|
901 |
|
902 @return KErrNone, always. |
|
903 */ |
|
904 { |
|
905 THISCALL_PROLOG1() |
|
906 // on entry ecx=this, [esp+4]=aInt, return code in eax |
|
907 asm("mov edx, [esp+4]"); // edx=aInt |
|
908 asm("or edx, edx"); // test sign/zero |
|
909 asm("mov eax, 0x7FFF"); |
|
910 asm("jz short trealxfromint0_2"); // branch if 0 |
|
911 asm("jns short trealxfromint1_2");// skip if positive |
|
912 asm("neg edx"); // take absolute value |
|
913 asm("add eax, 0x10000"); // sign bit in eax bit 16 |
|
914 asm("trealxfromint1_2:"); |
|
915 asm("push ecx"); // save this |
|
916 asm("bsr ecx, edx"); // bit number of edx MSB into ecx |
|
917 asm("add eax, ecx"); // add to eax to form result exponent |
|
918 asm("neg cl"); |
|
919 asm("add cl, 31"); // 31-bit number = number of shifts to normalise edx |
|
920 asm("shl edx, cl"); // normalise edx |
|
921 asm("pop ecx"); // this back into ecx |
|
922 asm("ror eax, 16"); // sign/exponent into normal positions |
|
923 asm("mov [ecx+4], edx"); // store mantissa high word |
|
924 asm("mov [ecx+8], eax"); // store sign/exponent |
|
925 asm("xor eax, eax"); |
|
926 asm("mov [ecx], eax"); // zero mantissa low word |
|
927 THISCALL_EPILOG1() // return KErrNone |
|
928 asm("trealxfromint0_2:"); |
|
929 asm("mov [ecx], edx"); |
|
930 asm("mov [ecx+4], edx"); // store mantissa high word=0 |
|
931 asm("mov [ecx+8], edx"); // store sign/exponent=0 |
|
932 asm("xor eax, eax"); // return KErrNone |
|
933 THISCALL_EPILOG1() |
|
934 } |
|
935 |
|
936 |
|
937 |
|
938 __NAKED__ EXPORT_C TInt TRealX::Set(TUint /*aInt*/) |
|
939 /** |
|
940 Gives this extended precision object a new value taken from |
|
941 an unsigned integer. |
|
942 |
|
943 @param aInt The unsigned integer value. |
|
944 |
|
945 @return KErrNone, always. |
|
946 */ |
|
947 { |
|
948 THISCALL_PROLOG1() |
|
949 asm("mov edx, [esp+4]"); // edx=aInt |
|
950 asm("mov eax, 0x7FFF"); |
|
951 asm("or edx, edx"); // test for 0 |
|
952 asm("jz short trealxfromuint0_");// branch if 0 |
|
953 asm("push ecx"); // save this |
|
954 asm("bsr ecx, edx"); // bit number of edx MSB into ecx |
|
955 asm("add eax, ecx"); // add to eax to form result exponent |
|
956 asm("neg cl"); |
|
957 asm("add cl, 31"); // 31-bit number = number of shifts to normalise edx |
|
958 asm("shl edx, cl"); // normalise edx |
|
959 asm("pop ecx"); // this back into ecx |
|
960 asm("shl eax, 16"); // exponent into normal position |
|
961 asm("mov [ecx+4], edx"); // store mantissa high word |
|
962 asm("mov [ecx+8], eax"); // store exponent |
|
963 asm("xor eax, eax"); |
|
964 asm("mov [ecx], eax"); // zero mantissa low word |
|
965 THISCALL_EPILOG1() // return KErrNone |
|
966 asm("trealxfromuint0_:"); |
|
967 asm("mov [ecx], edx"); |
|
968 asm("mov [ecx+4], edx"); // store mantissa high word=0 |
|
969 asm("mov [ecx+8], edx"); // store sign/exponent=0 |
|
970 asm("xor eax, eax"); // return KErrNone |
|
971 THISCALL_EPILOG1() |
|
972 } |
|
973 |
|
974 |
|
975 |
|
976 |
|
977 LOCAL_C __NAKED__ void TRealXFromTInt64(void) |
|
978 { |
|
979 // Convert TInt64 in edx:ebx to TRealX in ecx,edx:ebx |
|
980 asm("mov eax, 0x7FFF"); |
|
981 asm("or edx, edx"); // test sign/zero |
|
982 asm("jz short trealxfromtint64a"); // branch if top word zero |
|
983 asm("jns short trealxfromtint64b"); |
|
984 asm("add eax, 0x10000"); // sign bit into eax bit 16 |
|
985 asm("neg edx"); // take absolute value |
|
986 asm("neg ebx"); |
|
987 asm("sbb edx, 0"); |
|
988 asm("jz short trealxfromtint64d"); // branch if top word zero |
|
989 asm("trealxfromtint64b:"); |
|
990 asm("bsr ecx, edx"); // ecx=bit number of edx MSB |
|
991 asm("add eax, ecx"); // add to exponent in eax |
|
992 asm("add eax, 32"); |
|
993 asm("neg cl"); |
|
994 asm("add cl, 31"); // 31-bit number = number of left shifts to normalise |
|
995 asm("shld edx, ebx, cl"); // shift left to normalise edx:ebx |
|
996 asm("shl ebx, cl"); |
|
997 asm("mov ecx, eax"); // sign/exponent into ecx |
|
998 asm("ror ecx, 16"); // and into normal positions |
|
999 asm("ret"); |
|
1000 asm("trealxfromtint64a:"); // come here if top word zero |
|
1001 asm("or ebx, ebx"); // test for bottom word also zero |
|
1002 asm("jz short trealxfromtint64c"); // branch if it is |
|
1003 asm("trealxfromtint64d:"); // come here if top word zero, bottom word not |
|
1004 asm("mov edx, ebx"); // shift edx:ebx left 32 |
|
1005 asm("xor ebx, ebx"); |
|
1006 asm("bsr ecx, edx"); // ecx=bit number of edx MSB |
|
1007 asm("add eax, ecx"); // add to exponent in eax |
|
1008 asm("neg cl"); |
|
1009 asm("add cl, 31"); // 31-bit number = number of left shifts to normalise |
|
1010 asm("shl edx, cl"); // normalise |
|
1011 asm("mov ecx, eax"); // sign/exponent into ecx |
|
1012 asm("ror ecx, 16"); // and into normal positions |
|
1013 asm("ret"); |
|
1014 asm("trealxfromtint64c:"); // entire number is zero |
|
1015 asm("xor ecx, ecx"); |
|
1016 asm("ret"); |
|
1017 } |
|
1018 |
|
1019 |
|
1020 |
|
1021 |
|
1022 __NAKED__ EXPORT_C TInt TRealX::Set(const TInt64& /*aInt*/) |
|
1023 /** |
|
1024 Gives this extended precision object a new value taken from |
|
1025 a 64 bit integer. |
|
1026 |
|
1027 @param aInt The 64 bit integer value. |
|
1028 |
|
1029 @return KErrNone, always. |
|
1030 */ |
|
1031 { |
|
1032 // on entry ecx=this, [esp+4]=address of aInt, return code in eax |
|
1033 THISCALL_PROLOG1() |
|
1034 asm("push ebx"); |
|
1035 asm("push ecx"); |
|
1036 asm("mov edx, [esp+12]"); // edx=address of aInt |
|
1037 asm("mov ebx, [edx]"); |
|
1038 asm("mov edx, [edx+4]"); // edx:ebx=aInt |
|
1039 asm("call %a0": : "i"(&TRealXFromTInt64)); // convert to TRealX in ecx,edx:ebx |
|
1040 asm("pop eax"); // eax=this |
|
1041 asm("mov [eax], ebx"); // store result |
|
1042 asm("mov [eax+4], edx"); |
|
1043 asm("mov [eax+8], ecx"); |
|
1044 asm("xor eax, eax"); // return KErrNone |
|
1045 asm("pop ebx"); |
|
1046 THISCALL_EPILOG1() |
|
1047 } |
|
1048 |
|
1049 |
|
1050 |
|
1051 LOCAL_C __NAKED__ void __6TRealXi() |
|
1052 { |
|
1053 // common function for int to TRealX |
|
1054 THISCALL_PROLOG1() |
|
1055 asm("mov edx, [esp+4]"); // edx=aInt |
|
1056 asm("or edx, edx"); // test sign/zero |
|
1057 asm("mov eax, 0x7FFF"); |
|
1058 asm("jz short trealxfromint0"); // branch if 0 |
|
1059 asm("jns short trealxfromint1"); // skip if positive |
|
1060 asm("neg edx"); // take absolute value |
|
1061 asm("add eax, 0x10000"); // sign bit in eax bit 16 |
|
1062 asm("trealxfromint1:"); |
|
1063 asm("push ecx"); // save this |
|
1064 asm("bsr ecx, edx"); // bit number of edx MSB into ecx |
|
1065 asm("add eax, ecx"); // add to eax to form result exponent |
|
1066 asm("neg cl"); |
|
1067 asm("add cl, 31"); // 31-bit number = number of shifts to normalise edx |
|
1068 asm("shl edx, cl"); // normalise edx |
|
1069 asm("pop ecx"); // this back into ecx |
|
1070 asm("ror eax, 16"); // sign/exponent into normal positions |
|
1071 asm("mov [ecx+4], edx"); // store mantissa high word |
|
1072 asm("mov [ecx+8], eax"); // store sign/exponent |
|
1073 asm("xor eax, eax"); |
|
1074 asm("mov [ecx], eax"); // zero mantissa low word |
|
1075 asm("mov eax, ecx"); // return eax=this |
|
1076 THISCALL_EPILOG1() |
|
1077 asm("trealxfromint0:"); |
|
1078 asm("mov [ecx], edx"); |
|
1079 asm("mov [ecx+4], edx"); // store mantissa high word=0 |
|
1080 asm("mov [ecx+8], edx"); // store sign/exponent=0 |
|
1081 asm("mov eax, ecx"); // return eax=this |
|
1082 THISCALL_EPILOG1() |
|
1083 } |
|
1084 |
|
1085 |
|
1086 __NAKED__ EXPORT_C TRealX::TRealX(TInt /*aInt*/) |
|
1087 /** |
|
1088 Constructs an extended precision object from a signed integer value. |
|
1089 |
|
1090 @param aInt The signed integer value. |
|
1091 */ |
|
1092 { |
|
1093 // on entry ecx=this, [esp+4]=aInt, return eax=this |
|
1094 asm("jmp %a0": : "i"(&__6TRealXi)); |
|
1095 } |
|
1096 |
|
1097 |
|
1098 |
|
1099 |
|
1100 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TInt /*aInt*/) |
|
1101 /** |
|
1102 Assigns the specified signed integer value to this extended precision object. |
|
1103 |
|
1104 @param aInt The signed integer value. |
|
1105 |
|
1106 @return A reference to this extended precision object. |
|
1107 */ |
|
1108 { |
|
1109 // on entry ecx=this, [esp+4]=aInt, return eax=this |
|
1110 asm("jmp %a0": : "i"(&__6TRealXi)); |
|
1111 } |
|
1112 |
|
1113 |
|
1114 |
|
1115 LOCAL_C __NAKED__ void __6TRealXui() |
|
1116 { |
|
1117 // common function for unsigned int to TRealX |
|
1118 THISCALL_PROLOG1() |
|
1119 asm("mov edx, [esp+4]"); // edx=aInt |
|
1120 asm("mov eax, 0x7FFF"); |
|
1121 asm("or edx, edx"); // test for zero |
|
1122 asm("jz short trealxfromuint0"); // branch if 0 |
|
1123 asm("push ecx"); // save this |
|
1124 asm("bsr ecx, edx"); // bit number of edx MSB into ecx |
|
1125 asm("add eax, ecx"); // add to eax to form result exponent |
|
1126 asm("neg cl"); |
|
1127 asm("add cl, 31"); // 31-bit number = number of shifts to normalise edx |
|
1128 asm("shl edx, cl"); // normalise edx |
|
1129 asm("pop ecx"); // this back into ecx |
|
1130 asm("shl eax, 16"); // exponent into normal position |
|
1131 asm("mov [ecx+4], edx"); // store mantissa high word |
|
1132 asm("mov [ecx+8], eax"); // store exponent |
|
1133 asm("xor eax, eax"); |
|
1134 asm("mov [ecx], eax"); // zero mantissa low word |
|
1135 asm("mov eax, ecx"); // return eax=this |
|
1136 THISCALL_EPILOG1() |
|
1137 asm("trealxfromuint0:"); |
|
1138 asm("mov [ecx], edx"); |
|
1139 asm("mov [ecx+4], edx"); // store mantissa high word=0 |
|
1140 asm("mov [ecx+8], edx"); // store sign/exponent=0 |
|
1141 asm("mov eax, ecx"); // return eax=this |
|
1142 THISCALL_EPILOG1() |
|
1143 } |
|
1144 |
|
1145 |
|
1146 |
|
1147 __NAKED__ EXPORT_C TRealX::TRealX(TUint /*aInt*/) |
|
1148 /** |
|
1149 Constructs an extended precision object from an unsigned integer value. |
|
1150 |
|
1151 @param aInt The unsigned integer value. |
|
1152 */ |
|
1153 { |
|
1154 // on entry ecx=this, [esp+4]=aInt, return eax=this |
|
1155 asm("jmp %a0": : "i"(&__6TRealXui)); |
|
1156 } |
|
1157 |
|
1158 |
|
1159 |
|
1160 |
|
1161 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TUint /*aInt*/) |
|
1162 /** |
|
1163 Assigns the specified unsigned integer value to this extended precision object. |
|
1164 |
|
1165 @param aInt The unsigned integer value. |
|
1166 |
|
1167 @return A reference to this extended precision object. |
|
1168 */ |
|
1169 { |
|
1170 // on entry ecx=this, [esp+4]=aInt, return eax=this |
|
1171 asm("jmp %a0": : "i"(&__6TRealXui)); |
|
1172 } |
|
1173 |
|
1174 |
|
1175 |
|
1176 |
|
1177 LOCAL_C __NAKED__ void __6TRealXRC6TInt64() |
|
1178 { |
|
1179 // common function for TInt64 to TRealX |
|
1180 THISCALL_PROLOG1() |
|
1181 asm("push ebx"); // preserve ebx |
|
1182 asm("push ecx"); // save this |
|
1183 asm("mov edx, [esp+12]"); // edx=address of aInt |
|
1184 asm("mov ebx, [edx]"); |
|
1185 asm("mov edx, [edx+4]"); // edx:ebx=aInt |
|
1186 asm("call %a0": : "i"(&TRealXFromTInt64)); // convert to TRealX in ecx,edx:ebx |
|
1187 asm("pop eax"); // eax=this |
|
1188 asm("mov [eax], ebx"); // store result |
|
1189 asm("mov [eax+4], edx"); |
|
1190 asm("mov [eax+8], ecx"); |
|
1191 asm("mov ecx, eax"); // restore this ptr |
|
1192 asm("pop ebx"); // restore ebx |
|
1193 THISCALL_EPILOG1() |
|
1194 } |
|
1195 |
|
1196 |
|
1197 |
|
1198 |
|
1199 __NAKED__ EXPORT_C TRealX::TRealX(const TInt64& /*aInt*/) |
|
1200 /** |
|
1201 Constructs an extended precision object from a 64 bit integer. |
|
1202 |
|
1203 @param aInt A reference to a 64 bit integer. |
|
1204 */ |
|
1205 { |
|
1206 // on entry ecx=this, [esp+4]=address of aInt, return eax=this |
|
1207 asm("jmp %a0": : "i"(&__6TRealXRC6TInt64)); |
|
1208 } |
|
1209 |
|
1210 |
|
1211 |
|
1212 |
|
1213 __NAKED__ EXPORT_C TRealX& TRealX::operator=(const TInt64& /*aInt*/) |
|
1214 /** |
|
1215 Assigns the specified 64 bit integer value to this extended precision object. |
|
1216 |
|
1217 @param aInt A reference to a 64 bit integer. |
|
1218 |
|
1219 @return A reference to this extended precision object. |
|
1220 */ |
|
1221 { |
|
1222 // on entry ecx=this, [esp+4]=address of aInt, return eax=this |
|
1223 asm("jmp %a0": : "i"(&__6TRealXRC6TInt64)); |
|
1224 } |
|
1225 |
|
1226 |
|
1227 |
|
1228 |
|
1229 LOCAL_C __NAKED__ void ConvertTReal32ToTRealX(void) |
|
1230 { |
|
1231 // Convert TReal32 in edx to TRealX in ecx:edx,ebx |
|
1232 asm("xor ebx, ebx"); // mant low always zero |
|
1233 asm("mov eax, edx"); |
|
1234 asm("shr eax, 23"); // exponent now in al, sign in ah bit 0 |
|
1235 asm("test al, al"); // check for denormal/zero |
|
1236 asm("jz short treal32totrealx2"); // branch if denormal/zero |
|
1237 asm("xor ecx, ecx"); |
|
1238 asm("mov cl, al"); |
|
1239 asm("add ecx, 0x7F80"); // bias exponent correctly for TRealX |
|
1240 asm("cmp al, 0xFF"); // check for infinity/NaN |
|
1241 asm("jnz short treal32totrealx1"); // skip if neither |
|
1242 asm("mov cl, al"); // else set TRealX exponent to FFFF |
|
1243 asm("mov ch, al"); |
|
1244 asm("treal32totrealx1:"); |
|
1245 asm("shl edx, 8"); // left-justify mantissa in edx |
|
1246 asm("or edx, 0x80000000"); // put in implied integer bit |
|
1247 asm("shl ecx, 16"); // exponent into ecx bits 16-31 |
|
1248 asm("mov cl, ah"); // sign into ecx bit 0 |
|
1249 asm("ret"); |
|
1250 asm("treal32totrealx2:"); // come here if exponent 0 |
|
1251 asm("shl edx, 9"); // left-justify mantissa in edx [shift out integer bit as well] |
|
1252 asm("jnz short treal32totrealx3"); // jump if denormal |
|
1253 asm("xor ecx, ecx"); // else return 0 |
|
1254 asm("mov cl, ah"); // with same sign as input value |
|
1255 asm("ret"); |
|
1256 asm("treal32totrealx3:"); // come here if denormal |
|
1257 asm("bsr ecx, edx"); // ecx=bit number of MSB of edx |
|
1258 asm("neg ecx"); |
|
1259 asm("add ecx, 31"); // ecx=number of left shifts to normalise edx |
|
1260 asm("shl edx, cl"); // normalise |
|
1261 asm("neg ecx"); |
|
1262 asm("add ecx, 0x7F80"); // exponent=7F80-number of shifts |
|
1263 asm("shl ecx, 16"); // exponent into ecx bits 16-31 |
|
1264 asm("mov cl, ah"); // sign into ecx bit 0 |
|
1265 asm("ret"); |
|
1266 } |
|
1267 |
|
1268 |
|
1269 |
|
1270 |
|
1271 LOCAL_C __NAKED__ void ConvertTReal64ToTRealX(void) |
|
1272 { |
|
1273 // Convert TReal64 in edx:ebx to TRealX in ecx:edx,ebx |
|
1274 asm("mov eax, edx"); |
|
1275 asm("shr eax, 20"); |
|
1276 asm("mov ecx, 0x7FF"); |
|
1277 asm("and ecx, eax"); // ecx=exponent |
|
1278 asm("jz short treal64totrealx1"); // branch if zero/denormal |
|
1279 asm("add ecx, 0x7C00"); // else bias exponent correctly for TRealX |
|
1280 asm("cmp ecx, 0x83FF"); // check for infinity/NaN |
|
1281 asm("jnz short treal64totrealx2"); |
|
1282 asm("mov ch, cl"); // if so, set exponent to FFFF |
|
1283 asm("treal64totrealx2:"); |
|
1284 asm("shl ecx, 16"); // exponent into ecx bits 16-31 |
|
1285 asm("mov cl, 11"); // number of shifts needed to justify mantissa correctly |
|
1286 asm("shld edx, ebx, cl"); // shift mantissa left |
|
1287 asm("shl ebx, cl"); |
|
1288 asm("or edx, 0x80000000"); // put in implied integer bit |
|
1289 asm("shr eax, 11"); // sign bit into al bit 0 |
|
1290 asm("mov cl, al"); // into ecx bit 0 |
|
1291 asm("ret"); |
|
1292 asm("treal64totrealx1:"); // come here if zero/denormal |
|
1293 asm("mov cl, 12"); // number of shifts needed to justify mantissa correctly |
|
1294 asm("shld edx, ebx, cl"); // shift mantissa left |
|
1295 asm("shl ebx, cl"); |
|
1296 asm("test edx, edx"); // check for zero |
|
1297 asm("jnz short treal64totrealx3"); |
|
1298 asm("test ebx, ebx"); |
|
1299 asm("jnz short treal64totrealx4"); |
|
1300 asm("shr eax, 11"); // sign bit into eax bit 0, rest of eax=0 |
|
1301 asm("mov ecx, eax"); // return 0 result with correct sign |
|
1302 asm("ret"); |
|
1303 asm("treal64totrealx4:"); // come here if denormal, edx=0 |
|
1304 asm("mov edx, ebx"); // shift mantissa left 32 |
|
1305 asm("xor ebx, ebx"); |
|
1306 asm("bsr ecx, edx"); // ecx=bit number of MSB of edx |
|
1307 asm("neg ecx"); |
|
1308 asm("add ecx, 31"); // ecx=number of left shifts to normalise edx |
|
1309 asm("shl edx, cl"); // normalise |
|
1310 asm("neg ecx"); |
|
1311 asm("add ecx, 0x7BE0"); // exponent=7BE0-number of shifts |
|
1312 asm("shl ecx, 16"); // exponent into bits 16-31 of ecx |
|
1313 asm("shr eax, 11"); |
|
1314 asm("mov cl, al"); // sign into bit 0 of ecx |
|
1315 asm("ret"); |
|
1316 asm("treal64totrealx3:"); // come here if denormal, edx nonzero |
|
1317 asm("bsr ecx, edx"); // ecx=bit number of MSB of edx |
|
1318 asm("neg ecx"); |
|
1319 asm("add ecx, 31"); // ecx=number of left shifts to normalise edx:ebx |
|
1320 asm("shld edx, ebx, cl"); // normalise |
|
1321 asm("shl ebx, cl"); |
|
1322 asm("neg ecx"); |
|
1323 asm("add ecx, 0x7C00"); // exponent=7C00-number of shifts |
|
1324 asm("shl ecx, 16"); // exponent into bits 16-31 of ecx |
|
1325 asm("shr eax, 11"); |
|
1326 asm("mov cl, al"); // sign into bit 0 of ecx |
|
1327 asm("ret"); |
|
1328 } |
|
1329 |
|
1330 |
|
1331 |
|
1332 |
|
1333 __NAKED__ EXPORT_C TInt TRealX::Set(TReal32 /*aReal*/) |
|
1334 /** |
|
1335 Gives this extended precision object a new value taken from |
|
1336 a single precision floating point number. |
|
1337 |
|
1338 @param aReal The single precision floating point value. |
|
1339 |
|
1340 @return KErrNone, if a valid number; |
|
1341 KErrOverflow, if the number is infinite; |
|
1342 KErrArgument, if not a number. |
|
1343 */ |
|
1344 { |
|
1345 // on entry, ecx=this and aReal is in [esp+4] |
|
1346 // on exit, error code in eax |
|
1347 THISCALL_PROLOG1() |
|
1348 asm("push ecx"); |
|
1349 asm("push ebx"); // save ebx |
|
1350 asm("push ecx"); // save this |
|
1351 asm("mov edx, [esp+16]"); // aReal into edx |
|
1352 asm("call %a0": : "i"(&ConvertTReal32ToTRealX)); |
|
1353 asm("pop eax"); // eax=this |
|
1354 asm("mov [eax], ebx"); // store result |
|
1355 asm("mov [eax+4], edx"); |
|
1356 asm("mov [eax+8], ecx"); |
|
1357 asm("xor eax, eax"); // error code=KErrNone initially |
|
1358 asm("cmp ecx, 0xFFFF0000"); // check for infinity/NaN |
|
1359 asm("jb short trealxsettreal32a"); // if neither, return KErrNone |
|
1360 asm("mov eax, -9"); // eax=KErrOverflow |
|
1361 asm("cmp edx, 0x80000000"); // check for infinity |
|
1362 asm("je short trealxsettreal32a"); // if infinity, return KErrOverflow |
|
1363 asm("mov eax, -6"); // if NaN, return KErrArgument |
|
1364 asm("trealxsettreal32a:"); |
|
1365 asm("pop ebx"); |
|
1366 asm("pop ecx"); |
|
1367 THISCALL_EPILOG1() |
|
1368 } |
|
1369 |
|
1370 |
|
1371 |
|
1372 |
|
1373 __NAKED__ EXPORT_C TInt TRealX::Set(TReal64 /*aReal*/) |
|
1374 /** |
|
1375 Gives this extended precision object a new value taken from |
|
1376 a double precision floating point number. |
|
1377 |
|
1378 @param aReal The double precision floating point value. |
|
1379 |
|
1380 @return KErrNone, if a valid number; |
|
1381 KErrOverflow, if the number is infinite; |
|
1382 KErrArgument, if not a number. |
|
1383 */ |
|
1384 { |
|
1385 // on entry, ecx=this and aReal is in [esp+4] (mant low) and [esp+8] (sign/exp/mant high) |
|
1386 // on exit, error code in eax |
|
1387 THISCALL_PROLOG2() |
|
1388 asm("push ecx"); |
|
1389 asm("push ebx"); // save ebx |
|
1390 asm("push ecx"); // save this |
|
1391 asm("mov ebx, [esp+16]"); // aReal into edx:ebx |
|
1392 asm("mov edx, [esp+20]"); |
|
1393 asm("call %a0": : "i"(&ConvertTReal64ToTRealX)); |
|
1394 asm("pop eax"); // eax=this |
|
1395 asm("mov [eax], ebx"); // store result |
|
1396 asm("mov [eax+4], edx"); |
|
1397 asm("mov [eax+8], ecx"); |
|
1398 asm("xor eax, eax"); // error code=KErrNone initially |
|
1399 asm("cmp ecx, 0xFFFF0000"); // check for infinity/NaN |
|
1400 asm("jb short trealxsettreal64a"); // if neither, return KErrNone |
|
1401 asm("mov eax, -9"); // eax=KErrOverflow |
|
1402 asm("cmp edx, 0x80000000"); // check for infinity |
|
1403 asm("jne short trealxsettreal64b"); // branch if NaN |
|
1404 asm("test ebx, ebx"); |
|
1405 asm("je short trealxsettreal64a"); // if infinity, return KErrOverflow |
|
1406 asm("trealxsettreal64b:"); |
|
1407 asm("mov eax, -6"); // if NaN, return KErrArgument |
|
1408 asm("trealxsettreal64a:"); |
|
1409 asm("pop ebx"); |
|
1410 asm("pop ecx"); |
|
1411 THISCALL_EPILOG2() |
|
1412 } |
|
1413 |
|
1414 |
|
1415 |
|
1416 |
|
1417 LOCAL_C __NAKED__ void __6TRealXf() |
|
1418 { |
|
1419 // common function for float to TRealX |
|
1420 THISCALL_PROLOG1() |
|
1421 asm("push ebx"); // save ebx |
|
1422 asm("push ecx"); // save this |
|
1423 asm("mov edx, [esp+12]"); // aReal into edx |
|
1424 asm("call %a0": : "i"(&ConvertTReal32ToTRealX)); |
|
1425 asm("pop eax"); // eax=this |
|
1426 asm("mov [eax], ebx"); // store result |
|
1427 asm("mov [eax+4], edx"); |
|
1428 asm("mov [eax+8], ecx"); |
|
1429 asm("pop ebx"); |
|
1430 asm("mov ecx,eax"); |
|
1431 THISCALL_EPILOG1() |
|
1432 } |
|
1433 |
|
1434 |
|
1435 |
|
1436 |
|
1437 __NAKED__ EXPORT_C TRealX::TRealX(TReal32 /*aReal*/) |
|
1438 /** |
|
1439 Constructs an extended precision object from |
|
1440 a single precision floating point number. |
|
1441 |
|
1442 @param aReal The single precision floating point value. |
|
1443 */ |
|
1444 { |
|
1445 // on entry, ecx=this and aReal is in [esp+4] |
|
1446 // on exit, eax=this |
|
1447 asm("jmp %a0": : "i"(&__6TRealXf)); |
|
1448 } |
|
1449 |
|
1450 |
|
1451 |
|
1452 |
|
1453 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TReal32 /*aReal*/) |
|
1454 /** |
|
1455 Assigns the specified single precision floating point number to |
|
1456 this extended precision object. |
|
1457 |
|
1458 @param aReal The single precision floating point value. |
|
1459 |
|
1460 @return A reference to this extended precision object. |
|
1461 */ |
|
1462 { |
|
1463 // on entry, ecx=this and aReal is in [esp+4] |
|
1464 // on exit, eax=this |
|
1465 asm("jmp %a0": : "i"(&__6TRealXf)); |
|
1466 } |
|
1467 |
|
1468 |
|
1469 |
|
1470 |
|
1471 LOCAL_C __NAKED__ void __6TRealXd() |
|
1472 { |
|
1473 // common function for double to TRealX |
|
1474 THISCALL_PROLOG2() |
|
1475 asm("push ebx"); // save ebx |
|
1476 asm("push ecx"); // save this |
|
1477 asm("mov ebx, [esp+12]"); // aReal into edx:ebx |
|
1478 asm("mov edx, [esp+16]"); |
|
1479 asm("call %a0": : "i"(&ConvertTReal64ToTRealX)); |
|
1480 asm("pop eax"); // eax=this |
|
1481 asm("mov [eax], ebx"); // store result |
|
1482 asm("mov [eax+4], edx"); |
|
1483 asm("mov [eax+8], ecx"); |
|
1484 asm("pop ebx"); |
|
1485 asm("mov ecx,eax"); |
|
1486 THISCALL_EPILOG2() |
|
1487 } |
|
1488 |
|
1489 |
|
1490 |
|
1491 |
|
1492 __NAKED__ EXPORT_C TRealX::TRealX(TReal64 /*aReal*/) |
|
1493 /** |
|
1494 Constructs an extended precision object from |
|
1495 a double precision floating point number. |
|
1496 |
|
1497 @param aReal The double precision floating point value. |
|
1498 */ |
|
1499 { |
|
1500 // on entry, ecx=this and aReal is in [esp+4] (mant low) and [esp+8] (sign/exp/mant high) |
|
1501 // on exit, eax=this |
|
1502 asm("jmp %a0": : "i"(&__6TRealXd)); |
|
1503 } |
|
1504 |
|
1505 |
|
1506 |
|
1507 |
|
1508 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TReal64 /*aReal*/) |
|
1509 /** |
|
1510 Assigns the specified double precision floating point number to |
|
1511 this extended precision object. |
|
1512 |
|
1513 @param aReal The double precision floating point value. |
|
1514 |
|
1515 @return A reference to this extended precision object. |
|
1516 */ |
|
1517 { |
|
1518 // on entry, ecx=this and aReal is in [esp+4] (mant low) and [esp+8] (sign/exp/mant high) |
|
1519 // on exit, eax=this |
|
1520 asm("jmp %a0": : "i"(&__6TRealXd)); |
|
1521 } |
|
1522 |
|
1523 |
|
1524 |
|
1525 |
|
1526 __NAKED__ EXPORT_C TRealX::operator TInt() const |
|
1527 /** |
|
1528 Gets the extended precision value as a signed integer value. |
|
1529 |
|
1530 The operator asm("returns:"); |
|
1531 |
|
1532 1. zero , if the extended precision value is not a number |
|
1533 |
|
1534 2. 0x7FFFFFFF, if the value is positive and too big to fit into a TInt. |
|
1535 |
|
1536 3. 0x80000000, if the value is negative and too big to fit into a TInt. |
|
1537 */ |
|
1538 { |
|
1539 // on entry ecx=this, return value in eax |
|
1540 THISCALL_PROLOG0() |
|
1541 asm("push ecx"); |
|
1542 asm("mov edx, [ecx]"); // edx=mantissa low |
|
1543 asm("mov eax, [ecx+4]"); // eax=mantissa high |
|
1544 asm("mov ecx, [ecx+8]"); // ecx=exponent/sign |
|
1545 asm("ror ecx, 16"); // exponent into cx |
|
1546 asm("cmp cx, 0xFFFF"); |
|
1547 asm("jz short trealxtoint1"); // branch if exp=FFFF |
|
1548 asm("mov dx, cx"); |
|
1549 asm("mov cx, 0x801E"); |
|
1550 asm("sub cx, dx"); // cx=number of right shifts needed to convert mantissa to int |
|
1551 asm("jbe short trealxtoint2"); // if exp>=801E, saturate result |
|
1552 asm("cmp cx, 31"); // more than 31 shifts needed? |
|
1553 asm("ja short trealxtoint0"); // if so, underflow to zero |
|
1554 asm("shr eax, cl"); // else ABS[result]=eax>>cl |
|
1555 asm("test ecx, 0x10000"); // test sign |
|
1556 asm("jz short trealxtoint3"); // skip if + |
|
1557 asm("neg eax"); |
|
1558 asm("trealxtoint3:"); |
|
1559 asm("pop ecx"); |
|
1560 THISCALL_EPILOG0() |
|
1561 asm("trealxtoint1:"); // come here if exponent=FFFF |
|
1562 asm("cmp eax, 0x80000000"); // check for infinity |
|
1563 asm("jnz short trealxtoint0"); // if NaN, return 0 |
|
1564 asm("test edx, edx"); |
|
1565 asm("jnz short trealxtoint0"); // if NaN, return 0 |
|
1566 asm("trealxtoint2:"); // come here if argument too big for 32-bit integer |
|
1567 asm("mov eax, 0x7FFFFFFF"); |
|
1568 asm("shr ecx, 17"); // sign bit into carry flag |
|
1569 asm("adc eax, 0"); // eax=7FFFFFFF if +, 80000000 if - |
|
1570 asm("pop ecx"); |
|
1571 THISCALL_EPILOG0() // return saturated value |
|
1572 asm("trealxtoint0:"); // come here if INT{argument}=0 or NaN |
|
1573 asm("xor eax, eax"); // return 0 |
|
1574 asm("pop ecx"); |
|
1575 THISCALL_EPILOG0() |
|
1576 } |
|
1577 |
|
1578 |
|
1579 |
|
1580 |
|
1581 __NAKED__ EXPORT_C TRealX::operator TUint() const |
|
1582 /** |
|
1583 Returns the extended precision value as an unsigned signed integer value. |
|
1584 |
|
1585 The operator asm("returns:"); |
|
1586 |
|
1587 1. zero, if the extended precision value is not a number |
|
1588 |
|
1589 2. 0xFFFFFFFF, if the value is positive and too big to fit into a TUint. |
|
1590 |
|
1591 3. zero, if the value is negative and too big to fit into a TUint. |
|
1592 */ |
|
1593 { |
|
1594 // on entry ecx=this, return value in eax |
|
1595 THISCALL_PROLOG0() |
|
1596 asm("push ecx"); |
|
1597 asm("mov edx, [ecx]"); // edx=mantissa low |
|
1598 asm("mov eax, [ecx+4]"); // eax=mantissa high |
|
1599 asm("mov ecx, [ecx+8]"); // ecx=exponent/sign |
|
1600 asm("ror ecx, 16"); // exponent into cx |
|
1601 asm("cmp cx, 0xFFFF"); |
|
1602 asm("jz short trealxtouint1"); // branch if exp=FFFF |
|
1603 asm("mov dx, cx"); |
|
1604 asm("mov cx, 0x801E"); |
|
1605 asm("sub cx, dx"); // cx=number of right shifts needed to convert mantissa to int |
|
1606 asm("jb short trealxtouint2"); // if exp>801E, saturate result |
|
1607 asm("cmp cx, 31"); // more than 31 shifts needed? |
|
1608 asm("ja short trealxtouint0"); // if so, underflow to zero |
|
1609 asm("test ecx, 0x10000"); // test sign |
|
1610 asm("jnz short trealxtouint0"); // if -, return 0 |
|
1611 asm("shr eax, cl"); // else result=eax>>cl |
|
1612 asm("pop ecx"); |
|
1613 THISCALL_EPILOG0() |
|
1614 asm("trealxtouint1:"); // come here if exponent=FFFF |
|
1615 asm("cmp eax, 0x80000000"); // check for infinity |
|
1616 asm("jnz short trealxtouint0"); // if NaN, return 0 |
|
1617 asm("test edx, edx"); |
|
1618 asm("jnz short trealxtouint0"); // if NaN, return 0 |
|
1619 asm("trealxtouint2:"); // come here if argument too big for 32-bit integer |
|
1620 asm("mov eax, 0xFFFFFFFF"); |
|
1621 asm("shr ecx, 17"); // sign bit into carry flag |
|
1622 asm("adc eax, 0"); // eax=FFFFFFFF if +, 0 if - |
|
1623 asm("pop ecx"); |
|
1624 THISCALL_EPILOG0() // return saturated value |
|
1625 asm("trealxtouint0:"); // come here if INT{argument}=0 or NaN |
|
1626 asm("xor eax, eax"); // return 0 |
|
1627 asm("pop ecx"); |
|
1628 THISCALL_EPILOG0() |
|
1629 } |
|
1630 |
|
1631 |
|
1632 |
|
1633 |
|
1634 LOCAL_C __NAKED__ void ConvertTRealXToTInt64(void) |
|
1635 { |
|
1636 // Convert TRealX in ecx,edx:ebx to TInt64 in edx:ebx |
|
1637 asm("ror ecx, 16"); // exponent into cx |
|
1638 asm("cmp cx, 0xFFFF"); |
|
1639 asm("jz short trealxtoint64a"); // branch if exp=FFFF |
|
1640 asm("mov ax, cx"); |
|
1641 asm("mov cx, 0x803E"); |
|
1642 asm("sub cx, ax"); // cx=number of right shifts needed to convert mantissa to int |
|
1643 asm("jbe short trealxtoint64b"); // if exp>=803E, saturate result |
|
1644 asm("cmp cx, 63"); // more than 63 shifts needed? |
|
1645 asm("ja short trealxtoint64z"); // if so, underflow to zero |
|
1646 asm("cmp cl, 31"); // more than 31 shifts needed? |
|
1647 asm("jbe short trealxtoint64d"); // branch if not |
|
1648 asm("sub cl, 32"); // cl=shift count - 32 |
|
1649 asm("mov ebx, edx"); // shift right by 32 |
|
1650 asm("xor edx, edx"); |
|
1651 asm("trealxtoint64d:"); |
|
1652 asm("shrd ebx, edx, cl"); // shift edx:ebx right by cl to give ABS{result} |
|
1653 asm("shr edx, cl"); |
|
1654 asm("test ecx, 0x10000"); // test sign |
|
1655 asm("jz short trealxtoint64c"); // skip if + |
|
1656 asm("neg edx"); // if -, negate |
|
1657 asm("neg ebx"); |
|
1658 asm("sbb edx, 0"); |
|
1659 asm("trealxtoint64c:"); |
|
1660 asm("ret"); |
|
1661 asm("trealxtoint64a:"); // come here if exponent=FFFF |
|
1662 asm("cmp edx, 0x80000000"); // check for infinity |
|
1663 asm("jnz short trealxtoint64z"); // if NaN, return 0 |
|
1664 asm("test ebx, ebx"); |
|
1665 asm("jnz short trealxtoint64z"); // if NaN, return 0 |
|
1666 asm("trealxtoint64b:"); // come here if argument too big for 32-bit integer |
|
1667 asm("mov edx, 0x7FFFFFFF"); |
|
1668 asm("mov ebx, 0xFFFFFFFF"); |
|
1669 asm("shr ecx, 17"); // sign bit into carry flag |
|
1670 asm("adc ebx, 0"); // edx:ebx=7FFFFFFF FFFFFFFF if +, |
|
1671 asm("adc edx, 0"); // or 80000000 00000000 if - |
|
1672 asm("ret"); // return saturated value |
|
1673 asm("trealxtoint64z:"); // come here if INT{argument}=0 or NaN |
|
1674 asm("xor edx, edx"); // return 0 |
|
1675 asm("xor ebx, ebx"); |
|
1676 asm("ret"); |
|
1677 } |
|
1678 |
|
1679 |
|
1680 |
|
1681 |
|
1682 /** |
|
1683 Returns the extended precision value as a 64 bit integer value. |
|
1684 |
|
1685 The operator asm("returns:"); |
|
1686 |
|
1687 1. zero, if the extended precision value is not a number |
|
1688 |
|
1689 2. 0x7FFFFFFF FFFFFFFF, if the value is positive and too big to fit |
|
1690 into a TInt64 |
|
1691 |
|
1692 3. 0x80000000 00000000, if the value is negative and too big to fit |
|
1693 into a TInt. |
|
1694 */ |
|
1695 __NAKED__ EXPORT_C TRealX::operator TInt64() const |
|
1696 { |
|
1697 // on entry, ecx=this, return value in edx:eax |
|
1698 THISCALL_PROLOG0() |
|
1699 asm("push ecx"); |
|
1700 asm("push ebx"); |
|
1701 asm("mov ebx, [ecx]"); // get TRealX value into ecx,edx:ebx |
|
1702 asm("mov edx, [ecx+4]"); |
|
1703 asm("mov ecx, [ecx+8]"); |
|
1704 asm("call %a0": : "i"(&ConvertTRealXToTInt64)); |
|
1705 asm("mov eax, ebx"); // result low into eax |
|
1706 asm("pop ebx"); |
|
1707 asm("pop ecx"); |
|
1708 THISCALL_EPILOG0() |
|
1709 } |
|
1710 |
|
1711 |
|
1712 |
|
1713 |
|
1714 LOCAL_C __NAKED__ void TRealXGetTReal32(void) |
|
1715 { |
|
1716 // Convert TRealX in ecx,edx:ebx to TReal32 in edx |
|
1717 // Return error code in eax |
|
1718 asm("cmp ecx, 0xFFFF0000"); // check for infinity/NaN |
|
1719 asm("jnc short trealxgettreal32a"); |
|
1720 asm("xor eax, eax"); |
|
1721 asm("ror ecx, 16"); // exponent into cx |
|
1722 asm("sub cx, 0x7F80"); // cx=result exponent if normalised |
|
1723 asm("jbe short trealxgettreal32b"); // jump if denormal, zero or underflow |
|
1724 asm("cmp cx, 0xFF"); // check if overflow |
|
1725 asm("jb short trealxgettreal32c"); // jump if not |
|
1726 asm("trealxgettreal32d:"); // come here if overflow |
|
1727 asm("xor edx, edx"); // set mantissa=0 to generate infinity |
|
1728 asm("ror ecx, 16"); // ecx back to normal format |
|
1729 asm("trealxgettreal32a:"); // come here if infinity or NaN |
|
1730 asm("shr edx, 7"); |
|
1731 asm("or edx, 0xFF000000"); // set exponent to FF |
|
1732 asm("shr ecx, 1"); // sign bit -> carry |
|
1733 asm("rcr edx, 1"); // sign bit -> MSB of result |
|
1734 asm("mov eax, edx"); |
|
1735 asm("shl eax, 9"); // test for infinity or NaN |
|
1736 asm("mov eax, -9"); // eax=KErrOverflow |
|
1737 asm("jz short trealxgettreal32e"); |
|
1738 asm("mov eax, -6"); // if NaN, eax=KErrArgument |
|
1739 asm("trealxgettreal32e:"); |
|
1740 asm("ret"); |
|
1741 asm("trealxgettreal32b:"); // come here if exponent<=7F80 |
|
1742 asm("cmp cx, -24"); // check for zero or total underflow |
|
1743 asm("jle short trealxgettreal32z"); |
|
1744 asm("neg cl"); |
|
1745 asm("inc cl"); // cl=number of right shifts to form denormal mantissa |
|
1746 asm("shrd eax, ebx, cl"); // shift mantissa right into eax |
|
1747 asm("shrd ebx, edx, cl"); |
|
1748 asm("shr edx, cl"); |
|
1749 asm("or edx, 0x80000000"); // set top bit to ensure correct rounding up |
|
1750 asm("xor cl, cl"); // cl=result exponent=0 |
|
1751 asm("trealxgettreal32c:"); // come here if result normalised |
|
1752 asm("cmp dl, 0x80"); // check rounding bits |
|
1753 asm("ja short trealxgettreal32f"); // branch to round up |
|
1754 asm("jb short trealxgettreal32g"); // branch to round down |
|
1755 asm("test ebx, ebx"); |
|
1756 asm("jnz short trealxgettreal32f"); // branch to round up |
|
1757 asm("test eax, eax"); |
|
1758 asm("jnz short trealxgettreal32f"); // branch to round up |
|
1759 asm("test ecx, 0x01000000"); // check rounded-down flag |
|
1760 asm("jnz short trealxgettreal32f"); // branch to round up |
|
1761 asm("test ecx, 0x02000000"); // check rounded-up flag |
|
1762 asm("jnz short trealxgettreal32g"); // branch to round down |
|
1763 asm("test dh, 1"); // else round to even |
|
1764 asm("jz short trealxgettreal32g"); // branch to round down if LSB=0 |
|
1765 asm("trealxgettreal32f:"); // come here to round up |
|
1766 asm("add edx, 0x100"); // increment mantissa |
|
1767 asm("jnc short trealxgettreal32g"); |
|
1768 asm("rcr edx, 1"); |
|
1769 asm("inc cl"); // if carry, increment exponent |
|
1770 asm("cmp cl, 0xFF"); // and check for overflow |
|
1771 asm("jz short trealxgettreal32d"); // branch out if overflow |
|
1772 asm("trealxgettreal32g:"); // come here to round down |
|
1773 asm("xor dl, dl"); |
|
1774 asm("add edx, edx"); // shift out integer bit |
|
1775 asm("mov dl, cl"); |
|
1776 asm("ror edx, 8"); // exponent->edx bits 24-31, mantissa in 23-1 |
|
1777 asm("test edx, edx"); // check if underflow |
|
1778 asm("jz short trealxgettreal32h"); // branch out if underflow |
|
1779 asm("shr ecx, 17"); // sign bit->carry |
|
1780 asm("rcr edx, 1"); // ->edx bit 31, exp->edx bits 23-30, mant->edx bits 22-0 |
|
1781 asm("xor eax, eax"); // return KErrNone |
|
1782 asm("ret"); |
|
1783 asm("trealxgettreal32z:"); // come here if zero or underflow |
|
1784 asm("xor eax, eax"); |
|
1785 asm("cmp cx, 0x8080"); // check for zero |
|
1786 asm("jz short trealxgettreal32y"); // if zero, return KErrNone |
|
1787 asm("trealxgettreal32h:"); // come here if underflow after rounding |
|
1788 asm("mov eax, -10"); // eax=KErrUnderflow |
|
1789 asm("trealxgettreal32y:"); |
|
1790 asm("xor edx, edx"); |
|
1791 asm("shr ecx, 17"); |
|
1792 asm("rcr edx, 1"); // sign bit into edx bit 31, rest of edx=0 |
|
1793 asm("ret"); |
|
1794 } |
|
1795 |
|
1796 |
|
1797 |
|
1798 |
|
1799 LOCAL_C __NAKED__ void TRealXGetTReal64(void) |
|
1800 { |
|
1801 // Convert TRealX in ecx,edx:ebx to TReal64 in edx:ebx |
|
1802 // Return error code in eax |
|
1803 // edi, esi also modified |
|
1804 asm("ror ecx, 16"); // exponent into cx |
|
1805 asm("cmp cx, 0xFFFF"); // check for infinity/NaN |
|
1806 asm("jnc short trealxgettreal64a"); |
|
1807 asm("xor eax, eax"); |
|
1808 asm("xor edi, edi"); |
|
1809 asm("sub cx, 0x7C00"); // cx=result exponent if normalised |
|
1810 asm("jbe short trealxgettreal64b"); // jump if denormal, zero or underflow |
|
1811 asm("cmp cx, 0x07FF"); // check if overflow |
|
1812 asm("jb short trealxgettreal64c"); // jump if not |
|
1813 asm("trealxgettreal64d:"); // come here if overflow |
|
1814 asm("xor edx, edx"); // set mantissa=0 to generate infinity |
|
1815 asm("xor ebx, ebx"); |
|
1816 asm("trealxgettreal64a:"); // come here if infinity or NaN |
|
1817 asm("mov cl, 10"); |
|
1818 asm("shrd ebx, edx, cl"); |
|
1819 asm("shr edx, cl"); |
|
1820 asm("or edx, 0xFFE00000"); // set exponent to 7FF |
|
1821 asm("shr ecx, 17"); // sign bit -> carry |
|
1822 asm("rcr edx, 1"); // sign bit -> MSB of result |
|
1823 asm("rcr ebx, 1"); |
|
1824 asm("mov eax, edx"); |
|
1825 asm("shl eax, 12"); // test for infinity or NaN |
|
1826 asm("mov eax, -9"); // eax=KErrOverflow |
|
1827 asm("jnz short trealxgettreal64n"); |
|
1828 asm("test ebx, ebx"); |
|
1829 asm("jz short trealxgettreal64e"); |
|
1830 asm("trealxgettreal64n:"); |
|
1831 asm("mov eax, -6"); // if NaN, eax=KErrArgument |
|
1832 asm("trealxgettreal64e:"); |
|
1833 asm("ret"); |
|
1834 asm("trealxgettreal64b:"); // come here if exponent<=7C00 |
|
1835 asm("cmp cx, -53"); // check for zero or total underflow |
|
1836 asm("jle short trealxgettreal64z"); |
|
1837 asm("neg cl"); |
|
1838 asm("inc cl"); // cl=number of right shifts to form denormal mantissa |
|
1839 asm("cmp cl, 32"); |
|
1840 asm("jb trealxgettreal64x"); |
|
1841 asm("mov eax, ebx"); // if >=32 shifts, do 32 shifts and decrement count by 32 |
|
1842 asm("mov ebx, edx"); |
|
1843 asm("xor edx, edx"); |
|
1844 asm("trealxgettreal64x:"); |
|
1845 asm("shrd edi, eax, cl"); |
|
1846 asm("shrd eax, ebx, cl"); // shift mantissa right into eax |
|
1847 asm("shrd ebx, edx, cl"); |
|
1848 asm("shr edx, cl"); |
|
1849 asm("or edx, 0x80000000"); // set top bit to ensure correct rounding up |
|
1850 asm("xor cx, cx"); // cx=result exponent=0 |
|
1851 asm("trealxgettreal64c:"); // come here if result normalised |
|
1852 asm("mov esi, ebx"); |
|
1853 asm("and esi, 0x7FF"); // esi=rounding bits |
|
1854 asm("cmp esi, 0x400"); // check rounding bits |
|
1855 asm("ja short trealxgettreal64f"); // branch to round up |
|
1856 asm("jb short trealxgettreal64g"); // branch to round down |
|
1857 asm("test eax, eax"); |
|
1858 asm("jnz short trealxgettreal64f"); // branch to round up |
|
1859 asm("test edi, edi"); |
|
1860 asm("jnz short trealxgettreal64f"); // branch to round up |
|
1861 asm("test ecx, 0x01000000"); // check rounded-down flag |
|
1862 asm("jnz short trealxgettreal64f"); // branch to round up |
|
1863 asm("test ecx, 0x02000000"); // check rounded-up flag |
|
1864 asm("jnz short trealxgettreal64g"); // branch to round down |
|
1865 asm("test ebx, 0x800"); // else round to even |
|
1866 asm("jz short trealxgettreal64g"); // branch to round down if LSB=0 |
|
1867 asm("trealxgettreal64f:"); // come here to round up |
|
1868 asm("add ebx, 0x800"); // increment mantissa |
|
1869 asm("adc edx, 0"); |
|
1870 asm("jnc short trealxgettreal64g"); |
|
1871 asm("rcr edx, 1"); |
|
1872 asm("inc cx"); // if carry, increment exponent |
|
1873 asm("cmp cx, 0x7FF"); // and check for overflow |
|
1874 asm("jz short trealxgettreal64d"); // branch out if overflow |
|
1875 asm("trealxgettreal64g:"); // come here to round down |
|
1876 asm("xor bl, bl"); // clear rounding bits |
|
1877 asm("and bh, 0xF8"); |
|
1878 asm("mov di, cx"); // save exponent |
|
1879 asm("mov cl, 10"); |
|
1880 asm("and edx, 0x7FFFFFFF"); // clear integer bit |
|
1881 asm("shrd ebx, edx, cl"); // shift mantissa right by 10 |
|
1882 asm("shr edx, cl"); |
|
1883 asm("shl edi, 21"); // exponent into edi bits 21-31 |
|
1884 asm("or edx, edi"); // into edx bits 21-31 |
|
1885 asm("test edx, edx"); // check if underflow |
|
1886 asm("jnz short trealxgettreal64i"); |
|
1887 asm("test ebx, ebx"); |
|
1888 asm("jz short trealxgettreal64h"); // branch out if underflow |
|
1889 asm("trealxgettreal64i:"); |
|
1890 asm("shr ecx, 17"); // sign bit->carry |
|
1891 asm("rcr edx, 1"); // ->edx bit 31, exp->edx bits 20-30, mant->edx bits 20-0 |
|
1892 asm("rcr ebx, 1"); |
|
1893 asm("xor eax, eax"); // return KErrNone |
|
1894 asm("ret"); |
|
1895 asm("trealxgettreal64z:"); // come here if zero or underflow |
|
1896 asm("xor eax, eax"); |
|
1897 asm("cmp cx, 0x8400"); // check for zero |
|
1898 asm("jz short trealxgettreal64y"); // if zero, return KErrNone |
|
1899 asm("trealxgettreal64h:"); // come here if underflow after rounding |
|
1900 asm("mov eax, -10"); // eax=KErrUnderflow |
|
1901 asm("trealxgettreal64y:"); |
|
1902 asm("xor edx, edx"); |
|
1903 asm("xor ebx, ebx"); |
|
1904 asm("shr ecx, 17"); |
|
1905 asm("rcr edx, 1"); // sign bit into edx bit 31, rest of edx=0, ebx=0 |
|
1906 asm("ret"); |
|
1907 } |
|
1908 |
|
1909 |
|
1910 |
|
1911 |
|
1912 __NAKED__ EXPORT_C TRealX::operator TReal32() const |
|
1913 /** |
|
1914 Returns the extended precision value as |
|
1915 a single precision floating point value. |
|
1916 */ |
|
1917 { |
|
1918 // On entry, ecx=this |
|
1919 // On exit, TReal32 value on top of FPU stack |
|
1920 THISCALL_PROLOG0() |
|
1921 asm("push ecx"); |
|
1922 asm("push ebx"); |
|
1923 asm("mov ebx, [ecx]"); // *this into ecx,edx:ebx |
|
1924 asm("mov edx, [ecx+4]"); |
|
1925 asm("mov ecx, [ecx+8]"); |
|
1926 asm("call %a0": : "i"(&TRealXGetTReal32)); // Convert to TReal32 in edx |
|
1927 asm("push edx"); // push TReal32 onto stack |
|
1928 asm("fld dword ptr [esp]"); // push TReal32 onto FPU stack |
|
1929 asm("pop edx"); |
|
1930 asm("pop ebx"); |
|
1931 asm("pop ecx"); |
|
1932 THISCALL_EPILOG0() |
|
1933 } |
|
1934 |
|
1935 |
|
1936 |
|
1937 |
|
1938 __NAKED__ EXPORT_C TRealX::operator TReal64() const |
|
1939 /** |
|
1940 Returns the extended precision value as |
|
1941 a double precision floating point value. |
|
1942 */ |
|
1943 { |
|
1944 // On entry, ecx=this |
|
1945 // On exit, TReal64 value on top of FPU stack |
|
1946 THISCALL_PROLOG0() |
|
1947 asm("push ecx"); |
|
1948 asm("push ebx"); |
|
1949 asm("push esi"); |
|
1950 asm("push edi"); |
|
1951 asm("mov ebx, [ecx]"); // *this into ecx,edx:ebx |
|
1952 asm("mov edx, [ecx+4]"); |
|
1953 asm("mov ecx, [ecx+8]"); |
|
1954 asm("call %a0": : "i"(&TRealXGetTReal64)); // Convert to TReal32 in edx:ebx |
|
1955 asm("push edx"); // push TReal64 onto stack |
|
1956 asm("push ebx"); |
|
1957 asm("fld qword ptr [esp]"); // push TReal64 onto FPU stack |
|
1958 asm("add esp, 8"); |
|
1959 asm("pop edi"); |
|
1960 asm("pop esi"); |
|
1961 asm("pop ebx"); |
|
1962 asm("pop ecx"); |
|
1963 THISCALL_EPILOG0() |
|
1964 } |
|
1965 |
|
1966 |
|
1967 |
|
1968 |
|
1969 __NAKED__ EXPORT_C TInt TRealX::GetTReal(TReal32& /*aVal*/) const |
|
1970 /** |
|
1971 Extracts the extended precision value as |
|
1972 a single precision floating point value. |
|
1973 |
|
1974 @param aVal A reference to a single precision object which contains |
|
1975 the result of the operation. |
|
1976 |
|
1977 @return KErrNone, if the operation is successful; |
|
1978 KErrOverflow, if the operation results in overflow; |
|
1979 KErrUnderflow, if the operation results in underflow. |
|
1980 */ |
|
1981 { |
|
1982 // On entry, ecx=this, [esp+4]=address of aVal |
|
1983 // On exit, eax=return code |
|
1984 THISCALL_PROLOG1() |
|
1985 asm("push ecx"); |
|
1986 asm("push ebx"); |
|
1987 asm("mov ebx, [ecx]"); // *this into ecx,edx:ebx |
|
1988 asm("mov edx, [ecx+4]"); |
|
1989 asm("mov ecx, [ecx+8]"); |
|
1990 asm("call %a0": : "i"(&TRealXGetTReal32)); |
|
1991 asm("mov ecx, [esp+12]"); // ecx=address of aVal |
|
1992 asm("mov [ecx], edx"); // store result |
|
1993 asm("pop ebx"); |
|
1994 asm("pop ecx"); |
|
1995 THISCALL_EPILOG1() // return with error code in eax |
|
1996 } |
|
1997 |
|
1998 |
|
1999 |
|
2000 |
|
2001 __NAKED__ EXPORT_C TInt TRealX::GetTReal(TReal64& /*aVal*/) const |
|
2002 /** |
|
2003 Extracts the extended precision value as |
|
2004 a double precision floating point value. |
|
2005 |
|
2006 @param aVal A reference to a double precision object which |
|
2007 contains the result of the operation. |
|
2008 |
|
2009 @return KErrNone, if the operation is successful; |
|
2010 KErrOverflow, if the operation results in overflow; |
|
2011 KErrUnderflow, if the operation results in underflow. |
|
2012 */ |
|
2013 { |
|
2014 // On entry, ecx=this, [esp+4]=address of aVal |
|
2015 // On exit, eax=return code |
|
2016 THISCALL_PROLOG1() |
|
2017 asm("push ecx"); |
|
2018 asm("push ebx"); |
|
2019 asm("push esi"); |
|
2020 asm("push edi"); |
|
2021 asm("mov ebx, [ecx]"); // *this into ecx,edx:ebx |
|
2022 asm("mov edx, [ecx+4]"); |
|
2023 asm("mov ecx, [ecx+8]"); |
|
2024 asm("call %a0": : "i"(&TRealXGetTReal64)); |
|
2025 asm("mov ecx, [esp+20]"); // ecx=address of aVal |
|
2026 asm("mov [ecx], ebx"); // store result |
|
2027 asm("mov [ecx+4], edx"); |
|
2028 asm("pop edi"); |
|
2029 asm("pop esi"); |
|
2030 asm("pop ebx"); |
|
2031 asm("pop ecx"); |
|
2032 THISCALL_EPILOG1() // return with error code in eax |
|
2033 } |
|
2034 |
|
2035 |
|
2036 |
|
2037 |
|
2038 __NAKED__ EXPORT_C void TRealX::SetZero(TBool /*aNegative*/) |
|
2039 /** |
|
2040 Sets the value of this extended precision object to zero. |
|
2041 |
|
2042 @param aNegative ETrue, the value is a negative zero; |
|
2043 EFalse, the value is a positive zero, this is the default. |
|
2044 */ |
|
2045 { |
|
2046 THISCALL_PROLOG1() |
|
2047 asm("mov edx, [esp+4]"); // aNegative into edx |
|
2048 asm("xor eax, eax"); // eax=0 |
|
2049 asm("mov [ecx], eax"); |
|
2050 asm("mov [ecx+4], eax"); |
|
2051 asm("test edx, edx"); |
|
2052 asm("jz short setzero1"); |
|
2053 asm("inc eax"); // eax=1 if aNegative!=0 |
|
2054 asm("setzero1:"); |
|
2055 asm("mov [ecx+8], eax"); // generate positive or negative zero |
|
2056 THISCALL_EPILOG1() |
|
2057 } |
|
2058 |
|
2059 |
|
2060 |
|
2061 |
|
2062 __NAKED__ EXPORT_C void TRealX::SetNaN() |
|
2063 /** |
|
2064 Sets the value of this extended precision object to 'not a number'. |
|
2065 */ |
|
2066 { |
|
2067 THISCALL_PROLOG0() |
|
2068 asm("xor eax, eax"); // set *this to 'real indefinite' |
|
2069 asm("mov [ecx], eax"); |
|
2070 asm("mov eax, 0xC0000000"); |
|
2071 asm("mov [ecx+4], eax"); |
|
2072 asm("mov eax, 0xFFFF0001"); |
|
2073 asm("mov [ecx+8], eax"); |
|
2074 THISCALL_EPILOG0() |
|
2075 } |
|
2076 |
|
2077 |
|
2078 |
|
2079 |
|
2080 __NAKED__ EXPORT_C void TRealX::SetInfinite(TBool /*aNegative*/) |
|
2081 /** |
|
2082 Sets the value of this extended precision object to infinity. |
|
2083 |
|
2084 @param aNegative ETrue, the value is a negative zero; |
|
2085 EFalse, the value is a positive zero. |
|
2086 */ |
|
2087 { |
|
2088 THISCALL_PROLOG1() |
|
2089 asm("mov edx, [esp+4]"); // aNegative into edx |
|
2090 asm("mov eax, 0xFFFF0000"); // exponent=FFFF, sign=0 initially |
|
2091 asm("test edx, edx"); |
|
2092 asm("jz short setinf1"); |
|
2093 asm("inc eax"); // sign=1 if aNegative!=0 |
|
2094 asm("setinf1:"); |
|
2095 asm("mov [ecx+8], eax"); |
|
2096 asm("mov eax, 0x80000000"); // generate positive or negative infinity |
|
2097 asm("mov [ecx+4], eax"); |
|
2098 asm("xor eax, eax"); |
|
2099 asm("mov [ecx], eax"); |
|
2100 THISCALL_EPILOG1() |
|
2101 } |
|
2102 |
|
2103 |
|
2104 |
|
2105 |
|
2106 __NAKED__ EXPORT_C TBool TRealX::IsZero() const |
|
2107 /** |
|
2108 Determines whether the extended precision value is zero. |
|
2109 |
|
2110 @return True, if the extended precision value is zero, false, otherwise. |
|
2111 */ |
|
2112 { |
|
2113 THISCALL_PROLOG0() |
|
2114 asm("mov eax, [ecx+8]"); // check exponent |
|
2115 asm("shr eax, 16"); // move exponent into ax |
|
2116 asm("jz short iszero1"); // branch if zero |
|
2117 asm("xor eax, eax"); // else return 0 |
|
2118 THISCALL_EPILOG0() |
|
2119 asm("iszero1:"); |
|
2120 asm("inc eax"); // if zero, return 1 |
|
2121 THISCALL_EPILOG0() |
|
2122 } |
|
2123 |
|
2124 |
|
2125 |
|
2126 |
|
2127 __NAKED__ EXPORT_C TBool TRealX::IsNaN() const |
|
2128 /** |
|
2129 Determines whether the extended precision value is 'not a number'. |
|
2130 |
|
2131 @return True, if the extended precision value is 'not a number', |
|
2132 false, otherwise. |
|
2133 */ |
|
2134 { |
|
2135 THISCALL_PROLOG0() |
|
2136 asm("mov eax, [ecx+8]"); // check exponent |
|
2137 asm("cmp eax, 0xFFFF0000"); |
|
2138 asm("jc short isnan0"); // branch if not FFFF |
|
2139 asm("mov eax, [ecx+4]"); |
|
2140 asm("cmp eax, 0x80000000"); // check for infinity |
|
2141 asm("jne short isnan1"); |
|
2142 asm("mov eax, [ecx]"); |
|
2143 asm("test eax, eax"); |
|
2144 asm("jne short isnan1"); |
|
2145 asm("isnan0:"); |
|
2146 asm("xor eax, eax"); // return 0 if not NaN |
|
2147 THISCALL_EPILOG0() |
|
2148 asm("isnan1:"); |
|
2149 asm("mov eax, 1"); // return 1 if NaN |
|
2150 THISCALL_EPILOG0() |
|
2151 } |
|
2152 |
|
2153 |
|
2154 |
|
2155 |
|
2156 __NAKED__ EXPORT_C TBool TRealX::IsInfinite() const |
|
2157 /** |
|
2158 Determines whether the extended precision value has a finite value. |
|
2159 |
|
2160 @return True, if the extended precision value is finite, |
|
2161 false, if the value is 'not a number' or is infinite, |
|
2162 */ |
|
2163 { |
|
2164 THISCALL_PROLOG0() |
|
2165 asm("mov eax, [ecx+8]"); // check exponent |
|
2166 asm("cmp eax, 0xFFFF0000"); |
|
2167 asm("jc short isinf0"); // branch if not FFFF |
|
2168 asm("mov eax, [ecx+4]"); |
|
2169 asm("cmp eax, 0x80000000"); // check for infinity |
|
2170 asm("jne short isinf0"); |
|
2171 asm("mov eax, [ecx]"); |
|
2172 asm("test eax, eax"); |
|
2173 asm("jne short isinf0"); |
|
2174 asm("inc eax"); // return 1 if infinity |
|
2175 THISCALL_EPILOG0() |
|
2176 asm("isinf0:"); |
|
2177 asm("xor eax, eax"); // return 0 if not infinity |
|
2178 THISCALL_EPILOG0() |
|
2179 } |
|
2180 |
|
2181 |
|
2182 |
|
2183 |
|
2184 __NAKED__ EXPORT_C TBool TRealX::IsFinite() const |
|
2185 /** |
|
2186 Determines whether the extended precision value has a finite value. |
|
2187 |
|
2188 @return True, if the extended precision value is finite, |
|
2189 false, if the value is 'not a number' or is infinite, |
|
2190 */ |
|
2191 { |
|
2192 THISCALL_PROLOG0() |
|
2193 asm("mov eax, [ecx+8]"); // check exponent |
|
2194 asm("cmp eax, 0xFFFF0000"); // check for NaN or infinity |
|
2195 asm("jnc short isfinite0"); // branch if NaN or infinity |
|
2196 asm("mov eax, 1"); // return 1 if finite |
|
2197 THISCALL_EPILOG0() |
|
2198 asm("isfinite0:"); |
|
2199 asm("xor eax, eax"); // return 0 if NaN or infinity |
|
2200 THISCALL_EPILOG0() |
|
2201 } |
|
2202 |
|
2203 |
|
2204 |
|
2205 |
|
2206 __NAKED__ EXPORT_C const TRealX& TRealX::operator+=(const TRealX& /*aVal*/) |
|
2207 /** |
|
2208 Adds an extended precision value to this extended precision number. |
|
2209 |
|
2210 @param aVal The extended precision value to be added. |
|
2211 |
|
2212 @return A reference to this object. |
|
2213 |
|
2214 @panic MATHX KErrOverflow if the operation results in overflow. |
|
2215 @panic MATHX KErrUnderflow if the operation results in underflow. |
|
2216 */ |
|
2217 { |
|
2218 // on entry ecx=this, [esp+4]=address of aVal |
|
2219 THISCALL_PROLOG1() |
|
2220 asm("push ebx"); // save registers |
|
2221 asm("push ebp"); |
|
2222 asm("push esi"); |
|
2223 asm("push edi"); |
|
2224 asm("mov esi, ecx"); // this into esi |
|
2225 asm("mov ecx, [esp+20]"); // address of aVal into ecx |
|
2226 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
2227 asm("mov edx, [ecx+4]"); |
|
2228 asm("mov ecx, [ecx+8]"); |
|
2229 asm("call %a0": :"i"(&TRealXAdd)); // do addition, result in ecx,edx:ebx, error code in eax |
|
2230 asm("mov [esi], ebx"); // store result in *this |
|
2231 asm("mov [esi+4], edx"); |
|
2232 asm("mov [esi+8], ecx"); |
|
2233 asm("test eax, eax"); |
|
2234 _ASM_jn(z,TRealXPanicEax) // panic if error |
|
2235 asm("mov eax, esi"); // return this in eax |
|
2236 asm("mov ecx, esi"); // restore registers |
|
2237 asm("pop edi"); |
|
2238 asm("pop esi"); |
|
2239 asm("pop ebp"); |
|
2240 asm("pop ebx"); |
|
2241 THISCALL_EPILOG1() |
|
2242 } |
|
2243 |
|
2244 |
|
2245 |
|
2246 |
|
2247 __NAKED__ EXPORT_C const TRealX& TRealX::operator-=(const TRealX& /*aVal*/) |
|
2248 /** |
|
2249 Subtracts an extended precision value from this extended precision number. |
|
2250 |
|
2251 @param aVal The extended precision value to be subtracted. |
|
2252 |
|
2253 @return A reference to this object. |
|
2254 |
|
2255 @panic MATHX KErrOverflow if the operation results in overflow. |
|
2256 @panic MATHX KErrUnderflow if the operation results in underflow. |
|
2257 */ |
|
2258 { |
|
2259 // on entry ecx=this, [esp+4]=address of aVal |
|
2260 THISCALL_PROLOG1() |
|
2261 asm("push ebx"); // save registers |
|
2262 asm("push ebp"); |
|
2263 asm("push esi"); |
|
2264 asm("push edi"); |
|
2265 asm("mov esi, ecx"); // this into esi |
|
2266 asm("mov ecx, [esp+20]"); // address of aVal into ecx |
|
2267 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
2268 asm("mov edx, [ecx+4]"); |
|
2269 asm("mov ecx, [ecx+8]"); |
|
2270 asm("call %a0": : "i"(&TRealXSubtract)); // do subtraction, result in ecx,edx:ebx, error code in eax |
|
2271 asm("mov [esi], ebx"); // store result in *this |
|
2272 asm("mov [esi+4], edx"); |
|
2273 asm("mov [esi+8], ecx"); |
|
2274 asm("test eax, eax"); |
|
2275 _ASM_jn(z,TRealXPanicEax) // panic if error |
|
2276 asm("mov eax, esi"); // return this in eax |
|
2277 asm("mov ecx, esi"); // restore registers |
|
2278 asm("pop edi"); |
|
2279 asm("pop esi"); |
|
2280 asm("pop ebp"); |
|
2281 asm("pop ebx"); |
|
2282 THISCALL_EPILOG1() |
|
2283 } |
|
2284 |
|
2285 |
|
2286 |
|
2287 |
|
2288 __NAKED__ EXPORT_C const TRealX& TRealX::operator*=(const TRealX& /*aVal*/) |
|
2289 /** |
|
2290 Multiplies this extended precision number by an extended precision value. |
|
2291 |
|
2292 @param aVal The extended precision value to be subtracted. |
|
2293 |
|
2294 @return A reference to this object. |
|
2295 |
|
2296 @panic MATHX KErrOverflow if the operation results in overflow. |
|
2297 @panic MATHX KErrUnderflow if the operation results in underflow. |
|
2298 */ |
|
2299 { |
|
2300 // on entry ecx=this, [esp+4]=address of aVal |
|
2301 THISCALL_PROLOG1() |
|
2302 asm("push ebx"); // save registers |
|
2303 asm("push ebp"); |
|
2304 asm("push esi"); |
|
2305 asm("push edi"); |
|
2306 asm("mov esi, ecx"); // esi = this |
|
2307 asm("mov ecx, [esp+20]"); // address of aVal into ecx |
|
2308 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
2309 asm("mov edx, [ecx+4]"); |
|
2310 asm("mov ecx, [ecx+8]"); |
|
2311 asm("call %a0": : "i"(&TRealXMultiply)); // do multiplication, result in ecx,edx:ebx, error code in eax |
|
2312 asm("mov [esi], ebx"); // store result in *this |
|
2313 asm("mov [esi+4], edx"); |
|
2314 asm("mov [esi+8], ecx"); |
|
2315 asm("test eax, eax"); |
|
2316 _ASM_jn(z,TRealXPanicEax) // panic if error |
|
2317 asm("mov eax, esi"); // return this in eax |
|
2318 asm("mov ecx, esi"); // restore registers |
|
2319 asm("pop edi"); |
|
2320 asm("pop esi"); |
|
2321 asm("pop ebp"); |
|
2322 asm("pop ebx"); |
|
2323 THISCALL_EPILOG1() |
|
2324 } |
|
2325 |
|
2326 |
|
2327 |
|
2328 |
|
2329 __NAKED__ EXPORT_C const TRealX& TRealX::operator/=(const TRealX& /*aVal*/) |
|
2330 /** |
|
2331 Divides this extended precision number by an extended precision value. |
|
2332 |
|
2333 @param aVal The extended precision value to be used as the divisor. |
|
2334 |
|
2335 @return A reference to this object. |
|
2336 |
|
2337 @panic MATHX KErrOverflow if the operation results in overflow. |
|
2338 @panic MATHX KErrUnderflow if the operation results in underflow. |
|
2339 @panic MATHX KErrDivideByZero if the divisor is zero. |
|
2340 */ |
|
2341 { |
|
2342 // on entry ecx=this, [esp+4]=address of aVal |
|
2343 THISCALL_PROLOG1() |
|
2344 asm("push ebx"); |
|
2345 asm("push ebp"); |
|
2346 asm("push esi"); |
|
2347 asm("push edi"); |
|
2348 asm("mov esi, ecx"); // this into esi |
|
2349 asm("mov ecx, [esp+20]"); // address of aVal into ecx |
|
2350 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
2351 asm("mov edx, [ecx+4]"); |
|
2352 asm("mov ecx, [ecx+8]"); |
|
2353 asm("call %a0": : "i"(&TRealXDivide)); // do division, result in ecx,edx:ebx, error code in eax |
|
2354 asm("mov [esi], ebx"); // store result in *this |
|
2355 asm("mov [esi+4], edx"); |
|
2356 asm("mov [esi+8], ecx"); |
|
2357 asm("test eax, eax"); |
|
2358 _ASM_jn(z,TRealXPanicEax) // panic if error |
|
2359 asm("mov eax, esi"); // return this in eax |
|
2360 asm("mov ecx, esi"); // restore registers |
|
2361 asm("pop edi"); |
|
2362 asm("pop esi"); |
|
2363 asm("pop ebp"); |
|
2364 asm("pop ebx"); |
|
2365 THISCALL_EPILOG1() |
|
2366 } |
|
2367 |
|
2368 |
|
2369 |
|
2370 |
|
2371 __NAKED__ EXPORT_C const TRealX& TRealX::operator%=(const TRealX& /*aVal*/) |
|
2372 /** |
|
2373 Modulo-divides this extended precision number by an extended precision value. |
|
2374 |
|
2375 @param aVal The extended precision value to be used as the divisor. |
|
2376 |
|
2377 @return A reference to this object. |
|
2378 |
|
2379 @panic MATHX KErrTotalLossOfPrecision panic if precision is lost. |
|
2380 @panic MATHX KErrUnderflow if the operation results in underflow. |
|
2381 */ |
|
2382 { |
|
2383 // on entry ecx=this, [esp+4]=address of aVal |
|
2384 THISCALL_PROLOG1() |
|
2385 asm("push ebx"); |
|
2386 asm("push ebp"); |
|
2387 asm("push esi"); |
|
2388 asm("push edi"); |
|
2389 asm("mov esi, ecx"); // this into esi |
|
2390 asm("mov ecx, [esp+20]"); // address of aVal into ecx |
|
2391 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
2392 asm("mov edx, [ecx+4]"); |
|
2393 asm("mov ecx, [ecx+8]"); |
|
2394 asm("call %a0": : "i"(&TRealXModulo)); // do modulo, result in ecx,edx:ebx, error code in eax |
|
2395 asm("mov [esi], ebx"); // store result in *this |
|
2396 asm("mov [esi+4], edx"); |
|
2397 asm("mov [esi+8], ecx"); |
|
2398 asm("test eax, eax"); |
|
2399 _ASM_jn(z,TRealXPanicEax) // panic if error |
|
2400 asm("mov eax, esi"); // return this in eax |
|
2401 asm("mov ecx, esi"); // restore registers |
|
2402 asm("pop edi"); |
|
2403 asm("pop esi"); |
|
2404 asm("pop ebp"); |
|
2405 asm("pop ebx"); |
|
2406 THISCALL_EPILOG1() |
|
2407 } |
|
2408 |
|
2409 |
|
2410 |
|
2411 |
|
2412 __NAKED__ EXPORT_C TInt TRealX::AddEq(const TRealX& /*aVal*/) |
|
2413 /** |
|
2414 Adds an extended precision value to this extended precision number. |
|
2415 |
|
2416 @param aVal The extended precision value to be added. |
|
2417 |
|
2418 @return KErrNone, if the operation is successful; |
|
2419 KErrOverflow,if the operation results in overflow; |
|
2420 KErrUnderflow, if the operation results in underflow. |
|
2421 */ |
|
2422 { |
|
2423 // on entry ecx=this, [esp+4]=address of aVal |
|
2424 THISCALL_PROLOG1() |
|
2425 asm("push ebx"); // save registers |
|
2426 asm("push ebp"); |
|
2427 asm("push esi"); |
|
2428 asm("push edi"); |
|
2429 asm("mov esi, ecx"); // this into esi |
|
2430 asm("mov ecx, [esp+20]"); // address of aVal into ecx |
|
2431 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
2432 asm("mov edx, [ecx+4]"); |
|
2433 asm("mov ecx, [ecx+8]"); |
|
2434 asm("call %a0": :"i"(&TRealXAdd)); // do addition, result in ecx,edx:ebx, error code in eax |
|
2435 asm("mov [esi], ebx"); // store result |
|
2436 asm("mov [esi+4], edx"); |
|
2437 asm("mov [esi+8], ecx"); |
|
2438 asm("mov ecx, esi"); // restore registers |
|
2439 asm("pop edi"); |
|
2440 asm("pop esi"); |
|
2441 asm("pop ebp"); |
|
2442 asm("pop ebx"); |
|
2443 THISCALL_EPILOG1() // return with error code in eax |
|
2444 } |
|
2445 |
|
2446 |
|
2447 |
|
2448 |
|
2449 __NAKED__ EXPORT_C TInt TRealX::SubEq(const TRealX& /*aVal*/) |
|
2450 /** |
|
2451 Subtracts an extended precision value from this extended precision number. |
|
2452 |
|
2453 @param aVal The extended precision value to be subtracted. |
|
2454 |
|
2455 @return KErrNone, if the operation is successful; |
|
2456 KErrOverflow, if the operation results in overflow; |
|
2457 KErrUnderflow, if the operation results in underflow. |
|
2458 */ |
|
2459 { |
|
2460 // on entry ecx=this, [esp+4]=address of aVal |
|
2461 THISCALL_PROLOG1() |
|
2462 asm("push ebx"); // save registers |
|
2463 asm("push ebp"); |
|
2464 asm("push esi"); |
|
2465 asm("push edi"); |
|
2466 asm("mov esi, ecx"); // this into esi |
|
2467 asm("mov ecx, [esp+20]"); // address of aVal into ecx |
|
2468 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
2469 asm("mov edx, [ecx+4]"); |
|
2470 asm("mov ecx, [ecx+8]"); |
|
2471 asm("call %a0": : "i"(&TRealXSubtract)); // do subtraction, result in ecx,edx:ebx, error code in eax |
|
2472 asm("mov [esi], ebx"); // store result |
|
2473 asm("mov [esi+4], edx"); |
|
2474 asm("mov [esi+8], ecx"); |
|
2475 asm("mov ecx, esi"); // restore registers |
|
2476 asm("pop edi"); |
|
2477 asm("pop esi"); |
|
2478 asm("pop ebp"); |
|
2479 asm("pop ebx"); |
|
2480 THISCALL_EPILOG1() // return with error code in eax |
|
2481 } |
|
2482 |
|
2483 |
|
2484 |
|
2485 |
|
2486 __NAKED__ EXPORT_C TInt TRealX::MultEq(const TRealX& /*aVal*/) |
|
2487 /** |
|
2488 Multiplies this extended precision number by an extended precision value. |
|
2489 |
|
2490 @param aVal The extended precision value to be used as the multiplier. |
|
2491 |
|
2492 @return KErrNone, if the operation is successful; |
|
2493 KErrOverflow, if the operation results in overflow; |
|
2494 KErrUnderflow, if the operation results in underflow |
|
2495 */ |
|
2496 { |
|
2497 // on entry ecx=this, [esp+4]=address of aVal |
|
2498 THISCALL_PROLOG1() |
|
2499 asm("push ebx"); // save registers |
|
2500 asm("push ebp"); |
|
2501 asm("push esi"); |
|
2502 asm("push edi"); |
|
2503 asm("mov esi, ecx"); // this into esi |
|
2504 asm("mov ecx, [esp+20]"); // address of aVal into ecx |
|
2505 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
2506 asm("mov edx, [ecx+4]"); |
|
2507 asm("mov ecx, [ecx+8]"); |
|
2508 asm("call %a0": : "i"(&TRealXMultiply)); // do multiplication, result in ecx,edx:ebx, error code in eax |
|
2509 asm("mov [esi], ebx"); // store result |
|
2510 asm("mov [esi+4], edx"); |
|
2511 asm("mov [esi+8], ecx"); |
|
2512 asm("mov ecx, esi"); // restore registers |
|
2513 asm("pop edi"); |
|
2514 asm("pop esi"); |
|
2515 asm("pop ebp"); |
|
2516 asm("pop ebx"); |
|
2517 THISCALL_EPILOG1() // return with error code in eax |
|
2518 } |
|
2519 |
|
2520 |
|
2521 |
|
2522 |
|
2523 __NAKED__ EXPORT_C TInt TRealX::DivEq(const TRealX& /*aVal*/) |
|
2524 /** |
|
2525 Divides this extended precision number by an extended precision value. |
|
2526 |
|
2527 @param aVal The extended precision value to be used as the divisor. |
|
2528 |
|
2529 @return KErrNone, if the operation is successful; |
|
2530 KErrOverflow, if the operation results in overflow; |
|
2531 KErrUnderflow, if the operation results in underflow; |
|
2532 KErrDivideByZero, if the divisor is zero. |
|
2533 */ |
|
2534 { |
|
2535 // on entry ecx=this, [esp+4]=address of aVal |
|
2536 THISCALL_PROLOG1() |
|
2537 asm("push ebx"); // save registers |
|
2538 asm("push ebp"); |
|
2539 asm("push esi"); |
|
2540 asm("push edi"); |
|
2541 asm("mov esi, ecx"); // this into esi |
|
2542 asm("mov ecx, [esp+20]"); // address of aVal into ecx |
|
2543 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
2544 asm("mov edx, [ecx+4]"); |
|
2545 asm("mov ecx, [ecx+8]"); |
|
2546 asm("call %a0": : "i"(&TRealXDivide)); // do division, result in ecx,edx:ebx, error code in eax |
|
2547 asm("mov [esi], ebx"); // store result |
|
2548 asm("mov [esi+4], edx"); |
|
2549 asm("mov [esi+8], ecx"); |
|
2550 asm("mov ecx, esi"); // restore registers |
|
2551 asm("pop edi"); |
|
2552 asm("pop esi"); |
|
2553 asm("pop ebp"); |
|
2554 asm("pop ebx"); |
|
2555 THISCALL_EPILOG1() // return with error code in eax |
|
2556 } |
|
2557 |
|
2558 |
|
2559 |
|
2560 |
|
2561 __NAKED__ EXPORT_C TInt TRealX::ModEq(const TRealX& /*aVal*/) |
|
2562 /** |
|
2563 Modulo-divides this extended precision number by an extended precision value. |
|
2564 |
|
2565 @param aVal The extended precision value to be used as the divisor. |
|
2566 |
|
2567 @return KErrNone, if the operation is successful; |
|
2568 KErrTotalLossOfPrecision, if precision is lost; |
|
2569 KErrUnderflow, if the operation results in underflow. |
|
2570 */ |
|
2571 { |
|
2572 // on entry ecx=this, [esp+4]=address of aVal |
|
2573 THISCALL_PROLOG1() |
|
2574 asm("push ebx"); // save registers |
|
2575 asm("push ebp"); |
|
2576 asm("push esi"); |
|
2577 asm("push edi"); |
|
2578 asm("mov esi, ecx"); // this into esi |
|
2579 asm("mov ecx, [esp+20]"); // address of aVal into ecx |
|
2580 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
2581 asm("mov edx, [ecx+4]"); |
|
2582 asm("mov ecx, [ecx+8]"); |
|
2583 asm("call %a0": : "i"(&TRealXModulo)); // do modulo, result in ecx,edx:ebx, error code in eax |
|
2584 asm("mov [esi], ebx"); // store result |
|
2585 asm("mov [esi+4], edx"); |
|
2586 asm("mov [esi+8], ecx"); |
|
2587 asm("mov ecx, esi"); // restore registers |
|
2588 asm("pop edi"); |
|
2589 asm("pop esi"); |
|
2590 asm("pop ebp"); |
|
2591 asm("pop ebx"); |
|
2592 THISCALL_EPILOG1() // return with error code in eax |
|
2593 } |
|
2594 |
|
2595 |
|
2596 |
|
2597 |
|
2598 __NAKED__ EXPORT_C TRealX TRealX::operator+() const |
|
2599 /** |
|
2600 Returns this extended precision number unchanged. |
|
2601 |
|
2602 Note that this may also be referred to as a unary plus operator. |
|
2603 |
|
2604 @return The extended precision number. |
|
2605 */ |
|
2606 { |
|
2607 THISCALL_PROLOG0_BIGRETVAL() |
|
2608 asm("mov eax, [esp+4]"); // eax=address to write return value |
|
2609 asm("mov edx, [ecx]"); |
|
2610 asm("mov [eax], edx"); |
|
2611 asm("mov edx, [ecx+4]"); |
|
2612 asm("mov [eax+4], edx"); |
|
2613 asm("mov edx, [ecx+8]"); |
|
2614 asm("mov [eax+8], edx"); // return address of return value in eax |
|
2615 THISCALL_EPILOG0_BIGRETVAL() |
|
2616 } |
|
2617 |
|
2618 |
|
2619 |
|
2620 |
|
2621 __NAKED__ EXPORT_C TRealX TRealX::operator-() const |
|
2622 /** |
|
2623 Negates this extended precision number. |
|
2624 |
|
2625 This may also be referred to as a unary minus operator. |
|
2626 |
|
2627 @return The negative of the extended precision number. |
|
2628 */ |
|
2629 { |
|
2630 THISCALL_PROLOG0_BIGRETVAL() |
|
2631 asm("mov eax, [esp+4]"); // eax=address to write return value |
|
2632 asm("mov edx, [ecx]"); |
|
2633 asm("mov [eax], edx"); |
|
2634 asm("mov edx, [ecx+4]"); |
|
2635 asm("mov [eax+4], edx"); |
|
2636 asm("mov edx, [ecx+8]"); |
|
2637 asm("xor dl, 1"); // change sign bit |
|
2638 asm("mov [eax+8], edx"); |
|
2639 THISCALL_EPILOG0_BIGRETVAL() // return address of return value in eax |
|
2640 } |
|
2641 |
|
2642 |
|
2643 |
|
2644 |
|
2645 __NAKED__ EXPORT_C TRealX& TRealX::operator++() |
|
2646 /** |
|
2647 Increments this extended precision number by one, |
|
2648 and then returns a reference to it. |
|
2649 |
|
2650 This is also referred to as a prefix operator. |
|
2651 |
|
2652 @return A reference to this object. |
|
2653 |
|
2654 @panic MATHX KErrOverflow if the operation results in overflow. |
|
2655 @panic MATHX KErrUnderflow if the operation results in underflow. |
|
2656 */ |
|
2657 { |
|
2658 // pre-increment |
|
2659 // on entry ecx=this, return this in eax |
|
2660 THISCALL_PROLOG0() |
|
2661 asm("push ebx"); // save registers |
|
2662 asm("push ebp"); |
|
2663 asm("push esi"); |
|
2664 asm("push edi"); |
|
2665 asm("mov esi, ecx"); // this into esi |
|
2666 asm("mov ecx, 0x7FFF0000"); // set ecx,edx:ebx to 1.0 |
|
2667 asm("mov edx, 0x80000000"); |
|
2668 asm("xor ebx, ebx"); |
|
2669 asm("call %a0": :"i"(&TRealXAdd)); // add 1 to *this |
|
2670 asm("mov [esi], ebx"); // store result |
|
2671 asm("mov [esi+4], edx"); |
|
2672 asm("mov [esi+8], ecx"); |
|
2673 asm("test eax, eax"); // check error code |
|
2674 _ASM_jn(z,TRealXPanicEax) // panic if error |
|
2675 asm("mov eax, esi"); // else return this in eax |
|
2676 asm("mov ecx, esi"); |
|
2677 asm("pop edi"); |
|
2678 asm("pop esi"); |
|
2679 asm("pop ebp"); |
|
2680 asm("pop ebx"); |
|
2681 THISCALL_EPILOG0() |
|
2682 } |
|
2683 |
|
2684 |
|
2685 |
|
2686 |
|
2687 __NAKED__ EXPORT_C TRealX TRealX::operator++(TInt) |
|
2688 /** |
|
2689 Returns this extended precision number before incrementing it by one. |
|
2690 |
|
2691 This is also referred to as a postfix operator. |
|
2692 |
|
2693 @return A reference to this object. |
|
2694 |
|
2695 @panic MATHX KErrOverflow if the operation results in overflow. |
|
2696 @panic MATHX KErrUnderflow if the operation results in underflow. |
|
2697 */ |
|
2698 { |
|
2699 // post-increment |
|
2700 // on entry ecx=this, [esp+4]=address of return value, [esp+8]=dummy int |
|
2701 THISCALL_PROLOG1_BIGRETVAL() |
|
2702 asm("push ebx"); // save registers |
|
2703 asm("push ebp"); |
|
2704 asm("push esi"); |
|
2705 asm("push edi"); |
|
2706 asm("mov esi, ecx"); // this into esi |
|
2707 asm("mov edi, [esp+20]"); // address of return value into edi |
|
2708 asm("mov eax, [ecx]"); // copy initial value of *this into [edi] |
|
2709 asm("mov [edi], eax"); |
|
2710 asm("mov eax, [ecx+4]"); |
|
2711 asm("mov [edi+4], eax"); |
|
2712 asm("mov eax, [ecx+8]"); |
|
2713 asm("mov [edi+8], eax"); |
|
2714 asm("mov ecx, 0x7FFF0000"); // set ecx,edx:ebx to 1.0 |
|
2715 asm("mov edx, 0x80000000"); |
|
2716 asm("xor ebx, ebx"); |
|
2717 asm("call %a0": :"i"(&TRealXAdd)); // add 1 to *this |
|
2718 asm("mov [esi], ebx"); // store result in *this |
|
2719 asm("mov [esi+4], edx"); |
|
2720 asm("mov [esi+8], ecx"); |
|
2721 asm("test eax, eax"); // check error code |
|
2722 _ASM_jn(z,TRealXPanicEax) // panic if error |
|
2723 asm("mov eax, [esp+20]"); // address of return value into eax |
|
2724 asm("mov ecx, esi"); |
|
2725 asm("pop edi"); |
|
2726 asm("pop esi"); |
|
2727 asm("pop ebp"); |
|
2728 asm("pop ebx"); |
|
2729 THISCALL_EPILOG1_BIGRETVAL() |
|
2730 } |
|
2731 |
|
2732 |
|
2733 |
|
2734 |
|
2735 __NAKED__ EXPORT_C TRealX& TRealX::operator--() |
|
2736 /** |
|
2737 Decrements this extended precision number by one, |
|
2738 and then returns a reference to it. |
|
2739 |
|
2740 This is also referred to as a prefix operator. |
|
2741 |
|
2742 @return A reference to this object. |
|
2743 |
|
2744 @panic MATHX KErrOverflow if the operation results in overflow. |
|
2745 @panic MATHX KErrUnderflow if the operation results in underflow. |
|
2746 */ |
|
2747 { |
|
2748 // pre-decrement |
|
2749 // on entry ecx=this, return this in eax |
|
2750 THISCALL_PROLOG0() |
|
2751 asm("push ebx"); // save registers |
|
2752 asm("push ebp"); |
|
2753 asm("push esi"); |
|
2754 asm("push edi"); |
|
2755 asm("mov esi, ecx"); // this into esi |
|
2756 asm("mov ecx, 0x7FFF0001"); // set ecx,edx:ebx to -1.0 |
|
2757 asm("mov edx, 0x80000000"); |
|
2758 asm("xor ebx, ebx"); |
|
2759 asm("call %a0": :"i"(&TRealXAdd)); // add -1 to *this |
|
2760 asm("mov [esi], ebx"); // store result |
|
2761 asm("mov [esi+4], edx"); |
|
2762 asm("mov [esi+8], ecx"); |
|
2763 asm("test eax, eax"); // check error code |
|
2764 _ASM_jn(z,TRealXPanicEax) // panic if error |
|
2765 asm("mov eax, esi"); // else return this in eax |
|
2766 asm("mov ecx, esi"); |
|
2767 asm("pop edi"); |
|
2768 asm("pop esi"); |
|
2769 asm("pop ebp"); |
|
2770 asm("pop ebx"); |
|
2771 THISCALL_EPILOG0() |
|
2772 } |
|
2773 |
|
2774 |
|
2775 |
|
2776 |
|
2777 __NAKED__ EXPORT_C TRealX TRealX::operator--(TInt) |
|
2778 /** |
|
2779 Returns this extended precision number before decrementing it by one. |
|
2780 |
|
2781 This is also referred to as a postfix operator. |
|
2782 |
|
2783 @return A reference to this object. |
|
2784 |
|
2785 @panic MATHX KErrOverflow if the operation results in overflow. |
|
2786 @panic MATHX KErrUnderflow if the operation results in underflow. |
|
2787 */ |
|
2788 { |
|
2789 // post-decrement |
|
2790 // on entry ecx=this, [esp+4]=address of return value, [esp+8]=dummy int |
|
2791 THISCALL_PROLOG1_BIGRETVAL() |
|
2792 asm("push ebx"); // save registers |
|
2793 asm("push ebp"); |
|
2794 asm("push esi"); |
|
2795 asm("push edi"); |
|
2796 asm("mov esi, ecx"); // this into esi |
|
2797 asm("mov edi, [esp+20]"); // address of return value into edi |
|
2798 asm("mov eax, [ecx]"); // copy initial value of *this into [edi] |
|
2799 asm("mov [edi], eax"); |
|
2800 asm("mov eax, [ecx+4]"); |
|
2801 asm("mov [edi+4], eax"); |
|
2802 asm("mov eax, [ecx+8]"); |
|
2803 asm("mov [edi+8], eax"); |
|
2804 asm("mov ecx, 0x7FFF0001"); // set ecx,edx:ebx to -1.0 |
|
2805 asm("mov edx, 0x80000000"); |
|
2806 asm("xor ebx, ebx"); |
|
2807 asm("call %a0": :"i"(&TRealXAdd)); // add -1 to *this |
|
2808 asm("mov [esi], ebx"); // store result in *this |
|
2809 asm("mov [esi+4], edx"); |
|
2810 asm("mov [esi+8], ecx"); |
|
2811 asm("test eax, eax"); // check error code |
|
2812 _ASM_jn(z,TRealXPanicEax) // panic if error |
|
2813 asm("mov eax, [esp+20]"); // address of return value into eax |
|
2814 asm("mov ecx, esi"); |
|
2815 asm("pop edi"); |
|
2816 asm("pop esi"); |
|
2817 asm("pop ebp"); |
|
2818 asm("pop ebx"); |
|
2819 THISCALL_EPILOG1_BIGRETVAL() |
|
2820 } |
|
2821 |
|
2822 |
|
2823 |
|
2824 |
|
2825 __NAKED__ EXPORT_C TRealX TRealX::operator+(const TRealX& /*aVal*/) const |
|
2826 /** |
|
2827 Adds an extended precision value to this extended precision number. |
|
2828 |
|
2829 @param aVal The extended precision value to be added. |
|
2830 |
|
2831 @return An extended precision object containing the result. |
|
2832 |
|
2833 @panic MATHX KErrOverflow if the operation results in overflow. |
|
2834 @panic MATHX KErrUnderflow if the operation results in underflow. |
|
2835 */ |
|
2836 { |
|
2837 // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal |
|
2838 THISCALL_PROLOG1_BIGRETVAL() |
|
2839 asm("push ecx"); // save registers |
|
2840 asm("push ebx"); |
|
2841 asm("push ebp"); |
|
2842 asm("push esi"); |
|
2843 asm("push edi"); |
|
2844 asm("mov esi, ecx"); // this into esi |
|
2845 asm("mov ecx, [esp+28]"); // address of aVal into ecx |
|
2846 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
2847 asm("mov edx, [ecx+4]"); |
|
2848 asm("mov ecx, [ecx+8]"); |
|
2849 asm("call %a0": :"i"(&TRealXAdd)); // do addition, result in ecx,edx:ebx, error code in eax |
|
2850 asm("mov esi, [esp+24]"); // esi=address of return value |
|
2851 asm("mov [esi], ebx"); // store result |
|
2852 asm("mov [esi+4], edx"); |
|
2853 asm("mov [esi+8], ecx"); |
|
2854 asm("test eax, eax"); |
|
2855 _ASM_jn(z,TRealXPanicEax) // panic if error |
|
2856 asm("mov eax, esi"); // return address of return value in eax |
|
2857 asm("pop edi"); // restore registers |
|
2858 asm("pop esi"); |
|
2859 asm("pop ebp"); |
|
2860 asm("pop ebx"); |
|
2861 asm("pop ecx"); |
|
2862 THISCALL_EPILOG1_BIGRETVAL() |
|
2863 } |
|
2864 |
|
2865 |
|
2866 |
|
2867 |
|
2868 __NAKED__ EXPORT_C TRealX TRealX::operator-(const TRealX& /*aVal*/) const |
|
2869 /** |
|
2870 Subtracts an extended precision value from this extended precision number. |
|
2871 |
|
2872 @param aVal The extended precision value to be subtracted. |
|
2873 |
|
2874 @return An extended precision object containing the result. |
|
2875 |
|
2876 @panic MATHX KErrOverflow if the operation results in overflow. |
|
2877 @panic MATHX KErrUnderflow if the operation results in underflow. |
|
2878 */ |
|
2879 { |
|
2880 // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal |
|
2881 THISCALL_PROLOG1_BIGRETVAL() |
|
2882 asm("push ecx"); // save registers |
|
2883 asm("push ebx"); |
|
2884 asm("push ebp"); |
|
2885 asm("push esi"); |
|
2886 asm("push edi"); |
|
2887 asm("mov esi, ecx"); // this into esi |
|
2888 asm("mov ecx, [esp+28]"); // address of aVal into ecx |
|
2889 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
2890 asm("mov edx, [ecx+4]"); |
|
2891 asm("mov ecx, [ecx+8]"); |
|
2892 asm("call %a0": : "i"(&TRealXSubtract)); // do subtraction, result in ecx,edx:ebx, error code in eax |
|
2893 asm("mov esi, [esp+24]"); // esi=address of return value |
|
2894 asm("mov [esi], ebx"); // store result |
|
2895 asm("mov [esi+4], edx"); |
|
2896 asm("mov [esi+8], ecx"); |
|
2897 asm("test eax, eax"); |
|
2898 _ASM_jn(z,TRealXPanicEax) // panic if error |
|
2899 asm("mov eax, esi"); // return address of return value in eax |
|
2900 asm("pop edi"); // restore registers |
|
2901 asm("pop esi"); |
|
2902 asm("pop ebp"); |
|
2903 asm("pop ebx"); |
|
2904 asm("pop ecx"); |
|
2905 THISCALL_EPILOG1_BIGRETVAL() |
|
2906 } |
|
2907 |
|
2908 |
|
2909 |
|
2910 |
|
2911 __NAKED__ EXPORT_C TRealX TRealX::operator*(const TRealX& /*aVal*/) const |
|
2912 /** |
|
2913 Multiplies this extended precision number by an extended precision value. |
|
2914 |
|
2915 @param aVal The extended precision value to be used as the multiplier. |
|
2916 |
|
2917 @return An extended precision object containing the result. |
|
2918 |
|
2919 @panic MATHX KErrOverflow if the operation results in overflow. |
|
2920 @panic MATHX KErrUnderflow if the operation results in underflow. |
|
2921 */ |
|
2922 { |
|
2923 // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal |
|
2924 THISCALL_PROLOG1_BIGRETVAL() |
|
2925 asm("push ecx"); // save registers |
|
2926 asm("push ebx"); |
|
2927 asm("push ebp"); |
|
2928 asm("push esi"); |
|
2929 asm("push edi"); |
|
2930 asm("mov esi, ecx"); // this into esi |
|
2931 asm("mov ecx, [esp+28]"); // address of aVal into ecx |
|
2932 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
2933 asm("mov edx, [ecx+4]"); |
|
2934 asm("mov ecx, [ecx+8]"); |
|
2935 asm("call %a0": : "i"(&TRealXMultiply)); // do multiplication, result in ecx,edx:ebx, error code in eax |
|
2936 asm("mov esi, [esp+24]"); // esi=address of return value |
|
2937 asm("mov [esi], ebx"); // store result |
|
2938 asm("mov [esi+4], edx"); |
|
2939 asm("mov [esi+8], ecx"); |
|
2940 asm("test eax, eax"); |
|
2941 _ASM_jn(z,TRealXPanicEax) // panic if error |
|
2942 asm("mov eax, esi"); // return address of return value in eax |
|
2943 asm("pop edi"); // restore registers |
|
2944 asm("pop esi"); |
|
2945 asm("pop ebp"); |
|
2946 asm("pop ebx"); |
|
2947 asm("pop ecx"); |
|
2948 THISCALL_EPILOG1_BIGRETVAL() |
|
2949 } |
|
2950 |
|
2951 |
|
2952 |
|
2953 |
|
2954 __NAKED__ EXPORT_C TRealX TRealX::operator/(const TRealX& /*aVal*/) const |
|
2955 /** |
|
2956 Divides this extended precision number by an extended precision value. |
|
2957 |
|
2958 @param aVal The extended precision value to be used as the divisor. |
|
2959 |
|
2960 @return An extended precision object containing the result. |
|
2961 |
|
2962 @panic MATHX KErrOverflow if the operation results in overflow. |
|
2963 @panic MATHX KErrUnderflow if the operation results in underflow. |
|
2964 @panic MATHX KErrDivideByZero if the divisor is zero. |
|
2965 */ |
|
2966 { |
|
2967 // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal |
|
2968 THISCALL_PROLOG1_BIGRETVAL() |
|
2969 asm("push ecx"); // save registers |
|
2970 asm("push ebx"); |
|
2971 asm("push ebp"); |
|
2972 asm("push esi"); |
|
2973 asm("push edi"); |
|
2974 asm("mov esi, ecx"); // this into esi |
|
2975 asm("mov ecx, [esp+28]"); // address of aVal into ecx |
|
2976 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
2977 asm("mov edx, [ecx+4]"); |
|
2978 asm("mov ecx, [ecx+8]"); |
|
2979 asm("call %a0": : "i"(&TRealXDivide)); // do division, result in ecx,edx:ebx, error code in eax |
|
2980 asm("mov esi, [esp+24]"); // esi=address of return value |
|
2981 asm("mov [esi], ebx"); // store result |
|
2982 asm("mov [esi+4], edx"); |
|
2983 asm("mov [esi+8], ecx"); |
|
2984 asm("test eax, eax"); |
|
2985 _ASM_jn(z,TRealXPanicEax) // panic if error |
|
2986 asm("mov eax, esi"); // return address of return value in eax |
|
2987 asm("pop edi"); // restore registers |
|
2988 asm("pop esi"); |
|
2989 asm("pop ebp"); |
|
2990 asm("pop ebx"); |
|
2991 asm("pop ecx"); |
|
2992 THISCALL_EPILOG1_BIGRETVAL() |
|
2993 } |
|
2994 |
|
2995 |
|
2996 |
|
2997 |
|
2998 __NAKED__ EXPORT_C TRealX TRealX::operator%(const TRealX& /*aVal*/) const |
|
2999 /** |
|
3000 Modulo-divides this extended precision number by an extended precision value. |
|
3001 |
|
3002 @param aVal The extended precision value to be used as the divisor. |
|
3003 |
|
3004 @return An extended precision object containing the result. |
|
3005 |
|
3006 @panic MATHX KErrTotalLossOfPrecision if precision is lost. |
|
3007 @panic MATHX KErrUnderflow if the operation results in underflow. |
|
3008 */ |
|
3009 { |
|
3010 // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal |
|
3011 THISCALL_PROLOG1_BIGRETVAL() |
|
3012 asm("push ecx"); // save registers |
|
3013 asm("push ebx"); |
|
3014 asm("push ebp"); |
|
3015 asm("push esi"); |
|
3016 asm("push edi"); |
|
3017 asm("mov esi, ecx"); // this into esi |
|
3018 asm("mov ecx, [esp+28]"); // address of aVal into ecx |
|
3019 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
3020 asm("mov edx, [ecx+4]"); |
|
3021 asm("mov ecx, [ecx+8]"); |
|
3022 asm("call %a0": : "i"(&TRealXModulo)); // do modulo, result in ecx,edx:ebx, error code in eax |
|
3023 asm("mov esi, [esp+24]"); // esi=address of return value |
|
3024 asm("mov [esi], ebx"); // store result |
|
3025 asm("mov [esi+4], edx"); |
|
3026 asm("mov [esi+8], ecx"); |
|
3027 asm("test eax, eax"); |
|
3028 _ASM_jn(z,TRealXPanicEax) // panic if error |
|
3029 asm("mov eax, esi"); // return address of return value in eax |
|
3030 asm("pop edi"); // restore registers |
|
3031 asm("pop esi"); |
|
3032 asm("pop ebp"); |
|
3033 asm("pop ebx"); |
|
3034 asm("pop ecx"); |
|
3035 THISCALL_EPILOG1_BIGRETVAL() |
|
3036 } |
|
3037 |
|
3038 |
|
3039 |
|
3040 |
|
3041 __NAKED__ EXPORT_C TInt TRealX::Add(TRealX& /*aResult*/, const TRealX& /*aVal*/) const |
|
3042 /** |
|
3043 Adds an extended precision value to this extended precision number. |
|
3044 |
|
3045 @param aResult On return, a reference to an extended precision object |
|
3046 containing the result of the operation. |
|
3047 @param aVal The extended precision value to be added. |
|
3048 |
|
3049 @return KErrNone, if the operation is successful; |
|
3050 KErrOverflow, if the operation results in overflow; |
|
3051 KErrUnderflow, if the operation results in underflow. |
|
3052 */ |
|
3053 { |
|
3054 // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal |
|
3055 THISCALL_PROLOG2() |
|
3056 asm("push ecx"); // save registers |
|
3057 asm("push ebx"); |
|
3058 asm("push ebp"); |
|
3059 asm("push esi"); |
|
3060 asm("push edi"); |
|
3061 asm("mov esi, ecx"); // this into esi |
|
3062 asm("mov ecx, [esp+28]"); // address of aVal into ecx |
|
3063 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
3064 asm("mov edx, [ecx+4]"); |
|
3065 asm("mov ecx, [ecx+8]"); |
|
3066 asm("call %a0": :"i"(&TRealXAdd)); // do addition, result in ecx,edx:ebx, error code in eax |
|
3067 asm("mov esi, [esp+24]"); // esi=address of aResult |
|
3068 asm("mov [esi], ebx"); // store result |
|
3069 asm("mov [esi+4], edx"); |
|
3070 asm("mov [esi+8], ecx"); |
|
3071 asm("pop edi"); // restore registers |
|
3072 asm("pop esi"); |
|
3073 asm("pop ebp"); |
|
3074 asm("pop ebx"); |
|
3075 asm("pop ecx"); |
|
3076 THISCALL_EPILOG2() // return with error code in eax |
|
3077 } |
|
3078 |
|
3079 |
|
3080 |
|
3081 |
|
3082 __NAKED__ EXPORT_C TInt TRealX::Sub(TRealX& /*aResult*/, const TRealX& /*aVal*/) const |
|
3083 /** |
|
3084 Subtracts an extended precision value from this extended precision number. |
|
3085 |
|
3086 @param aResult On return, a reference to an extended precision object |
|
3087 containing the result of the operation. |
|
3088 @param aVal The extended precision value to be subtracted. |
|
3089 |
|
3090 @return KErrNone, if the operation is successful; |
|
3091 KErrOverflow, if the operation results in overflow; |
|
3092 KErrUnderflow, if the operation results in underflow. |
|
3093 */ |
|
3094 { |
|
3095 // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal |
|
3096 THISCALL_PROLOG2() |
|
3097 asm("push ecx"); // save registers |
|
3098 asm("push ebx"); |
|
3099 asm("push ebp"); |
|
3100 asm("push esi"); |
|
3101 asm("push edi"); |
|
3102 asm("mov esi, ecx"); // this into esi |
|
3103 asm("mov ecx, [esp+28]"); // address of aVal into ecx |
|
3104 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
3105 asm("mov edx, [ecx+4]"); |
|
3106 asm("mov ecx, [ecx+8]"); |
|
3107 asm("call %a0": : "i"(&TRealXSubtract)); // do subtraction, result in ecx,edx:ebx, error code in eax |
|
3108 asm("mov esi, [esp+24]"); // esi=address of aResult |
|
3109 asm("mov [esi], ebx"); // store result |
|
3110 asm("mov [esi+4], edx"); |
|
3111 asm("mov [esi+8], ecx"); |
|
3112 asm("pop edi"); // restore registers |
|
3113 asm("pop esi"); |
|
3114 asm("pop ebp"); |
|
3115 asm("pop ebx"); |
|
3116 asm("pop ecx"); |
|
3117 THISCALL_EPILOG2() // return with error code in eax |
|
3118 } |
|
3119 |
|
3120 |
|
3121 |
|
3122 |
|
3123 __NAKED__ EXPORT_C TInt TRealX::Mult(TRealX& /*aResult*/, const TRealX& /*aVal*/) const |
|
3124 /** |
|
3125 Multiplies this extended precision number by an extended precision value. |
|
3126 |
|
3127 @param aResult On return, a reference to an extended precision object |
|
3128 containing the result of the operation. |
|
3129 @param aVal The extended precision value to be used as the multiplier. |
|
3130 |
|
3131 @return KErrNone, if the operation is successful; |
|
3132 KErrOverflow, if the operation results in overflow; |
|
3133 KErrUnderflow, if the operation results in underflow. |
|
3134 */ |
|
3135 { |
|
3136 // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal |
|
3137 THISCALL_PROLOG2() |
|
3138 asm("push ecx"); // save registers |
|
3139 asm("push ebx"); |
|
3140 asm("push ebp"); |
|
3141 asm("push esi"); |
|
3142 asm("push edi"); |
|
3143 asm("mov esi, ecx"); // this into esi |
|
3144 asm("mov ecx, [esp+28]"); // address of aVal into ecx |
|
3145 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
3146 asm("mov edx, [ecx+4]"); |
|
3147 asm("mov ecx, [ecx+8]"); |
|
3148 asm("call %a0": : "i"(&TRealXMultiply)); // do multiplication, result in ecx,edx:ebx, error code in eax |
|
3149 asm("mov esi, [esp+24]"); // esi=address of aResult |
|
3150 asm("mov [esi], ebx"); // store result |
|
3151 asm("mov [esi+4], edx"); |
|
3152 asm("mov [esi+8], ecx"); |
|
3153 asm("pop edi"); // restore registers |
|
3154 asm("pop esi"); |
|
3155 asm("pop ebp"); |
|
3156 asm("pop ebx"); |
|
3157 asm("pop ecx"); |
|
3158 THISCALL_EPILOG2() // return with error code in eax |
|
3159 } |
|
3160 |
|
3161 |
|
3162 |
|
3163 __NAKED__ EXPORT_C TInt TRealX::Div(TRealX& /*aResult*/, const TRealX& /*aVal*/) const |
|
3164 /** |
|
3165 Divides this extended precision number by an extended precision value. |
|
3166 |
|
3167 @param aResult On return, a reference to an extended precision object |
|
3168 containing the result of the operation. |
|
3169 @param aVal The extended precision value to be used as the divisor. |
|
3170 |
|
3171 @return KErrNone, if the operation is successful; |
|
3172 KErrOverflow, if the operation results in overflow; |
|
3173 KErrUnderflow, if the operation results in underflow; |
|
3174 KErrDivideByZero, if the divisor is zero. |
|
3175 */ |
|
3176 { |
|
3177 // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal |
|
3178 THISCALL_PROLOG2() |
|
3179 asm("push ecx"); // save registers |
|
3180 asm("push ebx"); |
|
3181 asm("push ebp"); |
|
3182 asm("push esi"); |
|
3183 asm("push edi"); |
|
3184 asm("mov esi, ecx"); // this into esi |
|
3185 asm("mov ecx, [esp+28]"); // address of aVal into ecx |
|
3186 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
3187 asm("mov edx, [ecx+4]"); |
|
3188 asm("mov ecx, [ecx+8]"); |
|
3189 asm("call %a0": : "i"(&TRealXDivide)); // do division, result in ecx,edx:ebx, error code in eax |
|
3190 asm("mov esi, [esp+24]"); // esi=address of aResult |
|
3191 asm("mov [esi], ebx"); // store result |
|
3192 asm("mov [esi+4], edx"); |
|
3193 asm("mov [esi+8], ecx"); |
|
3194 asm("pop edi"); // restore registers |
|
3195 asm("pop esi"); |
|
3196 asm("pop ebp"); |
|
3197 asm("pop ebx"); |
|
3198 asm("pop ecx"); |
|
3199 THISCALL_EPILOG2() // return with error code in eax |
|
3200 } |
|
3201 |
|
3202 |
|
3203 |
|
3204 |
|
3205 __NAKED__ EXPORT_C TInt TRealX::Mod(TRealX& /*aResult*/, const TRealX& /*aVal*/) const |
|
3206 /** |
|
3207 Modulo-divides this extended precision number by an extended precision value. |
|
3208 |
|
3209 @param aResult On return, a reference to an extended precision object |
|
3210 containing the result of the operation. |
|
3211 |
|
3212 @param aVal The extended precision value to be used as the divisor. |
|
3213 |
|
3214 @return KErrNone, if the operation is successful; |
|
3215 KErrTotalLossOfPrecision, if precision is lost; |
|
3216 KErrUnderflow, if the operation results in underflow. |
|
3217 */ |
|
3218 { |
|
3219 // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal |
|
3220 THISCALL_PROLOG2() |
|
3221 asm("push ecx"); // save registers |
|
3222 asm("push ebx"); |
|
3223 asm("push ebp"); |
|
3224 asm("push esi"); |
|
3225 asm("push edi"); |
|
3226 asm("mov esi, ecx"); // this into esi |
|
3227 asm("mov ecx, [esp+28]"); // address of aVal into ecx |
|
3228 asm("mov ebx, [ecx]"); // aVal into ecx,edx:ebx |
|
3229 asm("mov edx, [ecx+4]"); |
|
3230 asm("mov ecx, [ecx+8]"); |
|
3231 asm("call %a0": : "i"(&TRealXModulo)); // do modulo, result in ecx,edx:ebx, error code in eax |
|
3232 asm("mov esi, [esp+24]"); // esi=address of aResult |
|
3233 asm("mov [esi], ebx"); // store result |
|
3234 asm("mov [esi+4], edx"); |
|
3235 asm("mov [esi+8], ecx"); |
|
3236 asm("pop edi"); // restore registers |
|
3237 asm("pop esi"); |
|
3238 asm("pop ebp"); |
|
3239 asm("pop ebx"); |
|
3240 asm("pop ecx"); |
|
3241 THISCALL_EPILOG2() // return with error code in eax |
|
3242 } |
|
3243 |
|
3244 // Compare TRealX in ecx,edx:ebx (op1) to TRealX at [esi] (op2) |
|
3245 // Return 1 if op1<op2 |
|
3246 // Return 2 if op1=op2 |
|
3247 // Return 4 if op1>op2 |
|
3248 // Return 8 if unordered |
|
3249 // Return value in eax |
|
3250 LOCAL_C __NAKED__ void TRealXCompare(void) |
|
3251 { |
|
3252 asm("cmp ecx, 0xFFFF0000"); // check if op1=NaN or infinity |
|
3253 asm("jc short fpcmp1"); // branch if not |
|
3254 asm("cmp edx, 0x80000000"); // check for infinity |
|
3255 asm("jnz short fpcmpunord"); // branch if NaN |
|
3256 asm("test ebx, ebx"); |
|
3257 asm("jz short fpcmp1"); // if infinity, process normally |
|
3258 asm("fpcmpunord:"); // come here if unordered |
|
3259 asm("mov eax, 8"); // return 8 |
|
3260 asm("ret"); |
|
3261 asm("fpcmp1:"); // op1 is not a NaN |
|
3262 asm("mov eax, [esi+8]"); // get op2 into eax,edi:ebp |
|
3263 asm("mov edi, [esi+4]"); |
|
3264 asm("mov ebp, [esi]"); |
|
3265 asm("cmp eax, 0xFFFF0000"); // check for NaN or infinity |
|
3266 asm("jc short fpcmp2"); // branch if neither |
|
3267 asm("cmp edi, 0x80000000"); // check for infinity |
|
3268 asm("jnz short fpcmpunord"); // branch if NaN |
|
3269 asm("test ebp, ebp"); |
|
3270 asm("jnz short fpcmpunord"); |
|
3271 asm("fpcmp2:"); // neither operand is a NaN |
|
3272 asm("cmp ecx, 0x10000"); // check if op1=0 |
|
3273 asm("jc short fpcmpop1z"); // branch if it is |
|
3274 asm("cmp eax, 0x10000"); // check if op2=0 |
|
3275 asm("jc short fpcmp4"); // branch if it is |
|
3276 asm("xor al, cl"); // check if signs the same |
|
3277 asm("test al, 1"); |
|
3278 asm("jnz short fpcmp4"); // branch if different |
|
3279 asm("push ecx"); |
|
3280 asm("shr ecx, 16"); // op1 exponent into cx |
|
3281 asm("shr eax, 16"); // op2 exponent into ax |
|
3282 asm("cmp ecx, eax"); // compare exponents |
|
3283 asm("pop ecx"); |
|
3284 asm("ja short fpcmp4"); // if op1 exp > op2 exp op1>op2 if +ve |
|
3285 asm("jb short fpcmp5"); // if op1 exp < op2 exp op1<op2 if +ve |
|
3286 asm("cmp edx, edi"); // else compare mantissa high words |
|
3287 asm("ja short fpcmp4"); |
|
3288 asm("jb short fpcmp5"); |
|
3289 asm("cmp ebx, ebp"); // if equal compare mantissa low words |
|
3290 asm("ja short fpcmp4"); |
|
3291 asm("jb short fpcmp5"); |
|
3292 asm("fpcmp0:"); |
|
3293 asm("mov eax, 2"); // numbers exactly equal |
|
3294 asm("ret"); |
|
3295 asm("fpcmp4:"); // come here if ABS{op1}>ABS{op2} or if signs different |
|
3296 // or if op2 zero, op1 nonzero |
|
3297 asm("mov eax, 4"); // return 4 if +ve |
|
3298 asm("test cl, 1"); // check sign |
|
3299 asm("jz short fpcmp4a"); // skip if + |
|
3300 asm("mov al, 1"); // return 1 if -ve |
|
3301 asm("fpcmp4a:"); |
|
3302 asm("ret"); |
|
3303 asm("fpcmp5:"); // come here if ABS{op1}<ABS{op2} |
|
3304 asm("mov eax, 1"); // return 1 if +ve |
|
3305 asm("test cl, 1"); // check sign |
|
3306 asm("jz short fpcmp5a"); // skip if + |
|
3307 asm("mov al, 4"); // return 4 if -ve |
|
3308 asm("fpcmp5a:"); |
|
3309 asm("ret"); |
|
3310 asm("fpcmpop1z:"); // come here if op1=0 |
|
3311 asm("cmp eax, 0x10000"); // check if op2 also zero |
|
3312 asm("jc short fpcmp0"); // if so, they are equal |
|
3313 asm("test al, 1"); // test sign of op 2 |
|
3314 asm("mov eax, 4"); // if -, return 4 |
|
3315 asm("jnz short fpcmpop1z2n"); // skip if - |
|
3316 asm("mov al, 1"); // else return 1 |
|
3317 asm("fpcmpop1z2n:"); |
|
3318 asm("ret"); |
|
3319 } |
|
3320 |
|
3321 |
|
3322 |
|
3323 |
|
3324 __NAKED__ EXPORT_C TRealX::TRealXOrder TRealX::Compare(const TRealX& /*aVal*/) const |
|
3325 /** |
|
3326 */ |
|
3327 { |
|
3328 // On entry ecx=this, [esp+4]=address of aVal |
|
3329 THISCALL_PROLOG1() |
|
3330 asm("push ecx"); // save registers |
|
3331 asm("push ebx"); |
|
3332 asm("push ebp"); |
|
3333 asm("push esi"); |
|
3334 asm("push edi"); |
|
3335 asm("mov esi, [esp+24]"); // address of aVal into esi |
|
3336 asm("mov ebx, [ecx]"); // *this into ecx,edx:ebx |
|
3337 asm("mov edx, [ecx+4]"); |
|
3338 asm("mov ecx, [ecx+8]"); |
|
3339 asm("call %a0": : "i"(&TRealXCompare)); // result in eax |
|
3340 asm("pop edi"); |
|
3341 asm("pop esi"); |
|
3342 asm("pop ebp"); |
|
3343 asm("pop ebx"); |
|
3344 asm("pop ecx"); |
|
3345 THISCALL_EPILOG1() |
|
3346 } |
|
3347 |
|
3348 |