First public contribution.
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\euser\epoc\win32\uc_realx.cpp
21 #pragma warning (disable : 4100) // unreferenced formal parameter
22 #pragma warning (disable : 4700) // local variable 'this' used without
23 // having been initialised
24 #pragma warning ( disable : 4414 ) // short jump to function converted to near
27 #if defined(__VC32__) && (_MSC_VER==1100) // untested on MSVC++ > 5.0
28 // Workaround for MSVC++ 5.0 bug; MSVC incorrectly fixes up conditional jumps
29 // when the destination is a C++ function.
30 #define _ASM_j(cond,dest) _asm jn##cond short $+11 _asm jmp dest
31 #define _ASM_jn(cond,dest) _asm j##cond short $+11 _asm jmp dest
32 #pragma optimize( "", off ) // stop MSVC murdering the code
34 #define _ASM_j(cond,dest) _asm j##cond dest
35 #define _ASM_jn(cond,dest) _asm jn##cond dest
39 // 64-bit precision floating point routines
40 // Register storage format:
41 // edx:ebx=64 bit normalised mantissa
42 // ecx bits 16-31 = 16-bit exponent, biased by 7FFF
44 // ecx bit 8 = rounded-down flag
45 // ecx bit 9 = rounded-up flag
47 // Memory storage format:
48 // 3 doublewords per number
49 // Low 32 bits of mantissa at [addr]
50 // High 32 bits of mantissa at [addr+4]
51 // Exponent/flags/sign at [addr+8]
54 LOCAL_C void TRealXPanic(TInt aErr)
56 User::Panic(_L("MATHX"),aErr);
59 __NAKED__ LOCAL_C void TRealXPanicEax(void)
65 LOCAL_C __NAKED__ void TRealXRealIndefinite(void)
67 // return 'real indefinite' NaN in ecx,edx:ebx
68 _asm mov ecx, 0xFFFF0001 // exponent=FFFF, sign negative
69 _asm mov edx, 0xC0000000 // mantissa=C0000000 00000000
71 _asm mov eax, -6 // return KErrArgument
75 LOCAL_C __NAKED__ void TRealXBinOpNaN(void)
77 // generic routine to process NaN's in binary operations
78 // destination operand in ecx,edx:eax
79 // source operand at [esi]
81 _asm mov eax, [esi+8] // source operand into eax,edi:ebp
84 _asm cmp ecx, 0xFFFF0000 // check if dest is a NaN
85 _asm jb short TRealXBinOpNaN1 // if not, swap them
86 _asm cmp edx, 0x80000000
87 _asm jne short TRealXBinOpNaN2
89 _asm jne short TRealXBinOpNaN2
90 TRealXBinOpNaN1: // swap the operands
95 _asm cmp eax, 0xFFFF0000 // check if both operands are NaNs
96 _asm jb short TRealXBinOpNaN4 // if not, ignore non-NaN operand
97 _asm cmp edi, 0x80000000
98 _asm jne short TRealXBinOpNaN3
100 _asm je short TRealXBinOpNaN4
101 TRealXBinOpNaN3: // if both operands are NaN's, compare significands
103 _asm ja short TRealXBinOpNaN4
104 _asm jb short TRealXBinOpNaN5
106 _asm jae short TRealXBinOpNaN4
107 TRealXBinOpNaN5: // come here if dest is smaller - copy source to dest
111 TRealXBinOpNaN4: // NaN with larger significand is in ecx,edx:ebx
112 _asm or edx, 0x40000000 // convert an SNaN to a QNaN
113 _asm mov eax, -6 // return KErrArgument
117 // Add TRealX at [esi] + ecx,edx:ebx
118 // Result in ecx,edx:ebx
120 // Note: +0 + +0 = +0, -0 + -0 = -0, +0 + -0 = -0 + +0 = +0,
121 // +/-0 + X = X + +/-0 = X, X + -X = -X + X = +0
122 __NAKED__ LOCAL_C void TRealXAdd()
124 _asm xor ch, ch // clear rounding flags
125 _asm cmp ecx, 0xFFFF0000 // check if dest=NaN or infinity
126 _asm jnc addfpsd // branch if it is
127 _asm mov eax, [esi+8] // fetch sign/exponent of source
128 _asm cmp eax, 0xFFFF0000 // check if source=NaN or infinity
129 _asm jnc addfpss // branch if it is
130 _asm cmp eax, 0x10000 // check if source=0
131 _asm jc addfp0s // branch if it is
132 _asm cmp ecx, 0x10000 // check if dest=0
133 _asm jc addfp0d // branch if it is
134 _asm and cl, 1 // clear bits 1-7 of ecx
135 _asm and al, 1 // clear bits 1-7 of eax
137 _asm xor ch, al // xor of signs into ch bit 0
139 _asm or cl, ch // and into cl bit 1
140 _asm or al, ch // and al bit 1
141 _asm xor ch, ch // clear rounding flags
142 _asm mov ebp, [esi] // fetch source mantissa 0-31
143 _asm mov edi, [esi+4] // fetch source mantissa 32-63
144 _asm ror ecx, 16 // dest exponent into cx
145 _asm ror eax, 16 // source exponent into ax
146 _asm push ecx // push dest exponent/sign
147 _asm sub cx, ax // cx = dest exponent - source exponent
148 _asm je short addfp3b // if equal, no shifting required
149 _asm ja short addfp1 // branch if dest exponent >= source exponent
150 _asm xchg ebx, ebp // make sure edi:ebp contains the mantissa to be shifted
151 _asm xchg edx, edi //
152 _asm xchg eax, [esp] // and larger exponent and corresponding sign is on the stack
153 _asm neg cx // make cx positive = number of right shifts needed
155 _asm cmp cx, 64 // if more than 64 shifts needed
156 _asm ja addfp2 // branch to output larger number
157 _asm jb addfp3 // branch if <64 shifts
158 _asm mov eax, edi // exactly 64 shifts needed - rounding word=mant high
159 _asm test ebp, ebp // check bits lost
160 _asm jz short addfp3a
161 _asm or ch, 1 // if not all zero, set rounded-down flag
163 _asm xor edi, edi // clear edx:ebx
165 _asm jmp short addfp5 // finished shifting
166 addfp3b: // exponents equal
167 _asm xor eax, eax // set rounding word=0
168 _asm jmp short addfp5
170 _asm cmp cl, 32 // 32 or more shifts needed ?
171 _asm jb short addfp4 // skip if <32
172 _asm mov eax, ebp // rounding word=mant low
173 _asm mov ebp, edi // mant low=mant high
174 _asm xor edi, edi // mant high=0
175 _asm sub cl, 32 // reduce count by 32
176 _asm jz short addfp5 // if now zero, finished shifting
177 _asm shrd edi, eax, cl // shift ebp:eax:edi right by cl bits
178 _asm shrd eax, ebp, cl //
180 _asm test edi, edi // check bits lost in shift
181 _asm jz short addfp5 // if all zero, finished
182 _asm or ch, 1 // else set rounded-down flag
183 _asm xor edi, edi // clear edx again
184 _asm jmp short addfp5 // finished shifting
185 addfp4: // <32 shifts needed now
186 _asm xor eax, eax // clear rounding word initially
187 _asm shrd eax, ebp, cl // shift edi:ebp:eax right by cl bits
188 _asm shrd ebp, edi, cl //
192 _asm mov [esp+3], ch // rounding flag into ch image on stack
193 _asm pop ecx // recover sign and exponent into ecx, with rounding flag
194 _asm ror ecx, 16 // into normal position
195 _asm test cl, 2 // addition or subtraction needed ?
196 _asm jnz short subfp1 // branch if subtraction
197 _asm add ebx,ebp // addition required - add mantissas
199 _asm jnc short roundfp // branch if no carry
200 _asm rcr edx,1 // shift carry right into mantissa
202 _asm rcr eax,1 // and into rounding word
203 _asm jnc short addfp5a
204 _asm or ch, 1 // if 1 shifted out, set rounded-down flag
206 _asm add ecx, 0x10000 // and increment exponent
208 // perform rounding based on rounding word in eax and rounding flag in ch
210 _asm cmp eax, 0x80000000
211 _asm jc roundfp0 // if rounding word<80000000, round down
212 _asm ja roundfp1 // if >80000000, round up
214 _asm jnz short roundfp1 // if rounded-down flag set, round up
216 _asm jnz short roundfp0 // if rounded-up flag set, round down
217 _asm test bl, 1 // else test mantissa lsb
218 _asm jz short roundfp0 // round down if 0, up if 1 (round to even)
219 roundfp1: // Come here to round up
220 _asm add ebx, 1 // increment mantissa
222 _asm jnc roundfp1a // if no carry OK
223 _asm rcr edx,1 // else shift carry into mantissa (edx:ebx=0 here)
224 _asm add ecx, 0x10000 // and increment exponent
226 _asm cmp ecx, 0xFFFF0000 // check for overflow
227 _asm jae short addfpovfw // jump if overflow
228 _asm mov ch, 2 // else set rounded-up flag
229 _asm xor eax, eax // return KErrNone
232 roundfp0: // Come here to round down
233 _asm cmp ecx, 0xFFFF0000 // check for overflow
234 _asm jae short addfpovfw // jump if overflow
235 _asm test eax, eax // else check if rounding word zero
236 _asm jz short roundfp0a // if so, leave rounding flags as they are
237 _asm mov ch, 1 // else set rounded-down flag
239 _asm xor eax, eax // return KErrNone
242 addfpovfw: // Come here if overflow occurs
243 _asm xor ch, ch // clear rounding flags, exponent=FFFF
245 _asm mov edx, 0x80000000 // mantissa=80000000 00000000 for infinity
246 _asm mov eax, -9 // return KErrOverflow
249 // exponents differ by more than 64 - output larger number
251 _asm pop ecx // recover exponent and sign
252 _asm ror ecx, 16 // into normal position
253 _asm or ch, 1 // set rounded-down flag
254 _asm test cl, 2 // check if signs the same
256 _asm xor ch, 3 // if not, set rounded-up flag
258 _asm xor eax, eax // return KErrNone
261 // signs differ, so must subtract mantissas
263 _asm add ch, ch // if rounded-down flag set, change it to rounded-up
264 _asm neg eax // subtract rounding word from 0
265 _asm sbb ebx, ebp // and subtract mantissas with borrow
267 _asm jnc short subfp2 // if no borrow, sign is correct
268 _asm xor cl, 1 // else change sign of result
269 _asm shr ch, 1 // change rounding back to rounded-down
270 _asm not eax // negate rounding word
271 _asm not ebx // and mantissa
273 _asm add eax,1 // two's complement negation
277 _asm jnz short subfp3 // branch if edx non-zero at this point
278 _asm mov edx, ebx // else shift ebx into edx
280 _asm jz short subfp4 // if still zero, branch
281 _asm mov ebx, eax // else shift rounding word into ebx
282 _asm xor eax, eax // and zero rounding word
283 _asm sub ecx, 0x200000 // decrease exponent by 32 due to shift
284 _asm jnc short subfp3 // if no borrow, carry on
285 _asm jmp short subfpundflw // if borrow here, underflow
287 _asm mov edx, eax // move rounding word into edx
288 _asm or edx, edx // is edx still zero ?
289 _asm jz short subfp0 // if so, result is precisely zero
290 _asm xor ebx, ebx // else zero ebx and rounding word
292 _asm sub ecx, 0x400000 // and decrease exponent by 64 due to shift
293 _asm jc short subfpundflw // if borrow, underflow
295 _asm mov edi, ecx // preserve sign and exponent
296 _asm bsr ecx, edx // position of most significant 1 into ecx
298 _asm add ecx, 31 // cl = 31-position of MS 1 = number of shifts to normalise
299 _asm shld edx, ebx, cl // shift edx:ebx:eax left by cl bits
300 _asm shld ebx, eax, cl //
302 _asm mov ebp, ecx // bit count into ebp for subtraction
303 _asm shl ebp, 16 // shift left by 16 to align with exponent
304 _asm mov ecx, edi // exponent, sign, rounding flags back into ecx
305 _asm sub ecx, ebp // subtract shift count from exponent
306 _asm jc short subfpundflw // if borrow, underflow
307 _asm cmp ecx, 0x10000 // check if exponent 0
308 _asm jnc roundfp // if not, jump to round result, else underflow
310 // come here if underflow
312 _asm and ecx, 1 // set exponent to zero, leave sign
315 _asm mov eax, -10 // return KErrUnderflow
318 // come here to return zero result
320 _asm xor ecx, ecx // set exponent to zero, positive sign
324 _asm xor eax, eax // return KErrNone
327 // come here if source=0 - eax=source exponent/sign
329 _asm cmp ecx, 0x10000 // check if dest=0
330 _asm jnc addfp0snzd // if not, return dest unaltered
331 _asm and ecx, eax // else both zero, result negative iff both zeros negative
333 _asm xor eax, eax // return KErrNone
336 // come here if dest=0, source nonzero
338 _asm mov ebx, [esi] // return source unaltered
339 _asm mov edx, [esi+4]
340 _asm mov ecx, [esi+8]
341 _asm xor eax, eax // return KErrNone
344 // come here if dest=NaN or infinity
346 _asm cmp edx, 0x80000000 // check for infinity
347 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
349 _ASM_jn(e,TRealXBinOpNaN)
350 _asm mov eax, [esi+8] // eax=second operand exponent
351 _asm cmp eax, 0xFFFF0000 // check second operand for NaN or infinity
352 _asm jae short addfpsd1 // branch if NaN or infinity
354 _asm mov eax, -9 // else return dest unaltered (infinity) and KErrOverflow
357 _asm mov ebp, [esi] // source mantissa into edi:ebp
358 _asm mov edi, [esi+4]
359 _asm cmp edi, 0x80000000 // check for infinity
360 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
362 _ASM_jn(e,TRealXBinOpNaN)
363 _asm xor al, cl // both operands are infinity - check signs
365 _asm jz short addfpsd2 // if both the same, return KErrOverflow
366 _asm jmp TRealXRealIndefinite // else return 'real indefinite'
368 // come here if source=NaN or infinity, dest finite
370 _asm mov ebp, [esi] // source mantissa into edi:ebp
371 _asm mov edi, [esi+4]
372 _asm cmp edi, 0x80000000 // check for infinity
373 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
375 _ASM_jn(e,TRealXBinOpNaN)
376 _asm mov ecx, eax // if source=infinity, return source unaltered
379 _asm mov eax, -9 // return KErrOverflow
383 // Subtract TRealX at [esi] - ecx,edx:ebx
384 // Result in ecx,edx:ebx
386 __NAKED__ LOCAL_C void TRealXSubtract()
388 _asm xor cl, 1 // negate subtrahend
392 // Multiply TRealX at [esi] * ecx,edx:ebx
393 // Result in ecx,edx:ebx
395 __NAKED__ LOCAL_C void TRealXMultiply()
397 _asm xor ch, ch // clear rounding flags
398 _asm mov eax, [esi+8] // fetch sign/exponent of source
399 _asm xor cl, al // xor signs
400 _asm cmp ecx, 0xFFFF0000 // check if dest=NaN or infinity
401 _asm jnc mulfpsd // branch if it is
402 _asm cmp eax, 0xFFFF0000 // check if source=NaN or infinity
403 _asm jnc mulfpss // branch if it is
404 _asm cmp eax, 0x10000 // check if source=0
405 _asm jc mulfp0 // branch if it is
406 _asm cmp ecx, 0x10000 // check if dest=0
407 _asm jc mulfp0 // branch if it is
408 _asm push ecx // save result sign
409 _asm shr ecx, 16 // dest exponent into cx
410 _asm shr eax, 16 // source exponent into ax
411 _asm add eax, ecx // add exponents
412 _asm sub eax, 0x7FFE // eax now contains result exponent
413 _asm push eax // save it
414 _asm mov edi, edx // save dest mantissa high
415 _asm mov eax, ebx // dest mantissa low -> eax
416 _asm mul dword ptr [esi] // dest mantissa low * source mantissa low -> edx:eax
417 _asm xchg ebx, eax // result dword 0 -> ebx, dest mant low -> eax
418 _asm mov ebp, edx // result dword 1 -> ebp
419 _asm mul dword ptr [esi+4] // dest mant low * src mant high -> edx:eax
420 _asm add ebp, eax // add in partial product to dwords 1 and 2
422 _asm mov ecx, edx // result dword 2 -> ecx
423 _asm mov eax, edi // dest mant high -> eax
424 _asm mul dword ptr [esi+4] // dest mant high * src mant high -> edx:eax
425 _asm add ecx, eax // add in partial product to dwords 2, 3
427 _asm mov eax, edi // dest mant high -> eax
428 _asm mov edi, edx // result dword 3 -> edi
429 _asm mul dword ptr [esi] // dest mant high * src mant low -> edx:eax
430 _asm add ebp, eax // add in partial product to dwords 1, 2
432 _asm adc edi, 0 // 128-bit mantissa product is now in edi:ecx:ebp:ebx
433 _asm mov edx, edi // top 64 bits into edx:ebx
435 _asm mov ebx, ecx // bottom 64 bits now in ebp:edi
436 _asm pop ecx // recover exponent
437 _asm js short mulfp1 // skip if mantissa normalised
438 _asm add edi, edi // else shift left (only one shift will be needed)
442 _asm dec ecx // and decrement exponent
444 _asm cmp ebp, 0x80000000 // compare bottom 64 bits with 80000000 00000000 for rounding
445 _asm ja short mulfp2 // branch to round up
446 _asm jb short mulfp3 // branch to round down
448 _asm jnz short mulfp2 // branch to round up
449 _asm test bl, 1 // if exactly half-way, test LSB of result mantissa
450 _asm jz short mulfp4 // if LSB=0, round down (round to even)
452 _asm add ebx, 1 // round up - increment mantissa
454 _asm jnc short mulfp2a
458 _asm mov al, 2 // set rounded-up flag
459 _asm jmp short mulfp5
460 mulfp3: // round down
461 _asm xor al, al // clear rounding flags
462 _asm or ebp, edi // check for exact result
463 _asm jz short mulfp5 // skip if exact
464 mulfp4: // come here to round down when we know result inexact
465 _asm mov al, 1 // else set rounded-down flag
466 mulfp5: // final mantissa now in edx:ebx, exponent in ecx
467 _asm cmp ecx, 0xFFFF // check for overflow
468 _asm jge short mulfp6 // branch if overflow
469 _asm cmp ecx, 0 // check for underflow
470 _asm jle short mulfp7 // branch if underflow
471 _asm shl ecx, 16 // else exponent up to top end of ecx
472 _asm mov ch, al // rounding flags into ch
473 _asm pop eax // recover result sign
474 _asm mov cl, al // into cl
475 _asm xor eax, eax // return KErrNone
478 // come here if overflow
480 _asm pop eax // recover result sign
481 _asm mov ecx, 0xFFFF0000 // exponent=FFFF
482 _asm mov cl, al // sign into cl
483 _asm mov edx, 0x80000000 // set mantissa to 80000000 00000000 for infinity
485 _asm mov eax, -9 // return KErrOverflow
488 // come here if underflow
490 _asm pop eax // recover result sign
491 _asm xor ecx, ecx // exponent=0
492 _asm mov cl, al // sign into cl
495 _asm mov eax, -10 // return KErrUnderflow
498 // come here if either operand zero
500 _asm and ecx, 1 // set exponent=0, keep sign
503 _asm xor eax, eax // return KErrNone
506 // come here if destination operand NaN or infinity
508 _asm cmp edx, 0x80000000 // check for infinity
509 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
511 _ASM_jn(e,TRealXBinOpNaN)
512 _asm cmp eax, 0xFFFF0000 // check second operand for NaN or infinity
513 _asm jae short mulfpsd1 // branch if NaN or infinity
514 _asm cmp eax, 0x10000 // check if second operand zero
515 _ASM_j(c,TRealXRealIndefinite) // if so, return 'real indefinite'
516 _asm mov eax, -9 // else return dest (infinity) with xor sign and KErrOverflow
519 _asm mov ebp, [esi] // source mantissa into edi:ebp
520 _asm mov edi, [esi+4]
521 _asm cmp edi, 0x80000000 // check for infinity
522 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
524 _ASM_jn(e,TRealXBinOpNaN)
525 _asm mov eax, -9 // both operands infinity - return infinity with xor sign
526 _asm ret // and KErrOverflow
528 // come here if source operand NaN or infinity, destination finite
530 _asm mov ebp, [esi] // source mantissa into edi:ebp
531 _asm mov edi, [esi+4]
532 _asm cmp edi, 0x80000000 // check for infinity
533 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
535 _ASM_jn(e,TRealXBinOpNaN)
536 _asm cmp ecx, 0x10000 // source=infinity, check if dest=0
537 _ASM_j(c,TRealXRealIndefinite) // if so, return 'real indefinite'
538 _asm or ecx, 0xFFFF0000 // set exp=FFFF, leave xor sign in cl
539 _asm mov edx, edi // set mantissa for infinity
541 _asm mov eax, -9 // return KErrOverflow
545 // Divide 96-bit unsigned dividend EDX:EAX:0 by 64-bit unsigned divisor ECX:EBX
546 // Assume ECX bit 31 = 1, ie 2^63 <= divisor < 2^64
547 // Assume the quotient fits in 32 bits
548 // Return 32 bit quotient in EDI
549 // Return 64 bit remainder in EBP:ESI
550 __NAKED__ LOCAL_C void LongDivide(void)
552 _asm push edx // save dividend
554 _asm cmp edx, ecx // check if truncation of divisor will overflow DIV instruction
555 _asm jb short longdiv1 // skip if not
556 _asm xor eax, eax // else return quotient of 0xFFFFFFFF
558 _asm jmp short longdiv2 //
560 _asm div ecx // divide EDX:EAX by ECX to give approximate quotient in EAX
562 _asm mov edi, eax // save approx quotient
563 _asm mul ebx // multiply approx quotient by full divisor ECX:EBX
564 _asm mov esi, eax // first partial product into EBP:ESI
566 _asm mov eax, edi // approx quotient back into eax
567 _asm mul ecx // upper partial product now in EDX:EAX
568 _asm add eax, ebp // add to form 96-bit product in EDX:EAX:ESI
570 _asm neg esi // remainder = dividend - approx quotient * divisor
571 _asm mov ebp, [esp] // fetch dividend bits 32-63
573 _asm mov eax, [esp+4] // fetch dividend bits 64-95
574 _asm sbb eax, edx // remainder is now in EAX:EBP:ESI
575 _asm jns short longdiv4 // if remainder positive, quotient is correct, so exit
577 _asm dec edi // else quotient is too big, so decrement it
578 _asm add esi, ebx // and add divisor to remainder
581 _asm js short longdiv3 // if still negative, repeat (requires <4 iterations)
583 _asm add esp, 8 // remove dividend from stack
584 _asm ret // return with quotient in EDI, remainder in EBP:ESI
587 // Divide TRealX at [esi] / ecx,edx:ebx
588 // Result in ecx,edx:ebx
590 __NAKED__ LOCAL_C void TRealXDivide(void)
592 _asm xor ch, ch // clear rounding flags
593 _asm mov eax, [esi+8] // fetch sign/exponent of dividend
594 _asm xor cl, al // xor signs
595 _asm cmp eax, 0xFFFF0000 // check if dividend=NaN or infinity
596 _asm jnc divfpss // branch if it is
597 _asm cmp ecx, 0xFFFF0000 // check if divisor=NaN or infinity
598 _asm jnc divfpsd // branch if it is
599 _asm cmp ecx, 0x10000 // check if divisor=0
600 _asm jc divfpdv0 // branch if it is
601 _asm cmp eax, 0x10000 // check if dividend=0
602 _asm jc divfpdd0 // branch if it is
603 _asm push esi // save pointer to dividend
604 _asm push ecx // save result sign
605 _asm shr ecx, 16 // divisor exponent into cx
606 _asm shr eax, 16 // dividend exponent into ax
607 _asm sub eax, ecx // subtract exponents
608 _asm add eax, 0x7FFE // eax now contains result exponent
609 _asm push eax // save it
610 _asm mov ecx, edx // divisor mantissa into ecx:ebx
611 _asm mov edx, [esi+4] // dividend mantissa into edx:eax
613 _asm xor edi, edi // clear edi initially
614 _asm cmp edx, ecx // compare EDX:EAX with ECX:EBX
615 _asm jb short divfp1 // if EDX:EAX < ECX:EBX, leave everything as is
616 _asm ja short divfp2 //
617 _asm cmp eax, ebx // if EDX=ECX, then compare ls dwords
618 _asm jb short divfp1 // if dividend mant < divisor mant, leave everything as is
620 _asm sub eax, ebx // else dividend mant -= divisor mant
622 _asm inc edi // and EDI=1 (bit 0 of EDI is the integer part of the result)
623 _asm inc dword ptr [esp] // also increment result exponent
625 _asm push edi // save top bit of result
626 _asm call LongDivide // divide EDX:EAX:0 by ECX:EBX to give next 32 bits of result in EDI
627 _asm push edi // save next 32 bits of result
628 _asm mov edx, ebp // remainder from EBP:ESI into EDX:EAX
630 _asm call LongDivide // divide EDX:EAX:0 by ECX:EBX to give next 32 bits of result in EDI
631 _asm test byte ptr [esp+4], 1 // test integer bit of result
632 _asm jnz short divfp4 // if set, no need to calculate another bit
634 _asm add esi, esi // 2*remainder into EAX:EBP:ESI
637 _asm sub esi, ebx // subtract divisor to generate final quotient bit
640 _asm jnc short divfp3 // skip if no borrow - in this case eax=0
641 _asm add esi, ebx // if borrow add back - final remainder now in EBP:ESI
643 _asm adc eax, 0 // eax will be zero after this and carry will be set
645 _asm cmc // final bit = 1-C
646 _asm rcr eax, 1 // shift it into eax bit 31
647 _asm mov ebx, edi // result into EDX:EBX:EAX, remainder in EBP:ESI
649 _asm add esp, 4 // discard integer bit (zero)
650 _asm jmp short divfp5 // branch to round
652 divfp4: // integer bit was set
653 _asm mov ebx, edi // result into EDX:EBX:EAX
655 _asm pop eax // integer part of result into eax (=1)
656 _asm stc // shift a 1 into top end of mantissa
659 _asm rcr eax,1 // bottom bit into eax bit 31
661 // when we get to here we have 65 bits of quotient mantissa in
662 // EDX:EBX:EAX (bottom bit in eax bit 31)
663 // and the remainder is in EBP:ESI
665 _asm pop ecx // recover result exponent
666 _asm add eax, eax // test rounding bit
667 _asm jnc short divfp6 // branch to round down
668 _asm or ebp, esi // test remainder to see if we are exactly half-way
669 _asm jnz short divfp7 // if not, round up
670 _asm test bl, 1 // exactly halfway - test LSB of mantissa
671 _asm jz short divfp8 // round down if LSB=0 (round to even)
673 _asm add ebx, 1 // round up - increment mantissa
675 _asm jnc short divfp7a
676 _asm rcr edx, 1 // if carry, shift 1 into mantissa MSB
677 _asm inc ecx // and increment exponent
679 _asm mov al, 2 // set rounded-up flag
680 _asm jmp short divfp9
682 _asm xor al, al // round down - first clear rounding flags
683 _asm or ebp, esi // test if result exact
684 _asm jz short divfp9 // skip if exact
685 divfp8: // come here to round down when we know result is inexact
686 _asm mov al, 1 // set rounded-down flag
687 divfp9: // final mantissa now in edx:ebx, exponent in ecx
688 _asm cmp ecx, 0xFFFF // check for overflow
689 _asm jge short divfp10 // branch if overflow
690 _asm cmp ecx, 0 // check for underflow
691 _asm jle short divfp11 // branch if underflow
692 _asm shl ecx, 16 // else exponent up to top end of ecx
693 _asm mov ch, al // rounding flags into ch
694 _asm pop eax // recover result sign
695 _asm mov cl, al // into cl
696 _asm pop esi // recover dividend pointer
697 _asm xor eax, eax // return KErrNone
700 // come here if overflow
702 _asm pop eax // recover result sign
703 _asm mov ecx, 0xFFFF0000 // exponent=FFFF
704 _asm mov cl, al // sign into cl
705 _asm mov edx, 0x80000000 // set mantissa to 80000000 00000000 for infinity
707 _asm mov eax, -9 // return KErrOverflow
708 _asm pop esi // recover dividend pointer
711 // come here if underflow
713 _asm pop eax // recover result sign
714 _asm xor ecx, ecx // exponent=0
715 _asm mov cl, al // sign into cl
718 _asm mov eax, -10 // return KErrUnderflow
719 _asm pop esi // recover dividend pointer
723 // come here if divisor=0, dividend finite
725 _asm cmp eax, 0x10000 // check if dividend also zero
726 _ASM_j(c,TRealXRealIndefinite) // if so, return 'real indefinite'
727 _asm or ecx, 0xFFFF0000 // else set exponent=FFFF, leave xor sign in cl
728 _asm mov edx, 0x80000000 // set mantissa for infinity
730 _asm mov eax, -41 // return KErrDivideByZero
733 // come here if dividend=0, divisor finite and nonzero
735 _asm and ecx, 1 // exponent=0, leave xor sign in cl
736 _asm xor eax, eax // return KErrNone
739 // come here if dividend is a NaN or infinity
741 _asm mov ebp, [esi] // dividend mantissa into edi:ebp
742 _asm mov edi, [esi+4]
743 _asm cmp edi, 0x80000000 // check for infinity
744 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
746 _ASM_jn(e,TRealXBinOpNaN)
747 _asm cmp ecx, 0xFFFF0000 // check divisor for NaN or infinity
748 _asm jae short divfpss1 // branch if NaN or infinity
749 _asm or ecx, 0xFFFF0000 // infinity/finite - return infinity with xor sign
750 _asm mov edx, 0x80000000
752 _asm mov eax, -9 // return KErrOverflow
755 _asm cmp edx, 0x80000000 // check for infinity
756 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
758 _ASM_jn(e,TRealXBinOpNaN)
759 _asm jmp TRealXRealIndefinite // if both operands infinite, return 'real indefinite'
761 // come here if divisor is a NaN or infinity, dividend finite
763 _asm cmp edx, 0x80000000 // check for infinity
764 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
766 _ASM_jn(e,TRealXBinOpNaN)
767 _asm and ecx, 1 // dividend is finite, divisor=infinity, so return 0 with xor sign
770 _asm xor eax, eax // return KErrNone
774 // TRealX modulo - dividend at [esi], divisor in ecx,edx:ebx
775 // Result in ecx,edx:ebx
777 __NAKED__ LOCAL_C void TRealXModulo(void)
779 _asm mov eax, [esi+8] // fetch sign/exponent of dividend
780 _asm mov cl, al // result sign=dividend sign
781 _asm xor ch, ch // clear rounding flags
782 _asm cmp eax, 0xFFFF0000 // check if dividend=NaN or infinity
783 _asm jnc modfpss // branch if it is
784 _asm cmp ecx, 0xFFFF0000 // check if divisor=NaN or infinity
785 _asm jnc modfpsd // branch if it is
786 _asm cmp ecx, 0x10000 // check if divisor=0
787 _ASM_j(c,TRealXRealIndefinite) // if so, return 'real indefinite'
788 _asm shr eax, 16 // ax=dividend exponent
789 _asm ror ecx, 16 // cx=divisor exponent
790 _asm sub ax, cx // ax=dividend exponent-divisor exponent
791 _asm jc modfpdd0 // if dividend exponent is smaller, return dividend
792 _asm cmp ax, 64 // check if exponents differ by >= 64 bits
793 _asm jnc modfplp // if so, underflow
794 _asm mov ah, 0 // ah bit 0 acts as 65th accumulator bit
795 _asm mov ebp, [esi] // edi:ebp=dividend mantissa
796 _asm mov edi, [esi+4] //
797 _asm jmp short modfp2 // skip left shift on first iteration
799 _asm add ebp, ebp // shift accumulator left (65 bits)
803 _asm sub ebp, ebx // subtract divisor from dividend
806 _asm jnc short modfp3 // skip if no borrow
807 _asm add ebp, ebx // else add back
811 _asm dec al // any more bits to do?
812 _asm jns short modfp1 // loop if there are
813 _asm mov edx, edi // result mantissa (not yet normalised) into edx:ebx
815 _asm or edi, ebx // check for zero
816 _asm jz modfp0 // jump if result zero
817 _asm or edx, edx // check if ms dword zero
818 _asm jnz short modfp4
819 _asm mov edx, ebx // if so, shift left by 32
821 _asm sub cx, 32 // and decrement exponent by 32
822 _asm jbe modfpund // if borrow or exponent zero, underflow
824 _asm mov edi, ecx // preserve sign and exponent
825 _asm bsr ecx, edx // position of most significant 1 into ecx
827 _asm add ecx, 31 // cl = 31-position of MS 1 = number of shifts to normalise
828 _asm shld edx, ebx, cl // shift edx:ebx left by cl bits
830 _asm mov ebp, ecx // bit count into ebp for subtraction
831 _asm mov ecx, edi // exponent & sign back into ecx
832 _asm sub cx, bp // subtract shift count from exponent
833 _asm jbe short modfpund // if borrow or exponent 0, underflow
834 _asm rol ecx, 16 // else ecx=exponent:sign
835 _asm xor eax, eax // normal exit, result in ecx,edx:ebx
838 // dividend=NaN or infinity
840 _asm mov ebp, [esi] // dividend mantissa into edi:ebp
841 _asm mov edi, [esi+4]
842 _asm cmp edi, 0x80000000 // check for infinity
843 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
845 _ASM_jn(e,TRealXBinOpNaN)
846 _asm cmp ecx, 0xFFFF0000 // check divisor for NaN or infinity
847 _ASM_j(b,TRealXRealIndefinite) // infinity%finite - return 'real indefinite'
848 _asm cmp edx, 0x80000000 // check for divisor=infinity
849 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
851 _ASM_jn(e,TRealXBinOpNaN)
852 _asm jmp TRealXRealIndefinite // if both operands infinite, return 'real indefinite'
854 // divisor=NaN or infinity, dividend finite
856 _asm cmp edx, 0x80000000 // check for infinity
857 _ASM_jn(e,TRealXBinOpNaN) // branch if NaN
859 _ASM_jn(e,TRealXBinOpNaN)
860 // finite%infinity - return dividend unaltered
863 _asm mov ebx, [esi] // normal exit, return dividend unaltered
864 _asm mov edx, [esi+4]
865 _asm mov ecx, [esi+8]
870 _asm shr ecx, 16 // normal exit, result 0
875 _asm shr ecx, 16 // underflow, result 0
876 _asm mov eax, -10 // return KErrUnderflow
880 _asm shr ecx, 16 // loss of precision, result 0
881 _asm mov eax, -7 // return KErrTotalLossOfPrecision
888 __NAKED__ EXPORT_C TRealX::TRealX()
890 Constructs a default extended precision object.
892 This sets the value to zero.
896 _asm mov [ecx], eax // set value to zero
897 _asm mov [ecx+4], eax
898 _asm mov [ecx+8], eax
899 _asm mov eax, ecx // must return this
906 __NAKED__ EXPORT_C TRealX::TRealX(TUint /*aExp*/, TUint /*aMantHi*/, TUint /*aMantLo*/)
908 Constructs an extended precision object from an explicit exponent and
911 @param aExp The exponent
912 @param aMantHi The high order 32 bits of the 64 bit mantissa
913 @param aMantLo The low order 32 bits of the 64 bit mantissa
916 _asm mov eax, [esp+4] // eax=aExp
917 _asm mov [ecx+8], eax
918 _asm mov eax, [esp+8] // eax=aMantHi
919 _asm mov [ecx+4], eax
920 _asm mov eax, [esp+12] // eax=aMantLo
922 _asm mov eax, ecx // must return this
929 __NAKED__ EXPORT_C TInt TRealX::Set(TInt /*aInt*/)
931 Gives this extended precision object a new value taken
932 from a signed integer.
934 @param aInt The signed integer value.
936 @return KErrNone, always.
939 // on entry ecx=this, [esp+4]=aInt, return code in eax
940 _asm mov edx, [esp+4] // edx=aInt
941 _asm or edx, edx // test sign/zero
943 _asm jz short trealxfromint0 // branch if 0
944 _asm jns short trealxfromint1 // skip if positive
945 _asm neg edx // take absolute value
946 _asm add eax, 0x10000 // sign bit in eax bit 16
948 _asm push ecx // save this
949 _asm bsr ecx, edx // bit number of edx MSB into ecx
950 _asm add eax, ecx // add to eax to form result exponent
952 _asm add cl, 31 // 31-bit number = number of shifts to normalise edx
953 _asm shl edx, cl // normalise edx
954 _asm pop ecx // this back into ecx
955 _asm ror eax, 16 // sign/exponent into normal positions
956 _asm mov [ecx+4], edx // store mantissa high word
957 _asm mov [ecx+8], eax // store sign/exponent
959 _asm mov [ecx], eax // zero mantissa low word
960 _asm ret 4 // return KErrNone
963 _asm mov [ecx+4], edx // store mantissa high word=0
964 _asm mov [ecx+8], edx // store sign/exponent=0
965 _asm xor eax, eax // return KErrNone
972 __NAKED__ EXPORT_C TInt TRealX::Set(TUint /*aInt*/)
974 Gives this extended precision object a new value taken from
977 @param aInt The unsigned integer value.
979 @return KErrNone, always.
982 // on entry ecx=this, [esp+4]=aInt, return code in eax
983 _asm mov edx, [esp+4] // edx=aInt
985 _asm or edx, edx // test for 0
986 _asm jz short trealxfromuint0 // branch if 0
987 _asm push ecx // save this
988 _asm bsr ecx, edx // bit number of edx MSB into ecx
989 _asm add eax, ecx // add to eax to form result exponent
991 _asm add cl, 31 // 31-bit number = number of shifts to normalise edx
992 _asm shl edx, cl // normalise edx
993 _asm pop ecx // this back into ecx
994 _asm shl eax, 16 // exponent into normal position
995 _asm mov [ecx+4], edx // store mantissa high word
996 _asm mov [ecx+8], eax // store exponent
998 _asm mov [ecx], eax // zero mantissa low word
999 _asm ret 4 // return KErrNone
1002 _asm mov [ecx+4], edx // store mantissa high word=0
1003 _asm mov [ecx+8], edx // store sign/exponent=0
1004 _asm xor eax, eax // return KErrNone
1011 __NAKED__ LOCAL_C void TRealXFromTInt64(void)
1013 // Convert TInt64 in edx:ebx to TRealX in ecx,edx:ebx
1014 _asm mov eax, 0x7FFF
1015 _asm or edx, edx // test sign/zero
1016 _asm jz short trealxfromtint64a // branch if top word zero
1017 _asm jns short trealxfromtint64b
1018 _asm add eax, 0x10000 // sign bit into eax bit 16
1019 _asm neg edx // take absolute value
1022 _asm jz short trealxfromtint64d // branch if top word zero
1024 _asm bsr ecx, edx // ecx=bit number of edx MSB
1025 _asm add eax, ecx // add to exponent in eax
1028 _asm add cl, 31 // 31-bit number = number of left shifts to normalise
1029 _asm shld edx, ebx, cl // shift left to normalise edx:ebx
1031 _asm mov ecx, eax // sign/exponent into ecx
1032 _asm ror ecx, 16 // and into normal positions
1034 trealxfromtint64a: // come here if top word zero
1035 _asm or ebx, ebx // test for bottom word also zero
1036 _asm jz short trealxfromtint64c // branch if it is
1037 trealxfromtint64d: // come here if top word zero, bottom word not
1038 _asm mov edx, ebx // shift edx:ebx left 32
1040 _asm bsr ecx, edx // ecx=bit number of edx MSB
1041 _asm add eax, ecx // add to exponent in eax
1043 _asm add cl, 31 // 31-bit number = number of left shifts to normalise
1044 _asm shl edx, cl // normalise
1045 _asm mov ecx, eax // sign/exponent into ecx
1046 _asm ror ecx, 16 // and into normal positions
1048 trealxfromtint64c: // entire number is zero
1056 __NAKED__ EXPORT_C TInt TRealX::Set(const TInt64& /*aInt*/)
1058 Gives this extended precision object a new value taken from
1061 @param aInt The 64 bit integer value.
1063 @return KErrNone, always.
1066 // on entry ecx=this, [esp+4]=address of aInt, return code in eax
1069 _asm mov edx, [esp+12] // edx=address of aInt
1071 _asm mov edx, [edx+4] // edx:ebx=aInt
1072 _asm call TRealXFromTInt64 // convert to TRealX in ecx,edx:ebx
1073 _asm pop eax // eax=this
1074 _asm mov [eax], ebx // store result
1075 _asm mov [eax+4], edx
1076 _asm mov [eax+8], ecx
1077 _asm xor eax, eax // return KErrNone
1085 __NAKED__ LOCAL_C void __6TRealXi()
1087 // common function for int to TRealX
1088 _asm mov edx, [esp+4] // edx=aInt
1089 _asm or edx, edx // test sign/zero
1090 _asm mov eax, 0x7FFF
1091 _asm jz short trealxfromint0 // branch if 0
1092 _asm jns short trealxfromint1 // skip if positive
1093 _asm neg edx // take absolute value
1094 _asm add eax, 0x10000 // sign bit in eax bit 16
1096 _asm push ecx // save this
1097 _asm bsr ecx, edx // bit number of edx MSB into ecx
1098 _asm add eax, ecx // add to eax to form result exponent
1100 _asm add cl, 31 // 31-bit number = number of shifts to normalise edx
1101 _asm shl edx, cl // normalise edx
1102 _asm pop ecx // this back into ecx
1103 _asm ror eax, 16 // sign/exponent into normal positions
1104 _asm mov [ecx+4], edx // store mantissa high word
1105 _asm mov [ecx+8], eax // store sign/exponent
1107 _asm mov [ecx], eax // zero mantissa low word
1108 _asm mov eax, ecx // return eax=this
1112 _asm mov [ecx+4], edx // store mantissa high word=0
1113 _asm mov [ecx+8], edx // store sign/exponent=0
1114 _asm mov eax, ecx // return eax=this
1121 __NAKED__ EXPORT_C TRealX::TRealX(TInt /*aInt*/)
1123 Constructs an extended precision object from a signed integer value.
1125 @param aInt The signed integer value.
1128 // on entry ecx=this, [esp+4]=aInt, return eax=this
1135 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TInt /*aInt*/)
1137 Assigns the specified signed integer value to this extended precision object.
1139 @param aInt The signed integer value.
1141 @return A reference to this extended precision object.
1144 // on entry ecx=this, [esp+4]=aInt, return eax=this
1151 __NAKED__ LOCAL_C void __6TRealXui()
1153 // common function for unsigned int to TRealX
1154 _asm mov edx, [esp+4] // edx=aInt
1155 _asm mov eax, 0x7FFF
1156 _asm or edx, edx // test for zero
1157 _asm jz short trealxfromuint0 // branch if 0
1158 _asm push ecx // save this
1159 _asm bsr ecx, edx // bit number of edx MSB into ecx
1160 _asm add eax, ecx // add to eax to form result exponent
1162 _asm add cl, 31 // 31-bit number = number of shifts to normalise edx
1163 _asm shl edx, cl // normalise edx
1164 _asm pop ecx // this back into ecx
1165 _asm shl eax, 16 // exponent into normal position
1166 _asm mov [ecx+4], edx // store mantissa high word
1167 _asm mov [ecx+8], eax // store exponent
1169 _asm mov [ecx], eax // zero mantissa low word
1170 _asm mov eax, ecx // return eax=this
1174 _asm mov [ecx+4], edx // store mantissa high word=0
1175 _asm mov [ecx+8], edx // store sign/exponent=0
1176 _asm mov eax, ecx // return eax=this
1183 __NAKED__ EXPORT_C TRealX::TRealX(TUint /*aInt*/)
1185 Constructs an extended precision object from an unsigned integer value.
1187 @param aInt The unsigned integer value.
1190 // on entry ecx=this, [esp+4]=aInt, return eax=this
1191 _asm jmp __6TRealXui
1197 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TUint /*aInt*/)
1199 Assigns the specified unsigned integer value to this extended precision object.
1201 @param aInt The unsigned integer value.
1203 @return A reference to this extended precision object.
1206 // on entry ecx=this, [esp+4]=aInt, return eax=this
1207 _asm jmp __6TRealXui
1213 __NAKED__ LOCAL_C void __6TRealXRC6TInt64()
1215 // common function for TInt64 to TRealX
1216 _asm push ebx // preserve ebx
1217 _asm push ecx // save this
1218 _asm mov edx, [esp+12] // edx=address of aInt
1220 _asm mov edx, [edx+4] // edx:ebx=aInt
1221 _asm call TRealXFromTInt64 // convert to TRealX in ecx,edx:ebx
1222 _asm pop eax // eax=this
1223 _asm mov [eax], ebx // store result
1224 _asm mov [eax+4], edx
1225 _asm mov [eax+8], ecx
1226 _asm pop ebx // restore ebx
1227 _asm ret 4 // return this in eax
1233 __NAKED__ EXPORT_C TRealX::TRealX(const TInt64& /*aInt*/)
1235 Constructs an extended precision object from a 64 bit integer.
1237 @param aInt A reference to a 64 bit integer.
1240 // on entry ecx=this, [esp+4]=address of aInt, return eax=this
1241 _asm jmp __6TRealXRC6TInt64
1247 __NAKED__ EXPORT_C TRealX& TRealX::operator=(const TInt64& /*aInt*/)
1249 Assigns the specified 64 bit integer value to this extended precision object.
1251 @param aInt A reference to a 64 bit integer.
1253 @return A reference to this extended precision object.
1256 // on entry ecx=this, [esp+4]=address of aInt, return eax=this
1257 _asm jmp __6TRealXRC6TInt64
1263 __NAKED__ LOCAL_C void ConvertTReal32ToTRealX(void)
1265 // Convert TReal32 in edx to TRealX in ecx:edx,ebx
1266 _asm xor ebx, ebx // mant low always zero
1268 _asm shr eax, 23 // exponent now in al, sign in ah bit 0
1269 _asm test al, al // check for denormal/zero
1270 _asm jz short treal32totrealx2 // branch if denormal/zero
1273 _asm add ecx, 0x7F80 // bias exponent correctly for TRealX
1274 _asm cmp al, 0xFF // check for infinity/NaN
1275 _asm jnz short treal32totrealx1 // skip if neither
1276 _asm mov cl, al // else set TRealX exponent to FFFF
1279 _asm shl edx, 8 // left-justify mantissa in edx
1280 _asm or edx, 0x80000000 // put in implied integer bit
1281 _asm shl ecx, 16 // exponent into ecx bits 16-31
1282 _asm mov cl, ah // sign into ecx bit 0
1284 treal32totrealx2: // come here if exponent 0
1285 _asm shl edx, 9 // left-justify mantissa in edx (shift out integer bit as well)
1286 _asm jnz short treal32totrealx3 // jump if denormal
1287 _asm xor ecx, ecx // else return 0
1288 _asm mov cl, ah // with same sign as input value
1290 treal32totrealx3: // come here if denormal
1291 _asm bsr ecx, edx // ecx=bit number of MSB of edx
1293 _asm add ecx, 31 // ecx=number of left shifts to normalise edx
1294 _asm shl edx, cl // normalise
1296 _asm add ecx, 0x7F80 // exponent=7F80-number of shifts
1297 _asm shl ecx, 16 // exponent into ecx bits 16-31
1298 _asm mov cl, ah // sign into ecx bit 0
1302 __NAKED__ LOCAL_C void ConvertTReal64ToTRealX(void)
1304 // Convert TReal64 in edx:ebx to TRealX in ecx:edx,ebx
1308 _asm and ecx, eax // ecx=exponent
1309 _asm jz short treal64totrealx1 // branch if zero/denormal
1310 _asm add ecx, 0x7C00 // else bias exponent correctly for TRealX
1311 _asm cmp ecx, 0x83FF // check for infinity/NaN
1312 _asm jnz short treal64totrealx2
1313 _asm mov ch, cl // if so, set exponent to FFFF
1315 _asm shl ecx, 16 // exponent into ecx bits 16-31
1316 _asm mov cl, 11 // number of shifts needed to justify mantissa correctly
1317 _asm shld edx, ebx, cl // shift mantissa left
1319 _asm or edx, 0x80000000 // put in implied integer bit
1320 _asm shr eax, 11 // sign bit into al bit 0
1321 _asm mov cl, al // into ecx bit 0
1323 treal64totrealx1: // come here if zero/denormal
1324 _asm mov cl, 12 // number of shifts needed to justify mantissa correctly
1325 _asm shld edx, ebx, cl // shift mantissa left
1327 _asm test edx, edx // check for zero
1328 _asm jnz short treal64totrealx3
1330 _asm jnz short treal64totrealx4
1331 _asm shr eax, 11 // sign bit into eax bit 0, rest of eax=0
1332 _asm mov ecx, eax // return 0 result with correct sign
1334 treal64totrealx4: // come here if denormal, edx=0
1335 _asm mov edx, ebx // shift mantissa left 32
1337 _asm bsr ecx, edx // ecx=bit number of MSB of edx
1339 _asm add ecx, 31 // ecx=number of left shifts to normalise edx
1340 _asm shl edx, cl // normalise
1342 _asm add ecx, 0x7BE0 // exponent=7BE0-number of shifts
1343 _asm shl ecx, 16 // exponent into bits 16-31 of ecx
1345 _asm mov cl, al // sign into bit 0 of ecx
1347 treal64totrealx3: // come here if denormal, edx nonzero
1348 _asm bsr ecx, edx // ecx=bit number of MSB of edx
1350 _asm add ecx, 31 // ecx=number of left shifts to normalise edx:ebx
1351 _asm shld edx, ebx, cl // normalise
1354 _asm add ecx, 0x7C00 // exponent=7C00-number of shifts
1355 _asm shl ecx, 16 // exponent into bits 16-31 of ecx
1357 _asm mov cl, al // sign into bit 0 of ecx
1364 __NAKED__ EXPORT_C TInt TRealX::Set(TReal32 /*aReal*/)
1366 Gives this extended precision object a new value taken from
1367 a single precision floating point number.
1369 @param aReal The single precision floating point value.
1371 @return KErrNone, if a valid number;
1372 KErrOverflow, if the number is infinite;
1373 KErrArgument, if not a number.
1376 // on entry, ecx=this and aReal is in [esp+4]
1377 // on exit, error code in eax
1378 _asm push ebx // save ebx
1379 _asm push ecx // save this
1380 _asm mov edx, [esp+12] // aReal into edx
1381 _asm call ConvertTReal32ToTRealX
1382 _asm pop eax // eax=this
1383 _asm mov [eax], ebx // store result
1384 _asm mov [eax+4], edx
1385 _asm mov [eax+8], ecx
1386 _asm xor eax, eax // error code=KErrNone initially
1387 _asm cmp ecx, 0xFFFF0000 // check for infinity/NaN
1388 _asm jb short trealxsettreal32a // if neither, return KErrNone
1389 _asm mov eax, -9 // eax=KErrOverflow
1390 _asm cmp edx, 0x80000000 // check for infinity
1391 _asm je short trealxsettreal32a // if infinity, return KErrOverflow
1392 _asm mov eax, -6 // if NaN, return KErrArgument
1401 __NAKED__ EXPORT_C TInt TRealX::Set(TReal64 /*aReal*/)
1403 Gives this extended precision object a new value taken from
1404 a double precision floating point number.
1406 @param aReal The double precision floating point value.
1408 @return KErrNone, if a valid number;
1409 KErrOverflow, if the number is infinite;
1410 KErrArgument, if not a number.
1413 // on entry, ecx=this and aReal is in [esp+4] (mant low) and [esp+8] (sign/exp/mant high)
1414 // on exit, error code in eax
1415 _asm push ebx // save ebx
1416 _asm push ecx // save this
1417 _asm mov ebx, [esp+12] // aReal into edx:ebx
1418 _asm mov edx, [esp+16]
1419 _asm call ConvertTReal64ToTRealX
1420 _asm pop eax // eax=this
1421 _asm mov [eax], ebx // store result
1422 _asm mov [eax+4], edx
1423 _asm mov [eax+8], ecx
1424 _asm xor eax, eax // error code=KErrNone initially
1425 _asm cmp ecx, 0xFFFF0000 // check for infinity/NaN
1426 _asm jb short trealxsettreal64a // if neither, return KErrNone
1427 _asm mov eax, -9 // eax=KErrOverflow
1428 _asm cmp edx, 0x80000000 // check for infinity
1429 _asm jne short trealxsettreal64b // branch if NaN
1431 _asm je short trealxsettreal64a // if infinity, return KErrOverflow
1433 _asm mov eax, -6 // if NaN, return KErrArgument
1442 __NAKED__ LOCAL_C void __6TRealXf()
1444 // common function for float to TRealX
1445 _asm push ebx // save ebx
1446 _asm push ecx // save this
1447 _asm mov edx, [esp+12] // aReal into edx
1448 _asm call ConvertTReal32ToTRealX
1449 _asm pop eax // eax=this
1450 _asm mov [eax], ebx // store result
1451 _asm mov [eax+4], edx
1452 _asm mov [eax+8], ecx
1460 __NAKED__ EXPORT_C TRealX::TRealX(TReal32 /*aReal*/)
1462 Constructs an extended precision object from
1463 a single precision floating point number.
1465 @param aReal The single precision floating point value.
1468 // on entry, ecx=this and aReal is in [esp+4]
1469 // on exit, eax=this
1476 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TReal32 /*aReal*/)
1478 Assigns the specified single precision floating point number to
1479 this extended precision object.
1481 @param aReal The single precision floating point value.
1483 @return A reference to this extended precision object.
1486 // on entry, ecx=this and aReal is in [esp+4]
1487 // on exit, eax=this
1494 __NAKED__ LOCAL_C void __6TRealXd()
1496 // common function for double to TRealX
1497 _asm push ebx // save ebx
1498 _asm push ecx // save this
1499 _asm mov ebx, [esp+12] // aReal into edx:ebx
1500 _asm mov edx, [esp+16]
1501 _asm call ConvertTReal64ToTRealX
1502 _asm pop eax // eax=this
1503 _asm mov [eax], ebx // store result
1504 _asm mov [eax+4], edx
1505 _asm mov [eax+8], ecx
1513 __NAKED__ EXPORT_C TRealX::TRealX(TReal64 /*aReal*/)
1515 Constructs an extended precision object from
1516 a double precision floating point number.
1518 @param aReal The double precision floating point value.
1521 // on entry, ecx=this and aReal is in [esp+4] (mant low) and [esp+8] (sign/exp/mant high)
1522 // on exit, eax=this
1529 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TReal64 /*aReal*/)
1531 Assigns the specified double precision floating point number to
1532 this extended precision object.
1534 @param aReal The double precision floating point value.
1536 @return A reference to this extended precision object.
1539 // on entry, ecx=this and aReal is in [esp+4] (mant low) and [esp+8] (sign/exp/mant high)
1540 // on exit, eax=this
1547 __NAKED__ EXPORT_C TRealX::operator TInt() const
1549 Gets the extended precision value as a signed integer value.
1551 The operator returns:
1553 1. zero , if the extended precision value is not a number
1555 2. 0x7FFFFFFF, if the value is positive and too big to fit into a TInt.
1557 3. 0x80000000, if the value is negative and too big to fit into a TInt.
1560 // on entry ecx=this, return value in eax
1561 _asm mov edx, [ecx] // edx=mantissa low
1562 _asm mov eax, [ecx+4] // eax=mantissa high
1563 _asm mov ecx, [ecx+8] // ecx=exponent/sign
1564 _asm ror ecx, 16 // exponent into cx
1566 _asm jz short trealxtoint1 // branch if exp=FFFF
1569 _asm sub cx, dx // cx=number of right shifts needed to convert mantissa to int
1570 _asm jbe short trealxtoint2 // if exp>=801E, saturate result
1571 _asm cmp cx, 31 // more than 31 shifts needed?
1572 _asm ja short trealxtoint0 // if so, underflow to zero
1573 _asm shr eax, cl // else ABS(result)=eax>>cl
1574 _asm test ecx, 0x10000 // test sign
1575 _asm jz short trealxtoint3 // skip if +
1579 trealxtoint1: // come here if exponent=FFFF
1580 _asm cmp eax, 0x80000000 // check for infinity
1581 _asm jnz short trealxtoint0 // if NaN, return 0
1583 _asm jnz short trealxtoint0 // if NaN, return 0
1584 trealxtoint2: // come here if argument too big for 32-bit integer
1585 _asm mov eax, 0x7FFFFFFF
1586 _asm shr ecx, 17 // sign bit into carry flag
1587 _asm adc eax, 0 // eax=7FFFFFFF if +, 80000000 if -
1588 _asm ret // return saturated value
1589 trealxtoint0: // come here if INT(argument)=0 or NaN
1590 _asm xor eax, eax // return 0
1597 __NAKED__ EXPORT_C TRealX::operator TUint() const
1599 Returns the extended precision value as an unsigned signed integer value.
1601 The operator returns:
1603 1. zero, if the extended precision value is not a number
1605 2. 0xFFFFFFFF, if the value is positive and too big to fit into a TUint.
1607 3. zero, if the value is negative and too big to fit into a TUint.
1610 // on entry ecx=this, return value in eax
1611 _asm mov edx, [ecx] // edx=mantissa low
1612 _asm mov eax, [ecx+4] // eax=mantissa high
1613 _asm mov ecx, [ecx+8] // ecx=exponent/sign
1614 _asm ror ecx, 16 // exponent into cx
1616 _asm jz short trealxtouint1 // branch if exp=FFFF
1619 _asm sub cx, dx // cx=number of right shifts needed to convert mantissa to int
1620 _asm jb short trealxtouint2 // if exp>801E, saturate result
1621 _asm cmp cx, 31 // more than 31 shifts needed?
1622 _asm ja short trealxtouint0 // if so, underflow to zero
1623 _asm test ecx, 0x10000 // test sign
1624 _asm jnz short trealxtouint0 // if -, return 0
1625 _asm shr eax, cl // else result=eax>>cl
1627 trealxtouint1: // come here if exponent=FFFF
1628 _asm cmp eax, 0x80000000 // check for infinity
1629 _asm jnz short trealxtouint0 // if NaN, return 0
1631 _asm jnz short trealxtouint0 // if NaN, return 0
1632 trealxtouint2: // come here if argument too big for 32-bit integer
1633 _asm mov eax, 0xFFFFFFFF
1634 _asm shr ecx, 17 // sign bit into carry flag
1635 _asm adc eax, 0 // eax=FFFFFFFF if +, 0 if -
1636 _asm ret // return saturated value
1637 trealxtouint0: // come here if INT(argument)=0 or NaN
1638 _asm xor eax, eax // return 0
1645 __NAKED__ LOCAL_C void ConvertTRealXToTInt64(void)
1647 // Convert TRealX in ecx,edx:ebx to TInt64 in edx:ebx
1648 _asm ror ecx, 16 // exponent into cx
1650 _asm jz short trealxtoint64a // branch if exp=FFFF
1653 _asm sub cx, ax // cx=number of right shifts needed to convert mantissa to int
1654 _asm jbe short trealxtoint64b // if exp>=803E, saturate result
1655 _asm cmp cx, 63 // more than 63 shifts needed?
1656 _asm ja short trealxtoint64z // if so, underflow to zero
1657 _asm cmp cl, 31 // more than 31 shifts needed?
1658 _asm jbe short trealxtoint64d // branch if not
1659 _asm sub cl, 32 // cl=shift count - 32
1660 _asm mov ebx, edx // shift right by 32
1663 _asm shrd ebx, edx, cl // shift edx:ebx right by cl to give ABS(result)
1665 _asm test ecx, 0x10000 // test sign
1666 _asm jz short trealxtoint64c // skip if +
1667 _asm neg edx // if -, negate
1672 trealxtoint64a: // come here if exponent=FFFF
1673 _asm cmp edx, 0x80000000 // check for infinity
1674 _asm jnz short trealxtoint64z // if NaN, return 0
1676 _asm jnz short trealxtoint64z // if NaN, return 0
1677 trealxtoint64b: // come here if argument too big for 32-bit integer
1678 _asm mov edx, 0x7FFFFFFF
1679 _asm mov ebx, 0xFFFFFFFF
1680 _asm shr ecx, 17 // sign bit into carry flag
1681 _asm adc ebx, 0 // edx:ebx=7FFFFFFF FFFFFFFF if +,
1682 _asm adc edx, 0 // or 80000000 00000000 if -
1683 _asm ret // return saturated value
1684 trealxtoint64z: // come here if INT(argument)=0 or NaN
1685 _asm xor edx, edx // return 0
1694 Returns the extended precision value as a 64 bit integer value.
1696 The operator returns:
1698 1. zero, if the extended precision value is not a number
1700 2. 0x7FFFFFFF FFFFFFFF, if the value is positive and too big to fit
1703 3. 0x80000000 00000000, if the value is negative and too big to fit
1706 __NAKED__ EXPORT_C TRealX::operator TInt64() const
1708 // on entry, ecx=this, return value in edx:eax
1710 _asm mov ebx, [ecx] // get TRealX value into ecx,edx:ebx
1711 _asm mov edx, [ecx+4]
1712 _asm mov ecx, [ecx+8]
1713 _asm call ConvertTRealXToTInt64
1714 _asm mov eax, ebx // store low result into eax
1722 __NAKED__ LOCAL_C void TRealXGetTReal32(void)
1724 // Convert TRealX in ecx,edx:ebx to TReal32 in edx
1725 // Return error code in eax
1726 _asm cmp ecx, 0xFFFF0000 // check for infinity/NaN
1727 _asm jnc short trealxgettreal32a
1729 _asm ror ecx, 16 // exponent into cx
1730 _asm sub cx, 0x7F80 // cx=result exponent if normalised
1731 _asm jbe short trealxgettreal32b // jump if denormal, zero or underflow
1732 _asm cmp cx, 0xFF // check if overflow
1733 _asm jb short trealxgettreal32c // jump if not
1734 trealxgettreal32d: // come here if overflow
1735 _asm xor edx, edx // set mantissa=0 to generate infinity
1736 _asm ror ecx, 16 // ecx back to normal format
1737 trealxgettreal32a: // come here if infinity or NaN
1739 _asm or edx, 0xFF000000 // set exponent to FF
1740 _asm shr ecx, 1 // sign bit -> carry
1741 _asm rcr edx, 1 // sign bit -> MSB of result
1743 _asm shl eax, 9 // test for infinity or NaN
1744 _asm mov eax, -9 // eax=KErrOverflow
1745 _asm jz short trealxgettreal32e
1746 _asm mov eax, -6 // if NaN, eax=KErrArgument
1749 trealxgettreal32b: // come here if exponent<=7F80
1750 _asm cmp cx, -24 // check for zero or total underflow
1751 _asm jle short trealxgettreal32z
1753 _asm inc cl // cl=number of right shifts to form denormal mantissa
1754 _asm shrd eax, ebx, cl // shift mantissa right into eax
1755 _asm shrd ebx, edx, cl
1757 _asm or edx, 0x80000000 // set top bit to ensure correct rounding up
1758 _asm xor cl, cl // cl=result exponent=0
1759 trealxgettreal32c: // come here if result normalised
1760 _asm cmp dl, 0x80 // check rounding bits
1761 _asm ja short trealxgettreal32f // branch to round up
1762 _asm jb short trealxgettreal32g // branch to round down
1764 _asm jnz short trealxgettreal32f // branch to round up
1766 _asm jnz short trealxgettreal32f // branch to round up
1767 _asm test ecx, 0x01000000 // check rounded-down flag
1768 _asm jnz short trealxgettreal32f // branch to round up
1769 _asm test ecx, 0x02000000 // check rounded-up flag
1770 _asm jnz short trealxgettreal32g // branch to round down
1771 _asm test dh, 1 // else round to even
1772 _asm jz short trealxgettreal32g // branch to round down if LSB=0
1773 trealxgettreal32f: // come here to round up
1774 _asm add edx, 0x100 // increment mantissa
1775 _asm jnc short trealxgettreal32g
1777 _asm inc cl // if carry, increment exponent
1778 _asm cmp cl, 0xFF // and check for overflow
1779 _asm jz short trealxgettreal32d // branch out if overflow
1780 trealxgettreal32g: // come here to round down
1782 _asm add edx, edx // shift out integer bit
1784 _asm ror edx, 8 // exponent->edx bits 24-31, mantissa in 23-1
1785 _asm test edx, edx // check if underflow
1786 _asm jz short trealxgettreal32h // branch out if underflow
1787 _asm shr ecx, 17 // sign bit->carry
1788 _asm rcr edx, 1 // ->edx bit 31, exp->edx bits 23-30, mant->edx bits 22-0
1789 _asm xor eax, eax // return KErrNone
1791 trealxgettreal32z: // come here if zero or underflow
1793 _asm cmp cx, 0x8080 // check for zero
1794 _asm jz short trealxgettreal32y // if zero, return KErrNone
1795 trealxgettreal32h: // come here if underflow after rounding
1796 _asm mov eax, -10 // eax=KErrUnderflow
1800 _asm rcr edx, 1 // sign bit into edx bit 31, rest of edx=0
1807 __NAKED__ LOCAL_C void TRealXGetTReal64(void)
1809 // Convert TRealX in ecx,edx:ebx to TReal64 in edx:ebx
1810 // Return error code in eax
1811 // edi, esi also modified
1812 _asm ror ecx, 16 // exponent into cx
1813 _asm cmp cx, 0xFFFF // check for infinity/NaN
1814 _asm jnc short trealxgettreal64a
1817 _asm sub cx, 0x7C00 // cx=result exponent if normalised
1818 _asm jbe short trealxgettreal64b // jump if denormal, zero or underflow
1819 _asm cmp cx, 0x07FF // check if overflow
1820 _asm jb short trealxgettreal64c // jump if not
1821 trealxgettreal64d: // come here if overflow
1822 _asm xor edx, edx // set mantissa=0 to generate infinity
1824 trealxgettreal64a: // come here if infinity or NaN
1826 _asm shrd ebx, edx, cl
1828 _asm or edx, 0xFFE00000 // set exponent to 7FF
1829 _asm shr ecx, 17 // sign bit -> carry
1830 _asm rcr edx, 1 // sign bit -> MSB of result
1833 _asm shl eax, 12 // test for infinity or NaN
1834 _asm mov eax, -9 // eax=KErrOverflow
1835 _asm jnz short trealxgettreal64n
1837 _asm jz short trealxgettreal64e
1839 _asm mov eax, -6 // if NaN, eax=KErrArgument
1842 trealxgettreal64b: // come here if exponent<=7C00
1843 _asm cmp cx, -53 // check for zero or total underflow
1844 _asm jle trealxgettreal64z
1846 _asm inc cl // cl=number of right shifts to form denormal mantissa
1848 _asm jb trealxgettreal64x
1849 _asm mov eax, ebx // if >=32 shifts, do 32 shifts and decrement count by 32
1853 _asm shrd edi, eax, cl
1854 _asm shrd eax, ebx, cl // shift mantissa right into eax
1855 _asm shrd ebx, edx, cl
1857 _asm or edx, 0x80000000 // set top bit to ensure correct rounding up
1858 _asm xor cx, cx // cx=result exponent=0
1859 trealxgettreal64c: // come here if result normalised
1861 _asm and esi, 0x7FF // esi=rounding bits
1862 _asm cmp esi, 0x400 // check rounding bits
1863 _asm ja short trealxgettreal64f // branch to round up
1864 _asm jb short trealxgettreal64g // branch to round down
1866 _asm jnz short trealxgettreal64f // branch to round up
1868 _asm jnz short trealxgettreal64f // branch to round up
1869 _asm test ecx, 0x01000000 // check rounded-down flag
1870 _asm jnz short trealxgettreal64f // branch to round up
1871 _asm test ecx, 0x02000000 // check rounded-up flag
1872 _asm jnz short trealxgettreal64g // branch to round down
1873 _asm test ebx, 0x800 // else round to even
1874 _asm jz short trealxgettreal64g // branch to round down if LSB=0
1875 trealxgettreal64f: // come here to round up
1876 _asm add ebx, 0x800 // increment mantissa
1878 _asm jnc short trealxgettreal64g
1880 _asm inc cx // if carry, increment exponent
1881 _asm cmp cx, 0x7FF // and check for overflow
1882 _asm jz trealxgettreal64d // branch out if overflow
1883 trealxgettreal64g: // come here to round down
1884 _asm xor bl, bl // clear rounding bits
1886 _asm mov di, cx // save exponent
1888 _asm and edx, 0x7FFFFFFF // clear integer bit
1889 _asm shrd ebx, edx, cl // shift mantissa right by 10
1891 _asm shl edi, 21 // exponent into edi bits 21-31
1892 _asm or edx, edi // into edx bits 21-31
1893 _asm test edx, edx // check if underflow
1894 _asm jnz short trealxgettreal64i
1896 _asm jz short trealxgettreal64h // branch out if underflow
1898 _asm shr ecx, 17 // sign bit->carry
1899 _asm rcr edx, 1 // ->edx bit 31, exp->edx bits 20-30, mant->edx bits 20-0
1901 _asm xor eax, eax // return KErrNone
1903 trealxgettreal64z: // come here if zero or underflow
1905 _asm cmp cx, 0x8400 // check for zero
1906 _asm jz short trealxgettreal64y // if zero, return KErrNone
1907 trealxgettreal64h: // come here if underflow after rounding
1908 _asm mov eax, -10 // eax=KErrUnderflow
1913 _asm rcr edx, 1 // sign bit into edx bit 31, rest of edx=0, ebx=0
1920 __NAKED__ EXPORT_C TRealX::operator TReal32() const
1922 Returns the extended precision value as
1923 a single precision floating point value.
1926 // On entry, ecx=this
1927 // On exit, TReal32 value on top of FPU stack
1929 _asm mov ebx, [ecx] // *this into ecx,edx:ebx
1930 _asm mov edx, [ecx+4]
1931 _asm mov ecx, [ecx+8]
1932 _asm call TRealXGetTReal32 // Convert to TReal32 in edx
1933 _asm push edx // push TReal32 onto stack
1934 _asm fld dword ptr [esp] // push TReal32 onto FPU stack
1943 __NAKED__ EXPORT_C TRealX::operator TReal64() const
1945 Returns the extended precision value as
1946 a double precision floating point value.
1949 // On entry, ecx=this
1950 // On exit, TReal64 value on top of FPU stack
1954 _asm mov ebx, [ecx] // *this into ecx,edx:ebx
1955 _asm mov edx, [ecx+4]
1956 _asm mov ecx, [ecx+8]
1957 _asm call TRealXGetTReal64 // Convert to TReal32 in edx:ebx
1958 _asm push edx // push TReal64 onto stack
1960 _asm fld qword ptr [esp] // push TReal64 onto FPU stack
1971 __NAKED__ EXPORT_C TInt TRealX::GetTReal(TReal32& /*aVal*/) const
1973 Extracts the extended precision value as
1974 a single precision floating point value.
1976 @param aVal A reference to a single precision object which contains
1977 the result of the operation.
1979 @return KErrNone, if the operation is successful;
1980 KErrOverflow, if the operation results in overflow;
1981 KErrUnderflow, if the operation results in underflow.
1984 // On entry, ecx=this, [esp+4]=address of aVal
1985 // On exit, eax=return code
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 TRealXGetTReal32
1991 _asm mov ecx, [esp+8] // ecx=address of aVal
1992 _asm mov [ecx], edx // store result
1994 _asm ret 4 // return with error code in eax
2000 __NAKED__ EXPORT_C TInt TRealX::GetTReal(TReal64& /*aVal*/) const
2002 Extracts the extended precision value as
2003 a double precision floating point value.
2005 @param aVal A reference to a double precision object which
2006 contains the result of the operation.
2008 @return KErrNone, if the operation is successful;
2009 KErrOverflow, if the operation results in overflow;
2010 KErrUnderflow, if the operation results in underflow.
2013 // On entry, ecx=this, [esp+4]=address of aVal
2014 // On exit, eax=return code
2018 _asm mov ebx, [ecx] // *this into ecx,edx:ebx
2019 _asm mov edx, [ecx+4]
2020 _asm mov ecx, [ecx+8]
2021 _asm call TRealXGetTReal64
2022 _asm mov ecx, [esp+16] // ecx=address of aVal
2023 _asm mov [ecx], ebx // store result
2024 _asm mov [ecx+4], edx
2028 _asm ret 4 // return with error code in eax
2034 __NAKED__ EXPORT_C void TRealX::SetZero(TBool /*aNegative*/)
2036 Sets the value of this extended precision object to zero.
2038 @param aNegative ETrue, the value is a negative zero;
2039 EFalse, the value is a positive zero, this is the default.
2042 _asm mov edx, [esp+4] // aNegative into edx
2043 _asm xor eax, eax // eax=0
2045 _asm mov [ecx+4], eax
2047 _asm jz short setzero1
2048 _asm inc eax // eax=1 if aNegative!=0
2050 _asm mov [ecx+8], eax // generate positive or negative zero
2057 __NAKED__ EXPORT_C void TRealX::SetNaN()
2059 Sets the value of this extended precision object to 'not a number'.
2062 _asm xor eax, eax // set *this to 'real indefinite'
2064 _asm mov eax, 0xC0000000
2065 _asm mov [ecx+4], eax
2066 _asm mov eax, 0xFFFF0001
2067 _asm mov [ecx+8], eax
2074 __NAKED__ EXPORT_C void TRealX::SetInfinite(TBool /*aNegative*/)
2076 Sets the value of this extended precision object to infinity.
2078 @param aNegative ETrue, the value is a negative zero;
2079 EFalse, the value is a positive zero.
2082 _asm mov edx, [esp+4] // aNegative into edx
2083 _asm mov eax, 0xFFFF0000 // exponent=FFFF, sign=0 initially
2085 _asm jz short setinf1
2086 _asm inc eax // sign=1 if aNegative!=0
2088 _asm mov [ecx+8], eax // generate positive or negative infinity
2089 _asm mov eax, 0x80000000
2090 _asm mov [ecx+4], eax
2099 __NAKED__ EXPORT_C TBool TRealX::IsZero() const
2101 Determines whether the extended precision value is zero.
2103 @return True, if the extended precision value is zero, false, otherwise.
2106 _asm mov eax, [ecx+8] // check exponent
2107 _asm shr eax, 16 // move exponent into ax
2108 _asm jz short iszero1 // branch if zero
2109 _asm xor eax, eax // else return 0
2112 _asm inc eax // if zero, return 1
2119 __NAKED__ EXPORT_C TBool TRealX::IsNaN() const
2121 Determines whether the extended precision value is 'not a number'.
2123 @return True, if the extended precision value is 'not a number',
2127 _asm mov eax, [ecx+8] // check exponent
2128 _asm cmp eax, 0xFFFF0000
2129 _asm jc short isnan0 // branch if not FFFF
2130 _asm mov eax, [ecx+4]
2131 _asm cmp eax, 0x80000000 // check for infinity
2132 _asm jne short isnan1
2135 _asm jne short isnan1
2137 _asm xor eax, eax // return 0 if not NaN
2140 _asm mov eax, 1 // return 1 if NaN
2147 __NAKED__ EXPORT_C TBool TRealX::IsInfinite() const
2149 Determines whether the extended precision value has a finite value.
2151 @return True, if the extended precision value is finite,
2152 false, if the value is 'not a number' or is infinite,
2155 _asm mov eax, [ecx+8] // check exponent
2156 _asm cmp eax, 0xFFFF0000
2157 _asm jc short isinf0 // branch if not FFFF
2158 _asm mov eax, [ecx+4]
2159 _asm cmp eax, 0x80000000 // check for infinity
2160 _asm jne short isinf0
2163 _asm jne short isinf0
2164 _asm inc eax // return 1 if infinity
2167 _asm xor eax, eax // return 0 if not infinity
2174 __NAKED__ EXPORT_C TBool TRealX::IsFinite() const
2176 Determines whether the extended precision value has a finite value.
2178 @return True, if the extended precision value is finite,
2179 false, if the value is 'not a number' or is infinite,
2182 _asm mov eax, [ecx+8] // check exponent
2183 _asm cmp eax, 0xFFFF0000 // check for NaN or infinity
2184 _asm jnc short isfinite0 // branch if NaN or infinity
2185 _asm mov eax, 1 // return 1 if finite
2188 _asm xor eax, eax // return 0 if NaN or infinity
2195 __NAKED__ EXPORT_C const TRealX& TRealX::operator+=(const TRealX& /*aVal*/)
2197 Adds an extended precision value to this extended precision number.
2199 @param aVal The extended precision value to be added.
2201 @return A reference to this object.
2203 @panic MATHX KErrOverflow if the operation results in overflow.
2204 @panic MATHX KErrUnderflow if the operation results in underflow.
2207 // on entry ecx=this, [esp+4]=address of aVal
2208 _asm push ebx // save registers
2212 _asm mov esi, ecx // this into esi
2213 _asm mov ecx, [esp+20] // address of aVal into ecx
2214 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2215 _asm mov edx, [ecx+4]
2216 _asm mov ecx, [ecx+8]
2217 _asm call TRealXAdd // do addition, result in ecx,edx:ebx, error code in eax
2218 _asm mov [esi], ebx // store result in *this
2219 _asm mov [esi+4], edx
2220 _asm mov [esi+8], ecx
2222 _ASM_jn(z,TRealXPanicEax) // panic if error
2223 _asm mov eax, esi // return this in eax
2224 _asm pop edi // restore registers
2234 __NAKED__ EXPORT_C const TRealX& TRealX::operator-=(const TRealX& /*aVal*/)
2236 Subtracts an extended precision value from this extended precision number.
2238 @param aVal The extended precision value to be subtracted.
2240 @return A reference to this object.
2242 @panic MATHX KErrOverflow if the operation results in overflow.
2243 @panic MATHX KErrUnderflow if the operation results in underflow.
2246 // on entry ecx=this, [esp+4]=address of aVal
2247 _asm push ebx // save registers
2251 _asm mov esi, ecx // this into esi
2252 _asm mov ecx, [esp+20] // address of aVal into ecx
2253 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2254 _asm mov edx, [ecx+4]
2255 _asm mov ecx, [ecx+8]
2256 _asm call TRealXSubtract // do subtraction, result in ecx,edx:ebx, error code in eax
2257 _asm mov [esi], ebx // store result in *this
2258 _asm mov [esi+4], edx
2259 _asm mov [esi+8], ecx
2261 _ASM_jn(z,TRealXPanicEax) // panic if error
2262 _asm mov eax, esi // return this in eax
2263 _asm pop edi // restore registers
2273 __NAKED__ EXPORT_C const TRealX& TRealX::operator*=(const TRealX& /*aVal*/)
2275 Multiplies this extended precision number by an extended precision value.
2277 @param aVal The extended precision value to be subtracted.
2279 @return A reference to this object.
2281 @panic MATHX KErrOverflow if the operation results in overflow.
2282 @panic MATHX KErrUnderflow if the operation results in underflow.
2285 // on entry ecx=this, [esp+4]=address of aVal
2286 _asm push ebx // save registers
2290 _asm mov esi, ecx // this into esi
2291 _asm mov ecx, [esp+20] // address of aVal into ecx
2292 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2293 _asm mov edx, [ecx+4]
2294 _asm mov ecx, [ecx+8]
2295 _asm call TRealXMultiply // do multiplication, result in ecx,edx:ebx, error code in eax
2296 _asm mov [esi], ebx // store result in *this
2297 _asm mov [esi+4], edx
2298 _asm mov [esi+8], ecx
2300 _ASM_jn(z,TRealXPanicEax) // panic if error
2301 _asm mov eax, esi // return this in eax
2302 _asm pop edi // restore registers
2312 __NAKED__ EXPORT_C const TRealX& TRealX::operator/=(const TRealX& /*aVal*/)
2314 Divides this extended precision number by an extended precision value.
2316 @param aVal The extended precision value to be used as the divisor.
2318 @return A reference to this object.
2320 @panic MATHX KErrOverflow if the operation results in overflow.
2321 @panic MATHX KErrUnderflow if the operation results in underflow.
2322 @panic MATHX KErrDivideByZero if the divisor is zero.
2325 // on entry ecx=this, [esp+4]=address of aVal
2326 _asm push ebx // save registers
2330 _asm mov esi, ecx // this into esi
2331 _asm mov ecx, [esp+20] // address of aVal into ecx
2332 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2333 _asm mov edx, [ecx+4]
2334 _asm mov ecx, [ecx+8]
2335 _asm call TRealXDivide // do division, result in ecx,edx:ebx, error code in eax
2336 _asm mov [esi], ebx // store result in *this
2337 _asm mov [esi+4], edx
2338 _asm mov [esi+8], ecx
2340 _ASM_jn(z,TRealXPanicEax) // panic if error
2341 _asm mov eax, esi // return this in eax
2342 _asm pop edi // restore registers
2352 __NAKED__ EXPORT_C const TRealX& TRealX::operator%=(const TRealX& /*aVal*/)
2354 Modulo-divides this extended precision number by an extended precision value.
2356 @param aVal The extended precision value to be used as the divisor.
2358 @return A reference to this object.
2360 @panic MATHX KErrTotalLossOfPrecision panic if precision is lost.
2361 @panic MATHX KErrUnderflow if the operation results in underflow.
2364 // on entry ecx=this, [esp+4]=address of aVal
2365 _asm push ebx // save registers
2369 _asm mov esi, ecx // this into esi
2370 _asm mov ecx, [esp+20] // address of aVal into ecx
2371 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2372 _asm mov edx, [ecx+4]
2373 _asm mov ecx, [ecx+8]
2374 _asm call TRealXModulo // do modulo, result in ecx,edx:ebx, error code in eax
2375 _asm mov [esi], ebx // store result in *this
2376 _asm mov [esi+4], edx
2377 _asm mov [esi+8], ecx
2379 _ASM_jn(z,TRealXPanicEax) // panic if error
2380 _asm mov eax, esi // return this in eax
2381 _asm pop edi // restore registers
2391 __NAKED__ EXPORT_C TInt TRealX::AddEq(const TRealX& /*aVal*/)
2393 Adds an extended precision value to this extended precision number.
2395 @param aVal The extended precision value to be added.
2397 @return KErrNone, if the operation is successful;
2398 KErrOverflow,if the operation results in overflow;
2399 KErrUnderflow, if the operation results in underflow.
2402 // on entry ecx=this, [esp+4]=address of aVal
2403 _asm push ebx // save registers
2407 _asm mov esi, ecx // this into esi
2408 _asm mov ecx, [esp+20] // address of aVal into ecx
2409 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2410 _asm mov edx, [ecx+4]
2411 _asm mov ecx, [ecx+8]
2412 _asm call TRealXAdd // do addition, result in ecx,edx:ebx, error code in eax
2413 _asm mov [esi], ebx // store result
2414 _asm mov [esi+4], edx
2415 _asm mov [esi+8], ecx
2416 _asm pop edi // restore registers
2420 _asm ret 4 // return with error code in eax
2426 __NAKED__ EXPORT_C TInt TRealX::SubEq(const TRealX& /*aVal*/)
2428 Subtracts an extended precision value from this extended precision number.
2430 @param aVal The extended precision value to be subtracted.
2432 @return KErrNone, if the operation is successful;
2433 KErrOverflow, if the operation results in overflow;
2434 KErrUnderflow, if the operation results in underflow.
2437 // on entry ecx=this, [esp+4]=address of aVal
2438 _asm push ebx // save registers
2442 _asm mov esi, ecx // this into esi
2443 _asm mov ecx, [esp+20] // address of aVal into ecx
2444 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2445 _asm mov edx, [ecx+4]
2446 _asm mov ecx, [ecx+8]
2447 _asm call TRealXSubtract // do subtraction, result in ecx,edx:ebx, error code in eax
2448 _asm mov [esi], ebx // store result
2449 _asm mov [esi+4], edx
2450 _asm mov [esi+8], ecx
2451 _asm pop edi // restore registers
2455 _asm ret 4 // return with error code in eax
2461 __NAKED__ EXPORT_C TInt TRealX::MultEq(const TRealX& /*aVal*/)
2463 Multiplies this extended precision number by an extended precision value.
2465 @param aVal The extended precision value to be used as the multiplier.
2467 @return KErrNone, if the operation is successful;
2468 KErrOverflow, if the operation results in overflow;
2469 KErrUnderflow, if the operation results in underflow
2472 // on entry ecx=this, [esp+4]=address of aVal
2473 _asm push ebx // save registers
2477 _asm mov esi, ecx // this into esi
2478 _asm mov ecx, [esp+20] // address of aVal into ecx
2479 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2480 _asm mov edx, [ecx+4]
2481 _asm mov ecx, [ecx+8]
2482 _asm call TRealXMultiply // do multiplication, result in ecx,edx:ebx, error code in eax
2483 _asm mov [esi], ebx // store result
2484 _asm mov [esi+4], edx
2485 _asm mov [esi+8], ecx
2486 _asm pop edi // restore registers
2490 _asm ret 4 // return with error code in eax
2496 __NAKED__ EXPORT_C TInt TRealX::DivEq(const TRealX& /*aVal*/)
2498 Divides this extended precision number by an extended precision value.
2500 @param aVal The extended precision value to be used as the divisor.
2502 @return KErrNone, if the operation is successful;
2503 KErrOverflow, if the operation results in overflow;
2504 KErrUnderflow, if the operation results in underflow;
2505 KErrDivideByZero, if the divisor is zero.
2508 // on entry ecx=this, [esp+4]=address of aVal
2509 _asm push ebx // save registers
2513 _asm mov esi, ecx // this into esi
2514 _asm mov ecx, [esp+20] // address of aVal into ecx
2515 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2516 _asm mov edx, [ecx+4]
2517 _asm mov ecx, [ecx+8]
2518 _asm call TRealXDivide // do division, result in ecx,edx:ebx, error code in eax
2519 _asm mov [esi], ebx // store result
2520 _asm mov [esi+4], edx
2521 _asm mov [esi+8], ecx
2522 _asm pop edi // restore registers
2526 _asm ret 4 // return with error code in eax
2532 __NAKED__ EXPORT_C TInt TRealX::ModEq(const TRealX& /*aVal*/)
2534 Modulo-divides this extended precision number by an extended precision value.
2536 @param aVal The extended precision value to be used as the divisor.
2538 @return KErrNone, if the operation is successful;
2539 KErrTotalLossOfPrecision, if precision is lost;
2540 KErrUnderflow, if the operation results in underflow.
2543 // on entry ecx=this, [esp+4]=address of aVal
2544 _asm push ebx // save registers
2548 _asm mov esi, ecx // this into esi
2549 _asm mov ecx, [esp+20] // address of aVal into ecx
2550 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2551 _asm mov edx, [ecx+4]
2552 _asm mov ecx, [ecx+8]
2553 _asm call TRealXModulo // do modulo, result in ecx,edx:ebx, error code in eax
2554 _asm mov [esi], ebx // store result
2555 _asm mov [esi+4], edx
2556 _asm mov [esi+8], ecx
2557 _asm pop edi // restore registers
2561 _asm ret 4 // return with error code in eax
2567 __NAKED__ EXPORT_C TRealX TRealX::operator+() const
2569 Returns this extended precision number unchanged.
2571 Note that this may also be referred to as a unary plus operator.
2573 @return The extended precision number.
2576 _asm mov eax, [esp+4] // eax=address to write return value
2579 _asm mov edx, [ecx+4]
2580 _asm mov [eax+4], edx
2581 _asm mov edx, [ecx+8]
2582 _asm mov [eax+8], edx
2583 _asm ret 4 // return address of return value in eax
2589 __NAKED__ EXPORT_C TRealX TRealX::operator-() const
2591 Negates this extended precision number.
2593 This may also be referred to as a unary minus operator.
2595 @return The negative of the extended precision number.
2598 _asm mov eax, [esp+4] // eax=address to write return value
2601 _asm mov edx, [ecx+4]
2602 _asm mov [eax+4], edx
2603 _asm mov edx, [ecx+8]
2604 _asm xor dl, 1 // change sign bit
2605 _asm mov [eax+8], edx
2606 _asm ret 4 // return address of return value in eax
2612 __NAKED__ EXPORT_C TRealX& TRealX::operator++()
2614 Increments this extended precision number by one,
2615 and then returns a reference to it.
2617 This is also referred to as a prefix operator.
2619 @return A reference to this object.
2621 @panic MATHX KErrOverflow if the operation results in overflow.
2622 @panic MATHX KErrUnderflow if the operation results in underflow.
2626 // on entry ecx=this, return this in eax
2627 _asm push ebx // save registers
2631 _asm mov esi, ecx // this into esi
2632 _asm mov ecx, 0x7FFF0000 // set ecx,edx:ebx to 1.0
2633 _asm mov edx, 0x80000000
2635 _asm call TRealXAdd // add 1 to *this
2636 _asm mov [esi], ebx // store result
2637 _asm mov [esi+4], edx
2638 _asm mov [esi+8], ecx
2639 _asm test eax, eax // check error code
2640 _ASM_jn(z,TRealXPanicEax) // panic if error
2641 _asm mov eax, esi // else return this in eax
2652 __NAKED__ EXPORT_C TRealX TRealX::operator++(TInt)
2654 Returns this extended precision number before incrementing it by one.
2656 This is also referred to as a postfix operator.
2658 @return A reference to this object.
2660 @panic MATHX KErrOverflow if the operation results in overflow.
2661 @panic MATHX KErrUnderflow if the operation results in underflow.
2665 // on entry ecx=this, [esp+4]=address of return value, [esp+8]=dummy int
2666 _asm push ebx // save registers
2670 _asm mov esi, ecx // this into esi
2671 _asm mov edi, [esp+20] // address of return value into edi
2672 _asm mov eax, [ecx] // copy initial value of *this into [edi]
2674 _asm mov eax, [ecx+4]
2675 _asm mov [edi+4], eax
2676 _asm mov eax, [ecx+8]
2677 _asm mov [edi+8], eax
2678 _asm mov ecx, 0x7FFF0000 // set ecx,edx:ebx to 1.0
2679 _asm mov edx, 0x80000000
2681 _asm call TRealXAdd // add 1 to *this
2682 _asm mov [esi], ebx // store result in *this
2683 _asm mov [esi+4], edx
2684 _asm mov [esi+8], ecx
2685 _asm test eax, eax // check error code
2686 _ASM_jn(z,TRealXPanicEax) // panic if error
2687 _asm mov eax, [esp+20] // address of return value into eax
2698 __NAKED__ EXPORT_C TRealX& TRealX::operator--()
2700 Decrements this extended precision number by one,
2701 and then returns a reference to it.
2703 This is also referred to as a prefix operator.
2705 @return A reference to this object.
2707 @panic MATHX KErrOverflow if the operation results in overflow.
2708 @panic MATHX KErrUnderflow if the operation results in underflow.
2712 // on entry ecx=this, return this in eax
2713 _asm push ebx // save registers
2717 _asm mov esi, ecx // this into esi
2718 _asm mov ecx, 0x7FFF0001 // set ecx,edx:ebx to -1.0
2719 _asm mov edx, 0x80000000
2721 _asm call TRealXAdd // add -1 to *this
2722 _asm mov [esi], ebx // store result
2723 _asm mov [esi+4], edx
2724 _asm mov [esi+8], ecx
2725 _asm test eax, eax // check error code
2726 _ASM_jn(z,TRealXPanicEax) // panic if error
2727 _asm mov eax, esi // else return this in eax
2738 __NAKED__ EXPORT_C TRealX TRealX::operator--(TInt)
2740 Returns this extended precision number before decrementing it by one.
2742 This is also referred to as a postfix operator.
2744 @return A reference to this object.
2746 @panic MATHX KErrOverflow if the operation results in overflow.
2747 @panic MATHX KErrUnderflow if the operation results in underflow.
2751 // on entry ecx=this, [esp+4]=address of return value, [esp+8]=dummy int
2752 _asm push ebx // save registers
2756 _asm mov esi, ecx // this into esi
2757 _asm mov edi, [esp+20] // address of return value into edi
2758 _asm mov eax, [ecx] // copy initial value of *this into [edi]
2760 _asm mov eax, [ecx+4]
2761 _asm mov [edi+4], eax
2762 _asm mov eax, [ecx+8]
2763 _asm mov [edi+8], eax
2764 _asm mov ecx, 0x7FFF0001 // set ecx,edx:ebx to -1.0
2765 _asm mov edx, 0x80000000
2767 _asm call TRealXAdd // add -1 to *this
2768 _asm mov [esi], ebx // store result in *this
2769 _asm mov [esi+4], edx
2770 _asm mov [esi+8], ecx
2771 _asm test eax, eax // check error code
2772 _ASM_jn(z,TRealXPanicEax) // panic if error
2773 _asm mov eax, [esp+20] // address of return value into eax
2784 __NAKED__ EXPORT_C TRealX TRealX::operator+(const TRealX& /*aVal*/) const
2786 Adds an extended precision value to this extended precision number.
2788 @param aVal The extended precision value to be added.
2790 @return An extended precision object containing the result.
2792 @panic MATHX KErrOverflow if the operation results in overflow.
2793 @panic MATHX KErrUnderflow if the operation results in underflow.
2796 // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
2797 _asm push ebx // save registers
2801 _asm mov esi, ecx // this into esi
2802 _asm mov ecx, [esp+24] // address of aVal into ecx
2803 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2804 _asm mov edx, [ecx+4]
2805 _asm mov ecx, [ecx+8]
2806 _asm call TRealXAdd // do addition, result in ecx,edx:ebx, error code in eax
2807 _asm mov esi, [esp+20] // esi=address of return value
2808 _asm mov [esi], ebx // store result
2809 _asm mov [esi+4], edx
2810 _asm mov [esi+8], ecx
2812 _ASM_jn(z,TRealXPanicEax) // panic if error
2813 _asm mov eax, esi // return address of return value in eax
2814 _asm pop edi // restore registers
2824 __NAKED__ EXPORT_C TRealX TRealX::operator-(const TRealX& /*aVal*/) const
2826 Subtracts an extended precision value from this extended precision number.
2828 @param aVal The extended precision value to be subtracted.
2830 @return An extended precision object containing the result.
2832 @panic MATHX KErrOverflow if the operation results in overflow.
2833 @panic MATHX KErrUnderflow if the operation results in underflow.
2836 // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
2837 _asm push ebx // save registers
2841 _asm mov esi, ecx // this into esi
2842 _asm mov ecx, [esp+24] // address of aVal into ecx
2843 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2844 _asm mov edx, [ecx+4]
2845 _asm mov ecx, [ecx+8]
2846 _asm call TRealXSubtract // do subtraction, result in ecx,edx:ebx, error code in eax
2847 _asm mov esi, [esp+20] // esi=address of return value
2848 _asm mov [esi], ebx // store result
2849 _asm mov [esi+4], edx
2850 _asm mov [esi+8], ecx
2852 _ASM_jn(z,TRealXPanicEax) // panic if error
2853 _asm mov eax, esi // return address of return value in eax
2854 _asm pop edi // restore registers
2864 __NAKED__ EXPORT_C TRealX TRealX::operator*(const TRealX& /*aVal*/) const
2866 Multiplies this extended precision number by an extended precision value.
2868 @param aVal The extended precision value to be used as the multiplier.
2870 @return An extended precision object containing the result.
2872 @panic MATHX KErrOverflow if the operation results in overflow.
2873 @panic MATHX KErrUnderflow if the operation results in underflow.
2876 // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
2877 _asm push ebx // save registers
2881 _asm mov esi, ecx // this into esi
2882 _asm mov ecx, [esp+24] // address of aVal into ecx
2883 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2884 _asm mov edx, [ecx+4]
2885 _asm mov ecx, [ecx+8]
2886 _asm call TRealXMultiply // do multiplication, result in ecx,edx:ebx, error code in eax
2887 _asm mov esi, [esp+20] // esi=address of return value
2888 _asm mov [esi], ebx // store result
2889 _asm mov [esi+4], edx
2890 _asm mov [esi+8], ecx
2892 _ASM_jn(z,TRealXPanicEax) // panic if error
2893 _asm mov eax, esi // return address of return value in eax
2894 _asm pop edi // restore registers
2904 __NAKED__ EXPORT_C TRealX TRealX::operator/(const TRealX& /*aVal*/) const
2906 Divides this extended precision number by an extended precision value.
2908 @param aVal The extended precision value to be used as the divisor.
2910 @return An extended precision object containing the result.
2912 @panic MATHX KErrOverflow if the operation results in overflow.
2913 @panic MATHX KErrUnderflow if the operation results in underflow.
2914 @panic MATHX KErrDivideByZero if the divisor is zero.
2917 // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
2918 _asm push ebx // save registers
2922 _asm mov esi, ecx // this into esi
2923 _asm mov ecx, [esp+24] // address of aVal into ecx
2924 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2925 _asm mov edx, [ecx+4]
2926 _asm mov ecx, [ecx+8]
2927 _asm call TRealXDivide // do division, result in ecx,edx:ebx, error code in eax
2928 _asm mov esi, [esp+20] // esi=address of return value
2929 _asm mov [esi], ebx // store result
2930 _asm mov [esi+4], edx
2931 _asm mov [esi+8], ecx
2933 _ASM_jn(z,TRealXPanicEax) // panic if error
2934 _asm mov eax, esi // return address of return value in eax
2935 _asm pop edi // restore registers
2945 __NAKED__ EXPORT_C TRealX TRealX::operator%(const TRealX& /*aVal*/) const
2947 Modulo-divides this extended precision number by an extended precision value.
2949 @param aVal The extended precision value to be used as the divisor.
2951 @return An extended precision object containing the result.
2953 @panic MATHX KErrTotalLossOfPrecision if precision is lost.
2954 @panic MATHX KErrUnderflow if the operation results in underflow.
2957 // on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
2958 _asm push ebx // save registers
2962 _asm mov esi, ecx // this into esi
2963 _asm mov ecx, [esp+24] // address of aVal into ecx
2964 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
2965 _asm mov edx, [ecx+4]
2966 _asm mov ecx, [ecx+8]
2967 _asm call TRealXModulo // do modulo, result in ecx,edx:ebx, error code in eax
2968 _asm mov esi, [esp+20] // esi=address of return value
2969 _asm mov [esi], ebx // store result
2970 _asm mov [esi+4], edx
2971 _asm mov [esi+8], ecx
2973 _ASM_jn(z,TRealXPanicEax) // panic if error
2974 _asm mov eax, esi // return address of return value in eax
2975 _asm pop edi // restore registers
2985 __NAKED__ EXPORT_C TInt TRealX::Add(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
2987 Adds an extended precision value to this extended precision number.
2989 @param aResult On return, a reference to an extended precision object
2990 containing the result of the operation.
2991 @param aVal The extended precision value to be added.
2993 @return KErrNone, if the operation is successful;
2994 KErrOverflow, if the operation results in overflow;
2995 KErrUnderflow, if the operation results in underflow.
2998 // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
2999 _asm push ebx // save registers
3003 _asm mov esi, ecx // this into esi
3004 _asm mov ecx, [esp+24] // address of aVal into ecx
3005 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
3006 _asm mov edx, [ecx+4]
3007 _asm mov ecx, [ecx+8]
3008 _asm call TRealXAdd // do addition, result in ecx,edx:ebx, error code in eax
3009 _asm mov esi, [esp+20] // esi=address of aResult
3010 _asm mov [esi], ebx // store result
3011 _asm mov [esi+4], edx
3012 _asm mov [esi+8], ecx
3013 _asm pop edi // restore registers
3017 _asm ret 8 // return with error code in eax
3023 __NAKED__ EXPORT_C TInt TRealX::Sub(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
3025 Subtracts an extended precision value from this extended precision number.
3027 @param aResult On return, a reference to an extended precision object
3028 containing the result of the operation.
3029 @param aVal The extended precision value to be subtracted.
3031 @return KErrNone, if the operation is successful;
3032 KErrOverflow, if the operation results in overflow;
3033 KErrUnderflow, if the operation results in underflow.
3036 // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
3037 _asm push ebx // save registers
3041 _asm mov esi, ecx // this into esi
3042 _asm mov ecx, [esp+24] // address of aVal into ecx
3043 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
3044 _asm mov edx, [ecx+4]
3045 _asm mov ecx, [ecx+8]
3046 _asm call TRealXSubtract // do subtraction, result in ecx,edx:ebx, error code in eax
3047 _asm mov esi, [esp+20] // esi=address of aResult
3048 _asm mov [esi], ebx // store result
3049 _asm mov [esi+4], edx
3050 _asm mov [esi+8], ecx
3051 _asm pop edi // restore registers
3055 _asm ret 8 // return with error code in eax
3061 __NAKED__ EXPORT_C TInt TRealX::Mult(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
3063 Multiplies this extended precision number by an extended precision value.
3065 @param aResult On return, a reference to an extended precision object
3066 containing the result of the operation.
3067 @param aVal The extended precision value to be used as the multiplier.
3069 @return KErrNone, if the operation is successful;
3070 KErrOverflow, if the operation results in overflow;
3071 KErrUnderflow, if the operation results in underflow.
3074 // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
3075 _asm push ebx // save registers
3079 _asm mov esi, ecx // this into esi
3080 _asm mov ecx, [esp+24] // address of aVal into ecx
3081 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
3082 _asm mov edx, [ecx+4]
3083 _asm mov ecx, [ecx+8]
3084 _asm call TRealXMultiply // do multiplication, result in ecx,edx:ebx, error code in eax
3085 _asm mov esi, [esp+20] // esi=address of aResult
3086 _asm mov [esi], ebx // store result
3087 _asm mov [esi+4], edx
3088 _asm mov [esi+8], ecx
3089 _asm pop edi // restore registers
3093 _asm ret 8 // return with error code in eax
3099 __NAKED__ EXPORT_C TInt TRealX::Div(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
3101 Divides this extended precision number by an extended precision value.
3103 @param aResult On return, a reference to an extended precision object
3104 containing the result of the operation.
3105 @param aVal The extended precision value to be used as the divisor.
3107 @return KErrNone, if the operation is successful;
3108 KErrOverflow, if the operation results in overflow;
3109 KErrUnderflow, if the operation results in underflow;
3110 KErrDivideByZero, if the divisor is zero.
3113 // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
3114 _asm push ebx // save registers
3118 _asm mov esi, ecx // this into esi
3119 _asm mov ecx, [esp+24] // address of aVal into ecx
3120 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
3121 _asm mov edx, [ecx+4]
3122 _asm mov ecx, [ecx+8]
3123 _asm call TRealXDivide // do division, result in ecx,edx:ebx, error code in eax
3124 _asm mov esi, [esp+20] // esi=address of aResult
3125 _asm mov [esi], ebx // store result
3126 _asm mov [esi+4], edx
3127 _asm mov [esi+8], ecx
3128 _asm pop edi // restore registers
3132 _asm ret 8 // return with error code in eax
3138 __NAKED__ EXPORT_C TInt TRealX::Mod(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
3140 Modulo-divides this extended precision number by an extended precision value.
3142 @param aResult On return, a reference to an extended precision object
3143 containing the result of the operation.
3145 @param aVal The extended precision value to be used as the divisor.
3147 @return KErrNone, if the operation is successful;
3148 KErrTotalLossOfPrecision, if precision is lost;
3149 KErrUnderflow, if the operation results in underflow.
3152 // on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
3153 _asm push ebx // save registers
3157 _asm mov esi, ecx // this into esi
3158 _asm mov ecx, [esp+24] // address of aVal into ecx
3159 _asm mov ebx, [ecx] // aVal into ecx,edx:ebx
3160 _asm mov edx, [ecx+4]
3161 _asm mov ecx, [ecx+8]
3162 _asm call TRealXModulo // do modulo, result in ecx,edx:ebx, error code in eax
3163 _asm mov esi, [esp+20] // esi=address of aResult
3164 _asm mov [esi], ebx // store result
3165 _asm mov [esi+4], edx
3166 _asm mov [esi+8], ecx
3167 _asm pop edi // restore registers
3171 _asm ret 8 // return with error code in eax
3174 // Compare TRealX in ecx,edx:ebx (op1) to TRealX at [esi] (op2)
3175 // Return 1 if op1<op2
3176 // Return 2 if op1=op2
3177 // Return 4 if op1>op2
3178 // Return 8 if unordered
3179 // Return value in eax
3180 __NAKED__ LOCAL_C void TRealXCompare(void)
3182 _asm cmp ecx, 0xFFFF0000 // check if op1=NaN or infinity
3183 _asm jc short fpcmp1 // branch if not
3184 _asm cmp edx, 0x80000000 // check for infinity
3185 _asm jnz short fpcmpunord // branch if NaN
3187 _asm jz short fpcmp1 // if infinity, process normally
3188 fpcmpunord: // come here if unordered
3189 _asm mov eax, 8 // return 8
3191 fpcmp1: // op1 is not a NaN
3192 _asm mov eax, [esi+8] // get op2 into eax,edi:ebp
3193 _asm mov edi, [esi+4]
3195 _asm cmp eax, 0xFFFF0000 // check for NaN or infinity
3196 _asm jc short fpcmp2 // branch if neither
3197 _asm cmp edi, 0x80000000 // check for infinity
3198 _asm jnz short fpcmpunord // branch if NaN
3200 _asm jnz short fpcmpunord
3201 fpcmp2: // neither operand is a NaN
3202 _asm cmp ecx, 0x10000 // check if op1=0
3203 _asm jc short fpcmpop1z // branch if it is
3204 _asm cmp eax, 0x10000 // check if op2=0
3205 _asm jc short fpcmp4 // branch if it is
3206 _asm xor al, cl // check if signs the same
3208 _asm jnz short fpcmp4 // branch if different
3210 _asm shr ecx, 16 // op1 exponent into cx
3211 _asm shr eax, 16 // op2 exponent into ax
3212 _asm cmp ecx, eax // compare exponents
3214 _asm ja short fpcmp4 // if op1 exp > op2 exp op1>op2 if +ve
3215 _asm jb short fpcmp5 // if op1 exp < op2 exp op1<op2 if +ve
3216 _asm cmp edx, edi // else compare mantissa high words
3217 _asm ja short fpcmp4
3218 _asm jb short fpcmp5
3219 _asm cmp ebx, ebp // if equal compare mantissa low words
3220 _asm ja short fpcmp4
3221 _asm jb short fpcmp5
3223 _asm mov eax, 2 // numbers exactly equal
3225 fpcmp4: // come here if ABS(op1)>ABS(op2) or if signs different
3226 // or if op2 zero, op1 nonzero
3227 _asm mov eax, 4 // return 4 if +ve
3228 _asm test cl, 1 // check sign
3229 _asm jz short fpcmp4a // skip if +
3230 _asm mov al, 1 // return 1 if -ve
3233 fpcmp5: // come here if ABS(op1)<ABS(op2)
3234 _asm mov eax, 1 // return 1 if +ve
3235 _asm test cl, 1 // check sign
3236 _asm jz short fpcmp5a // skip if +
3237 _asm mov al, 4 // return 4 if -ve
3240 fpcmpop1z: // come here if op1=0
3241 _asm cmp eax, 0x10000 // check if op2 also zero
3242 _asm jc short fpcmp0 // if so, they are equal
3243 _asm test al, 1 // test sign of op 2
3244 _asm mov eax, 4 // if -, return 4
3245 _asm jnz short fpcmpop1z2n // skip if -
3246 _asm mov al, 1 // else return 1
3254 __NAKED__ EXPORT_C TRealX::TRealXOrder TRealX::Compare(const TRealX& /*aVal*/) const
3258 // On entry ecx=this, [esp+4]=address of aVal
3259 _asm push ebx // save registers
3263 _asm mov esi, [esp+20] // address of aVal into esi
3264 _asm mov ebx, [ecx] // *this into ecx,edx:ebx
3265 _asm mov edx, [ecx+4]
3266 _asm mov ecx, [ecx+8]
3267 _asm call TRealXCompare // result in eax
3278 #pragma warning (default : 4100) // unreferenced formal parameter
3279 #pragma warning (default : 4414) // short jump converted to near
3280 #pragma warning (default : 4700) // local variable 'this' used without having been initialised