kernel/eka/euser/epoc/win32/uc_realx.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\euser\epoc\win32\uc_realx.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "u32std.h"
       
    19 #include <e32math.h>
       
    20 
       
    21 #pragma warning (disable : 4100)	// unreferenced formal parameter
       
    22 #pragma warning (disable : 4700)	// local variable 'this' used without
       
    23 									// having been initialised
       
    24 #pragma warning ( disable : 4414 )  // short jump to function converted to near
       
    25 
       
    26 
       
    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
       
    33 #else
       
    34 #define _ASM_j(cond,dest) _asm j##cond dest
       
    35 #define _ASM_jn(cond,dest) _asm jn##cond dest
       
    36 #endif
       
    37 
       
    38 //
       
    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
       
    43 // ecx bit 0 = sign
       
    44 // ecx bit 8 = rounded-down flag
       
    45 // ecx bit 9 = rounded-up flag
       
    46 //
       
    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]
       
    52 //
       
    53 
       
    54 LOCAL_C void TRealXPanic(TInt aErr)
       
    55 	{
       
    56 	User::Panic(_L("MATHX"),aErr);
       
    57 	}
       
    58 
       
    59 __NAKED__ LOCAL_C void TRealXPanicEax(void)
       
    60 	{
       
    61 	_asm push eax
       
    62 	_asm call TRealXPanic
       
    63 	}
       
    64 
       
    65 LOCAL_C __NAKED__ void TRealXRealIndefinite(void)
       
    66 	{
       
    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
       
    70 	_asm xor ebx, ebx
       
    71 	_asm mov eax, -6			// return KErrArgument
       
    72 	_asm ret
       
    73 	}
       
    74 
       
    75 LOCAL_C __NAKED__ void TRealXBinOpNaN(void)
       
    76 	{
       
    77 	// generic routine to process NaN's in binary operations
       
    78 	// destination operand in ecx,edx:eax
       
    79 	// source operand at [esi]
       
    80 
       
    81 	_asm mov eax, [esi+8]		// source operand into eax,edi:ebp
       
    82 	_asm mov edi, [esi+4]
       
    83 	_asm mov ebp, [esi]
       
    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
       
    88 	_asm test ebx, ebx
       
    89 	_asm jne short TRealXBinOpNaN2
       
    90 	TRealXBinOpNaN1:			// swap the operands
       
    91 	_asm xchg ecx, eax
       
    92 	_asm xchg edx, edi
       
    93 	_asm xchg ebx, ebp
       
    94 	TRealXBinOpNaN2:
       
    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
       
    99 	_asm test ebp, ebp
       
   100 	_asm je short TRealXBinOpNaN4
       
   101 	TRealXBinOpNaN3:			// if both operands are NaN's, compare significands
       
   102 	_asm cmp edx, edi
       
   103 	_asm ja short TRealXBinOpNaN4
       
   104 	_asm jb short TRealXBinOpNaN5
       
   105 	_asm cmp ebx, ebp
       
   106 	_asm jae short TRealXBinOpNaN4
       
   107 	TRealXBinOpNaN5:			// come here if dest is smaller - copy source to dest
       
   108 	_asm mov ecx, eax
       
   109 	_asm mov edx, edi
       
   110 	_asm mov ebx, ebp
       
   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
       
   114 	_asm ret
       
   115 	}
       
   116 
       
   117 // Add TRealX at [esi] + ecx,edx:ebx
       
   118 // Result in ecx,edx:ebx
       
   119 // Error code in eax
       
   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()
       
   123 	{
       
   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
       
   136 	_asm mov ch, cl
       
   137 	_asm xor ch, al				// xor of signs into ch bit 0
       
   138 	_asm add ch, ch
       
   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
       
   154 	addfp1:
       
   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
       
   162 	addfp3a:
       
   163 	_asm xor edi, edi			// clear edx:ebx
       
   164 	_asm xor ebp, ebp
       
   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
       
   169 	addfp3:
       
   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		//
       
   179 	_asm shr 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		//
       
   189 	_asm shr edi, cl			//
       
   190 
       
   191 	addfp5:
       
   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
       
   198 	_asm adc edx,edi			//
       
   199 	_asm jnc short roundfp		// branch if no carry
       
   200 	_asm rcr edx,1				// shift carry right into mantissa
       
   201 	_asm rcr ebx,1				//
       
   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
       
   205 	addfp5a:
       
   206 	_asm add ecx, 0x10000		// and increment exponent
       
   207 
       
   208 	// perform rounding based on rounding word in eax and rounding flag in ch
       
   209 	roundfp:
       
   210 	_asm cmp eax, 0x80000000
       
   211 	_asm jc roundfp0			// if rounding word<80000000, round down
       
   212 	_asm ja roundfp1			// if >80000000, round up
       
   213 	_asm test ch, 1
       
   214 	_asm jnz short roundfp1		// if rounded-down flag set, round up
       
   215 	_asm test ch, 2
       
   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
       
   221 	_asm adc edx,0				//
       
   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
       
   225 	roundfp1a:
       
   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
       
   230 	_asm ret
       
   231 
       
   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
       
   238 	roundfp0a:
       
   239 	_asm xor eax, eax			// return KErrNone
       
   240 	_asm ret					// exit
       
   241 
       
   242 	addfpovfw:					// Come here if overflow occurs
       
   243 	_asm xor ch, ch				// clear rounding flags, exponent=FFFF
       
   244 	_asm xor ebx, ebx
       
   245 	_asm mov edx, 0x80000000	// mantissa=80000000 00000000 for infinity
       
   246 	_asm mov eax, -9			// return KErrOverflow
       
   247 	_asm ret
       
   248 
       
   249 	// exponents differ by more than 64 - output larger number
       
   250 	addfp2:
       
   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
       
   255 	_asm jz addfp2a
       
   256 	_asm xor ch, 3				// if not, set rounded-up flag
       
   257 	addfp2a:
       
   258 	_asm xor eax, eax			// return KErrNone
       
   259 	_asm ret
       
   260 
       
   261 	// signs differ, so must subtract mantissas
       
   262 	subfp1:
       
   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
       
   266 	_asm sbb edx, edi			//
       
   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
       
   272 	_asm not edx				//
       
   273 	_asm add eax,1				// two's complement negation
       
   274 	_asm adc ebx,0				//
       
   275 	_asm adc edx,0				//
       
   276 	subfp2:
       
   277 	_asm jnz short subfp3		// branch if edx non-zero at this point
       
   278 	_asm mov edx, ebx			// else shift ebx into edx
       
   279 	_asm or edx, 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
       
   286 	subfp4:
       
   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
       
   291 	_asm xor eax, eax			//
       
   292 	_asm sub ecx, 0x400000		// and decrease exponent by 64 due to shift
       
   293 	_asm jc short subfpundflw	// if borrow, underflow
       
   294 	subfp3:
       
   295 	_asm mov edi, ecx			// preserve sign and exponent
       
   296 	_asm bsr ecx, edx			// position of most significant 1 into ecx
       
   297 	_asm neg 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		//
       
   301 	_asm shl 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
       
   309 
       
   310 	// come here if underflow
       
   311 	subfpundflw:
       
   312 	_asm and ecx, 1				// set exponent to zero, leave sign
       
   313 	_asm xor edx, edx
       
   314 	_asm xor ebx, ebx
       
   315 	_asm mov eax, -10			// return KErrUnderflow
       
   316 	_asm ret
       
   317 
       
   318 	// come here to return zero result
       
   319 	subfp0:
       
   320 	_asm xor ecx, ecx			// set exponent to zero, positive sign
       
   321 	_asm xor edx, edx
       
   322 	_asm xor ebx, ebx
       
   323 	addfp0snzd:
       
   324 	_asm xor eax, eax			// return KErrNone
       
   325 	_asm ret
       
   326 
       
   327 	// come here if source=0 - eax=source exponent/sign
       
   328 	addfp0s:
       
   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
       
   332 	_asm and ecx, 1
       
   333 	_asm xor eax, eax			// return KErrNone
       
   334 	_asm ret
       
   335 
       
   336 	// come here if dest=0, source nonzero
       
   337 	addfp0d:
       
   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
       
   342 	_asm ret
       
   343 
       
   344 	// come here if dest=NaN or infinity
       
   345 	addfpsd:
       
   346 	_asm cmp edx, 0x80000000	// check for infinity
       
   347 	_ASM_jn(e,TRealXBinOpNaN)	// branch if NaN
       
   348 	_asm test ebx, ebx
       
   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
       
   353 	addfpsd2:
       
   354 	_asm mov eax, -9			// else return dest unaltered (infinity) and KErrOverflow
       
   355 	_asm ret
       
   356 	addfpsd1:
       
   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
       
   361 	_asm test ebp, ebp
       
   362 	_ASM_jn(e,TRealXBinOpNaN)
       
   363 	_asm xor al, cl				// both operands are infinity - check signs
       
   364 	_asm test al, 1
       
   365 	_asm jz short addfpsd2		// if both the same, return KErrOverflow
       
   366 	_asm jmp TRealXRealIndefinite	// else return 'real indefinite'
       
   367 
       
   368 	// come here if source=NaN or infinity, dest finite
       
   369 	addfpss:
       
   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
       
   374 	_asm test ebp, ebp
       
   375 	_ASM_jn(e,TRealXBinOpNaN)
       
   376 	_asm mov ecx, eax			// if source=infinity, return source unaltered
       
   377 	_asm mov edx, edi
       
   378 	_asm mov ebx, ebp
       
   379 	_asm mov eax, -9			// return KErrOverflow
       
   380 	_asm ret
       
   381 	}
       
   382 
       
   383 // Subtract TRealX at [esi] - ecx,edx:ebx
       
   384 // Result in ecx,edx:ebx
       
   385 // Error code in eax
       
   386 __NAKED__ LOCAL_C void TRealXSubtract()
       
   387 	{
       
   388 	_asm xor cl, 1              // negate subtrahend
       
   389 	_asm jmp TRealXAdd
       
   390 	}
       
   391 
       
   392 // Multiply TRealX at [esi] * ecx,edx:ebx
       
   393 // Result in ecx,edx:ebx
       
   394 // Error code in eax
       
   395 __NAKED__ LOCAL_C void TRealXMultiply()
       
   396 	{
       
   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
       
   421 	_asm adc edx, 0				//
       
   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
       
   426 	_asm adc edx, 0				//
       
   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
       
   431 	_asm adc ecx, edx			//
       
   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
       
   434 	_asm mov edi, 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)
       
   439 	_asm adc ebp, ebp
       
   440 	_asm adc ebx, ebx
       
   441 	_asm adc edx, edx
       
   442 	_asm dec ecx				// and decrement exponent
       
   443 	mulfp1:
       
   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
       
   447 	_asm test edi, edi
       
   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)
       
   451 	mulfp2:
       
   452 	_asm add ebx, 1				// round up - increment mantissa
       
   453 	_asm adc edx, 0
       
   454 	_asm jnc short mulfp2a
       
   455 	_asm rcr edx, 1
       
   456 	_asm inc ecx
       
   457 	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
       
   476 	_asm ret
       
   477 
       
   478 	// come here if overflow
       
   479 	mulfp6:
       
   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
       
   484 	_asm xor ebx, ebx
       
   485 	_asm mov eax, -9			// return KErrOverflow
       
   486 	_asm ret
       
   487 
       
   488 	// come here if underflow
       
   489 	mulfp7:
       
   490 	_asm pop eax				// recover result sign
       
   491 	_asm xor ecx, ecx			// exponent=0
       
   492 	_asm mov cl, al				// sign into cl
       
   493 	_asm xor edx, edx
       
   494 	_asm xor ebx, ebx
       
   495 	_asm mov eax, -10			// return KErrUnderflow
       
   496 	_asm ret
       
   497 
       
   498 	// come here if either operand zero
       
   499 	mulfp0:
       
   500 	_asm and ecx, 1				// set exponent=0, keep sign
       
   501 	_asm xor edx, edx
       
   502 	_asm xor ebx, ebx
       
   503 	_asm xor eax, eax			// return KErrNone
       
   504 	_asm ret
       
   505 
       
   506 	// come here if destination operand NaN or infinity
       
   507 	mulfpsd:
       
   508 	_asm cmp edx, 0x80000000	// check for infinity
       
   509 	_ASM_jn(e,TRealXBinOpNaN)	// branch if NaN
       
   510 	_asm test ebx, ebx
       
   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
       
   517 	_asm ret
       
   518 	mulfpsd1:
       
   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
       
   523 	_asm test ebp, ebp
       
   524 	_ASM_jn(e,TRealXBinOpNaN)
       
   525 	_asm mov eax, -9			// both operands infinity - return infinity with xor sign
       
   526 	_asm ret					// and KErrOverflow
       
   527 
       
   528 	// come here if source operand NaN or infinity, destination finite
       
   529 	mulfpss:
       
   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
       
   534 	_asm test ebp, ebp
       
   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
       
   540 	_asm mov ebx, ebp
       
   541 	_asm mov eax, -9			// return KErrOverflow
       
   542 	_asm ret
       
   543 	}
       
   544 
       
   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)
       
   551 	{
       
   552 	_asm push edx				// save dividend
       
   553 	_asm push eax				//
       
   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
       
   557 	_asm dec eax				//
       
   558 	_asm jmp short longdiv2		//
       
   559 	longdiv1:
       
   560 	_asm div ecx				// divide EDX:EAX by ECX to give approximate quotient in EAX
       
   561 	longdiv2:
       
   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
       
   565 	_asm mov ebp, edx			//
       
   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
       
   569 	_asm adc edx, 0				//
       
   570 	_asm neg esi				// remainder = dividend - approx quotient * divisor
       
   571 	_asm mov ebp, [esp]			// fetch dividend bits 32-63
       
   572 	_asm sbb ebp, eax			//
       
   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
       
   576 	longdiv3:
       
   577 	_asm dec edi				// else quotient is too big, so decrement it
       
   578 	_asm add esi, ebx			// and add divisor to remainder
       
   579 	_asm adc ebp, ecx			//
       
   580 	_asm adc eax, 0				//
       
   581 	_asm js short longdiv3		// if still negative, repeat (requires <4 iterations)
       
   582 	longdiv4:
       
   583 	_asm add esp, 8				// remove dividend from stack
       
   584 	_asm ret					// return with quotient in EDI, remainder in EBP:ESI
       
   585 	}
       
   586 
       
   587 // Divide TRealX at [esi] / ecx,edx:ebx
       
   588 // Result in ecx,edx:ebx
       
   589 // Error code in eax
       
   590 __NAKED__ LOCAL_C void TRealXDivide(void)
       
   591 	{
       
   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
       
   612 	_asm mov eax, [esi]
       
   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
       
   619 	divfp2:
       
   620 	_asm sub eax, ebx			// else dividend mant -= divisor mant
       
   621 	_asm sbb edx, ecx			//
       
   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
       
   624 	divfp1:
       
   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
       
   629 	_asm mov eax, esi			//
       
   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
       
   633 	_asm xor eax, eax			//
       
   634 	_asm add esi, esi			// 2*remainder into EAX:EBP:ESI
       
   635 	_asm adc ebp, ebp			//
       
   636 	_asm adc eax, eax			//
       
   637 	_asm sub esi, ebx			// subtract divisor to generate final quotient bit
       
   638 	_asm sbb ebp, ecx			//
       
   639 	_asm sbb eax, 0				//
       
   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
       
   642 	_asm adc ebp, ecx			//
       
   643 	_asm adc eax, 0				// eax will be zero after this and carry will be set
       
   644 	divfp3:
       
   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
       
   648 	_asm pop edx
       
   649 	_asm add esp, 4				// discard integer bit (zero)
       
   650 	_asm jmp short divfp5		// branch to round
       
   651 
       
   652 	divfp4:						// integer bit was set
       
   653 	_asm mov ebx, edi			// result into EDX:EBX:EAX
       
   654 	_asm pop edx				//
       
   655 	_asm pop eax				// integer part of result into eax (=1)
       
   656 	_asm stc					// shift a 1 into top end of mantissa
       
   657 	_asm rcr edx,1				//
       
   658 	_asm rcr ebx,1				//
       
   659 	_asm rcr eax,1				// bottom bit into eax bit 31
       
   660 
       
   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
       
   664 	divfp5:
       
   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)
       
   672 	divfp7:
       
   673 	_asm add ebx, 1				// round up - increment mantissa
       
   674 	_asm adc edx, 0
       
   675 	_asm jnc short divfp7a
       
   676 	_asm rcr edx, 1				// if carry, shift 1 into mantissa MSB
       
   677 	_asm inc ecx				// and increment exponent
       
   678 	divfp7a:
       
   679 	_asm mov al, 2				// set rounded-up flag
       
   680 	_asm jmp short divfp9
       
   681 	divfp6:
       
   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
       
   698 	_asm ret
       
   699 
       
   700 	// come here if overflow
       
   701 	divfp10:
       
   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
       
   706 	_asm xor ebx, ebx
       
   707 	_asm mov eax, -9			// return KErrOverflow
       
   708 	_asm pop esi				// recover dividend pointer
       
   709 	_asm ret
       
   710 
       
   711 	// come here if underflow
       
   712 	divfp11:
       
   713 	_asm pop eax				// recover result sign
       
   714 	_asm xor ecx, ecx			// exponent=0
       
   715 	_asm mov cl, al				// sign into cl
       
   716 	_asm xor edx, edx
       
   717 	_asm xor ebx, ebx
       
   718 	_asm mov eax, -10			// return KErrUnderflow
       
   719 	_asm pop esi				// recover dividend pointer
       
   720 	_asm ret
       
   721 
       
   722 
       
   723 	// come here if divisor=0, dividend finite
       
   724 	divfpdv0:
       
   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
       
   729 	_asm xor ebx, ebx
       
   730 	_asm mov eax, -41			// return KErrDivideByZero
       
   731 	_asm ret
       
   732 
       
   733 	// come here if dividend=0, divisor finite and nonzero
       
   734 	divfpdd0:
       
   735 	_asm and ecx, 1				// exponent=0, leave xor sign in cl
       
   736 	_asm xor eax, eax			// return KErrNone
       
   737 	_asm ret
       
   738 
       
   739 	// come here if dividend is a NaN or infinity
       
   740 	divfpss:
       
   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
       
   745 	_asm test ebp, ebp
       
   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
       
   751 	_asm xor ebx, ebx
       
   752 	_asm mov eax, -9			// return KErrOverflow
       
   753 	_asm ret
       
   754 	divfpss1:
       
   755 	_asm cmp edx, 0x80000000	// check for infinity
       
   756 	_ASM_jn(e,TRealXBinOpNaN)	// branch if NaN
       
   757 	_asm test ebx, ebx
       
   758 	_ASM_jn(e,TRealXBinOpNaN)
       
   759 	_asm jmp TRealXRealIndefinite	// if both operands infinite, return 'real indefinite'
       
   760 
       
   761 	// come here if divisor is a NaN or infinity, dividend finite
       
   762 	divfpsd:
       
   763 	_asm cmp edx, 0x80000000	// check for infinity
       
   764 	_ASM_jn(e,TRealXBinOpNaN)	// branch if NaN
       
   765 	_asm test ebx, ebx
       
   766 	_ASM_jn(e,TRealXBinOpNaN)
       
   767 	_asm and ecx, 1				// dividend is finite, divisor=infinity, so return 0 with xor sign
       
   768 	_asm xor edx, edx
       
   769 	_asm xor ebx, ebx
       
   770 	_asm xor eax, eax			// return KErrNone
       
   771 	_asm ret
       
   772 	}
       
   773 
       
   774 // TRealX modulo - dividend at [esi], divisor in ecx,edx:ebx
       
   775 // Result in ecx,edx:ebx
       
   776 // Error code in eax
       
   777 __NAKED__ LOCAL_C void TRealXModulo(void)
       
   778 	{
       
   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
       
   798 	modfp1:
       
   799 	_asm add ebp, ebp			// shift accumulator left (65 bits)
       
   800 	_asm adc edi, edi
       
   801 	_asm adc ah, ah
       
   802 	modfp2:
       
   803 	_asm sub ebp, ebx			// subtract divisor from dividend
       
   804 	_asm sbb edi, edx
       
   805 	_asm sbb ah, 0
       
   806 	_asm jnc short modfp3		// skip if no borrow
       
   807 	_asm add ebp, ebx			// else add back
       
   808 	_asm adc edi, edx
       
   809 	_asm adc ah, 0
       
   810 	modfp3:
       
   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
       
   814 	_asm mov ebx, ebp
       
   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
       
   820 	_asm xor ebx, ebx
       
   821 	_asm sub cx, 32				// and decrement exponent by 32
       
   822 	_asm jbe modfpund			// if borrow or exponent zero, underflow
       
   823 	modfp4:
       
   824 	_asm mov edi, ecx			// preserve sign and exponent
       
   825 	_asm bsr ecx, edx			// position of most significant 1 into ecx
       
   826 	_asm neg 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
       
   829 	_asm shl ebx, cl			//
       
   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
       
   836 	_asm ret
       
   837 
       
   838 	// dividend=NaN or infinity
       
   839 	modfpss:
       
   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
       
   844 	_asm test ebp, ebp
       
   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
       
   850 	_asm test ebx, ebx
       
   851 	_ASM_jn(e,TRealXBinOpNaN)
       
   852 	_asm jmp TRealXRealIndefinite	// if both operands infinite, return 'real indefinite'
       
   853 
       
   854 	// divisor=NaN or infinity, dividend finite
       
   855 	modfpsd:
       
   856 	_asm cmp edx, 0x80000000	// check for infinity
       
   857 	_ASM_jn(e,TRealXBinOpNaN)	// branch if NaN
       
   858 	_asm test ebx, ebx
       
   859 	_ASM_jn(e,TRealXBinOpNaN)
       
   860 	// finite%infinity - return dividend unaltered
       
   861 
       
   862 	modfpdd0:
       
   863 	_asm mov ebx, [esi]			// normal exit, return dividend unaltered
       
   864 	_asm mov edx, [esi+4]
       
   865 	_asm mov ecx, [esi+8]
       
   866 	_asm xor eax, eax
       
   867 	_asm ret
       
   868 
       
   869 	modfp0:
       
   870 	_asm shr ecx, 16			// normal exit, result 0
       
   871 	_asm xor eax, eax
       
   872 	_asm ret
       
   873 
       
   874 	modfpund:
       
   875 	_asm shr ecx, 16			// underflow, result 0
       
   876 	_asm mov eax, -10			// return KErrUnderflow
       
   877 	_asm ret
       
   878 
       
   879 	modfplp:
       
   880 	_asm shr ecx, 16			// loss of precision, result 0
       
   881 	_asm mov eax, -7			// return KErrTotalLossOfPrecision
       
   882 	_asm ret
       
   883 	}
       
   884 
       
   885 
       
   886 
       
   887 
       
   888 __NAKED__ EXPORT_C TRealX::TRealX()
       
   889 /**
       
   890 Constructs a default extended precision object.
       
   891 
       
   892 This sets the value to zero.
       
   893 */
       
   894 	{
       
   895 	_asm xor eax, eax
       
   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
       
   900 	_asm ret
       
   901 	}
       
   902 
       
   903 
       
   904 
       
   905 
       
   906 __NAKED__ EXPORT_C TRealX::TRealX(TUint /*aExp*/, TUint /*aMantHi*/, TUint /*aMantLo*/)
       
   907 /**
       
   908 Constructs an extended precision object from an explicit exponent and
       
   909 a 64 bit mantissa.
       
   910 
       
   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 
       
   914 */
       
   915 	{
       
   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
       
   921 	_asm mov [ecx], eax
       
   922 	_asm mov eax, ecx			// must return this
       
   923 	_asm ret 12
       
   924 	}
       
   925 
       
   926 
       
   927 
       
   928 
       
   929 __NAKED__ EXPORT_C TInt TRealX::Set(TInt /*aInt*/)
       
   930 /**
       
   931 Gives this extended precision object a new value taken
       
   932 from a signed integer.
       
   933 
       
   934 @param aInt The signed integer value.
       
   935 
       
   936 @return KErrNone, always.
       
   937 */
       
   938 	{
       
   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
       
   942 	_asm mov eax, 0x7FFF
       
   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
       
   947 	trealxfromint1:
       
   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
       
   951 	_asm neg cl
       
   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
       
   958 	_asm xor eax, eax
       
   959 	_asm mov [ecx], eax				// zero mantissa low word
       
   960 	_asm ret 4						// return KErrNone
       
   961 	trealxfromint0:
       
   962 	_asm mov [ecx], edx
       
   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
       
   966 	_asm ret 4
       
   967 	}
       
   968 
       
   969 
       
   970 
       
   971 
       
   972 __NAKED__ EXPORT_C TInt TRealX::Set(TUint /*aInt*/)
       
   973 /**
       
   974 Gives this extended precision object a new value taken from
       
   975 an unsigned integer.
       
   976 
       
   977 @param aInt The unsigned integer value.
       
   978 
       
   979 @return KErrNone, always.
       
   980 */
       
   981 	{
       
   982 	// on entry ecx=this, [esp+4]=aInt, return code in eax
       
   983 	_asm mov edx, [esp+4]		// edx=aInt
       
   984 	_asm mov eax, 0x7FFF
       
   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
       
   990 	_asm neg cl
       
   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
       
   997 	_asm xor eax, eax
       
   998 	_asm mov [ecx], eax				// zero mantissa low word
       
   999 	_asm ret 4						// return KErrNone
       
  1000 	trealxfromuint0:
       
  1001 	_asm mov [ecx], edx
       
  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
       
  1005 	_asm ret 4
       
  1006 	}
       
  1007 
       
  1008 
       
  1009 
       
  1010 
       
  1011 __NAKED__ LOCAL_C void TRealXFromTInt64(void)
       
  1012 	{
       
  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
       
  1020 	_asm neg ebx
       
  1021 	_asm sbb edx, 0
       
  1022 	_asm jz short trealxfromtint64d	// branch if top word zero
       
  1023 	trealxfromtint64b:
       
  1024 	_asm bsr ecx, edx				// ecx=bit number of edx MSB
       
  1025 	_asm add eax, ecx				// add to exponent in eax
       
  1026 	_asm add eax, 32
       
  1027 	_asm neg cl
       
  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
       
  1030 	_asm shl ebx, cl
       
  1031 	_asm mov ecx, eax				// sign/exponent into ecx
       
  1032 	_asm ror ecx, 16				// and into normal positions
       
  1033 	_asm ret
       
  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
       
  1039 	_asm xor ebx, ebx
       
  1040 	_asm bsr ecx, edx				// ecx=bit number of edx MSB
       
  1041 	_asm add eax, ecx				// add to exponent in eax
       
  1042 	_asm neg cl
       
  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
       
  1047 	_asm ret
       
  1048 	trealxfromtint64c:				// entire number is zero
       
  1049 	_asm xor ecx, ecx
       
  1050 	_asm ret
       
  1051 	}
       
  1052 
       
  1053 
       
  1054 
       
  1055 
       
  1056 __NAKED__ EXPORT_C TInt TRealX::Set(const TInt64& /*aInt*/)
       
  1057 /**
       
  1058 Gives this extended precision object a new value taken from
       
  1059 a 64 bit integer.
       
  1060 
       
  1061 @param aInt The 64 bit integer value.
       
  1062 
       
  1063 @return KErrNone, always.
       
  1064 */
       
  1065 	{
       
  1066 	// on entry ecx=this, [esp+4]=address of aInt, return code in eax
       
  1067 	_asm push ebx
       
  1068 	_asm push ecx
       
  1069 	_asm mov edx, [esp+12]		// edx=address of aInt
       
  1070 	_asm mov ebx, [edx]
       
  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
       
  1078 	_asm pop ebx
       
  1079 	_asm ret 4
       
  1080 	}
       
  1081 
       
  1082 
       
  1083 
       
  1084 
       
  1085 __NAKED__ LOCAL_C void __6TRealXi()
       
  1086 	{
       
  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
       
  1095 	trealxfromint1:
       
  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
       
  1099 	_asm neg cl
       
  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
       
  1106 	_asm xor eax, eax
       
  1107 	_asm mov [ecx], eax				// zero mantissa low word
       
  1108 	_asm mov eax, ecx				// return eax=this
       
  1109 	_asm ret 4
       
  1110 	trealxfromint0:
       
  1111 	_asm mov [ecx], edx
       
  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
       
  1115 	_asm ret 4
       
  1116 	}
       
  1117 
       
  1118 
       
  1119 
       
  1120 
       
  1121 __NAKED__ EXPORT_C TRealX::TRealX(TInt /*aInt*/)
       
  1122 /**
       
  1123 Constructs an extended precision object from a signed integer value.
       
  1124 
       
  1125 @param aInt The signed integer value.
       
  1126 */
       
  1127 	{
       
  1128 	// on entry ecx=this, [esp+4]=aInt, return eax=this
       
  1129 	_asm jmp __6TRealXi
       
  1130 	}
       
  1131 
       
  1132 
       
  1133 
       
  1134 
       
  1135 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TInt /*aInt*/)
       
  1136 /**
       
  1137 Assigns the specified signed integer value to this extended precision object.
       
  1138 
       
  1139 @param aInt The signed integer value.
       
  1140 
       
  1141 @return A reference to this extended precision object.
       
  1142 */
       
  1143 	{
       
  1144 	// on entry ecx=this, [esp+4]=aInt, return eax=this
       
  1145 	_asm jmp __6TRealXi
       
  1146 	}
       
  1147 
       
  1148 
       
  1149 
       
  1150 
       
  1151 __NAKED__ LOCAL_C void __6TRealXui()
       
  1152 	{
       
  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
       
  1161 	_asm neg cl
       
  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
       
  1168 	_asm xor eax, eax
       
  1169 	_asm mov [ecx], eax				// zero mantissa low word
       
  1170 	_asm mov eax, ecx				// return eax=this
       
  1171 	_asm ret 4
       
  1172 	trealxfromuint0:
       
  1173 	_asm mov [ecx], edx
       
  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
       
  1177 	_asm ret 4
       
  1178 	}
       
  1179 
       
  1180 
       
  1181 
       
  1182 
       
  1183 __NAKED__ EXPORT_C TRealX::TRealX(TUint /*aInt*/)
       
  1184 /**
       
  1185 Constructs an extended precision object from an unsigned integer value.
       
  1186 
       
  1187 @param aInt The unsigned integer value.
       
  1188 */
       
  1189 	{
       
  1190 	// on entry ecx=this, [esp+4]=aInt, return eax=this
       
  1191 	_asm jmp __6TRealXui
       
  1192 	}
       
  1193 
       
  1194 
       
  1195 
       
  1196 
       
  1197 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TUint /*aInt*/)
       
  1198 /**
       
  1199 Assigns the specified unsigned integer value to this extended precision object.
       
  1200 
       
  1201 @param aInt The unsigned integer value.
       
  1202 
       
  1203 @return A reference to this extended precision object.
       
  1204 */
       
  1205 	{
       
  1206 	// on entry ecx=this, [esp+4]=aInt, return eax=this
       
  1207 	_asm jmp __6TRealXui
       
  1208 	}
       
  1209 
       
  1210 
       
  1211 
       
  1212 
       
  1213 __NAKED__ LOCAL_C void __6TRealXRC6TInt64()
       
  1214 	{
       
  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
       
  1219 	_asm mov ebx, [edx]
       
  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
       
  1228 	}
       
  1229 
       
  1230 
       
  1231 
       
  1232 
       
  1233 __NAKED__ EXPORT_C TRealX::TRealX(const TInt64& /*aInt*/)
       
  1234 /**
       
  1235 Constructs an extended precision object from a 64 bit integer.
       
  1236 
       
  1237 @param aInt A reference to a 64 bit integer. 
       
  1238 */
       
  1239 	{
       
  1240 	// on entry ecx=this, [esp+4]=address of aInt, return eax=this
       
  1241 	_asm jmp __6TRealXRC6TInt64
       
  1242 	}
       
  1243 
       
  1244 
       
  1245 
       
  1246 
       
  1247 __NAKED__ EXPORT_C TRealX& TRealX::operator=(const TInt64& /*aInt*/)
       
  1248 /**
       
  1249 Assigns the specified 64 bit integer value to this extended precision object.
       
  1250 
       
  1251 @param aInt A reference to a 64 bit integer. 
       
  1252 
       
  1253 @return A reference to this extended precision object.
       
  1254 */
       
  1255 	{
       
  1256 	// on entry ecx=this, [esp+4]=address of aInt, return eax=this
       
  1257 	_asm jmp __6TRealXRC6TInt64
       
  1258 	}
       
  1259 
       
  1260 
       
  1261 
       
  1262 
       
  1263 __NAKED__ LOCAL_C void ConvertTReal32ToTRealX(void)
       
  1264 	{
       
  1265 	// Convert TReal32 in edx to TRealX in ecx:edx,ebx
       
  1266 	_asm xor ebx, ebx			// mant low always zero
       
  1267 	_asm mov eax, edx
       
  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
       
  1271 	_asm xor ecx, ecx
       
  1272 	_asm mov cl, al
       
  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
       
  1277 	_asm mov ch, al
       
  1278 	treal32totrealx1:
       
  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
       
  1283 	_asm ret
       
  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
       
  1289 	_asm ret
       
  1290 	treal32totrealx3:			// come here if denormal
       
  1291 	_asm bsr ecx, edx			// ecx=bit number of MSB of edx
       
  1292 	_asm neg ecx
       
  1293 	_asm add ecx, 31			// ecx=number of left shifts to normalise edx
       
  1294 	_asm shl edx, cl			// normalise
       
  1295 	_asm neg ecx
       
  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
       
  1299 	_asm ret
       
  1300 	}
       
  1301 
       
  1302 __NAKED__ LOCAL_C void ConvertTReal64ToTRealX(void)
       
  1303 	{
       
  1304 	// Convert TReal64 in edx:ebx to TRealX in ecx:edx,ebx
       
  1305 	_asm mov eax, edx
       
  1306 	_asm shr eax, 20
       
  1307 	_asm mov ecx, 0x7FF
       
  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
       
  1314 	treal64totrealx2:
       
  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
       
  1318 	_asm shl ebx, cl
       
  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
       
  1322 	_asm ret
       
  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
       
  1326 	_asm shl ebx, cl
       
  1327 	_asm test edx, edx				// check for zero
       
  1328 	_asm jnz short treal64totrealx3
       
  1329 	_asm test ebx, ebx
       
  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
       
  1333 	_asm ret
       
  1334 	treal64totrealx4:				// come here if denormal, edx=0
       
  1335 	_asm mov edx, ebx				// shift mantissa left 32
       
  1336 	_asm xor ebx, ebx
       
  1337 	_asm bsr ecx, edx				// ecx=bit number of MSB of edx
       
  1338 	_asm neg ecx
       
  1339 	_asm add ecx, 31				// ecx=number of left shifts to normalise edx
       
  1340 	_asm shl edx, cl				// normalise
       
  1341 	_asm neg ecx
       
  1342 	_asm add ecx, 0x7BE0			// exponent=7BE0-number of shifts
       
  1343 	_asm shl ecx, 16				// exponent into bits 16-31 of ecx
       
  1344 	_asm shr eax, 11
       
  1345 	_asm mov cl, al					// sign into bit 0 of ecx
       
  1346 	_asm ret
       
  1347 	treal64totrealx3:				// come here if denormal, edx nonzero
       
  1348 	_asm bsr ecx, edx				// ecx=bit number of MSB of edx
       
  1349 	_asm neg ecx
       
  1350 	_asm add ecx, 31				// ecx=number of left shifts to normalise edx:ebx
       
  1351 	_asm shld edx, ebx, cl			// normalise
       
  1352 	_asm shl ebx, cl
       
  1353 	_asm neg ecx
       
  1354 	_asm add ecx, 0x7C00				// exponent=7C00-number of shifts
       
  1355 	_asm shl ecx, 16				// exponent into bits 16-31 of ecx
       
  1356 	_asm shr eax, 11
       
  1357 	_asm mov cl, al					// sign into bit 0 of ecx
       
  1358 	_asm ret
       
  1359 	}
       
  1360 
       
  1361 
       
  1362 
       
  1363 
       
  1364 __NAKED__ EXPORT_C TInt TRealX::Set(TReal32 /*aReal*/)
       
  1365 /**
       
  1366 Gives this extended precision object a new value taken from
       
  1367 a single precision floating point number.
       
  1368 
       
  1369 @param aReal The single precision floating point value. 
       
  1370 
       
  1371 @return KErrNone, if a valid number;
       
  1372         KErrOverflow, if the number is infinite;
       
  1373         KErrArgument, if not a number.
       
  1374 */
       
  1375 	{
       
  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
       
  1393 	trealxsettreal32a:
       
  1394 	_asm pop ebx
       
  1395 	_asm ret 4
       
  1396 	}
       
  1397 
       
  1398 
       
  1399 
       
  1400 
       
  1401 __NAKED__ EXPORT_C TInt TRealX::Set(TReal64 /*aReal*/)
       
  1402 /**
       
  1403 Gives this extended precision object a new value taken from
       
  1404 a double precision floating point number.
       
  1405 
       
  1406 @param aReal The double precision floating point value. 
       
  1407 
       
  1408 @return KErrNone, if a valid number;
       
  1409         KErrOverflow, if the number is infinite;
       
  1410         KErrArgument, if not a number.
       
  1411 */
       
  1412 	{
       
  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
       
  1430 	_asm test ebx, ebx
       
  1431 	_asm je short trealxsettreal64a		// if infinity, return KErrOverflow
       
  1432 	trealxsettreal64b:
       
  1433 	_asm mov eax, -6				// if NaN, return KErrArgument
       
  1434 	trealxsettreal64a:
       
  1435 	_asm pop ebx
       
  1436 	_asm ret 8
       
  1437 	}
       
  1438 
       
  1439 
       
  1440 
       
  1441 
       
  1442 __NAKED__ LOCAL_C void __6TRealXf()
       
  1443 	{
       
  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
       
  1453 	_asm pop ebx
       
  1454 	_asm ret 4
       
  1455 	}
       
  1456 
       
  1457 
       
  1458 
       
  1459 
       
  1460 __NAKED__ EXPORT_C TRealX::TRealX(TReal32 /*aReal*/)
       
  1461 /**
       
  1462 Constructs an extended precision object from
       
  1463 a single precision floating point number.
       
  1464 
       
  1465 @param aReal The single precision floating point value.
       
  1466 */
       
  1467 	{
       
  1468 	// on entry, ecx=this and aReal is in [esp+4]
       
  1469 	// on exit, eax=this
       
  1470 	_asm jmp __6TRealXf
       
  1471 	}
       
  1472 
       
  1473 
       
  1474 
       
  1475 
       
  1476 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TReal32 /*aReal*/)
       
  1477 /**
       
  1478 Assigns the specified single precision floating point number to
       
  1479 this extended precision object.
       
  1480 
       
  1481 @param aReal The single precision floating point value.
       
  1482 
       
  1483 @return A reference to this extended precision object.
       
  1484 */
       
  1485 	{
       
  1486 	// on entry, ecx=this and aReal is in [esp+4]
       
  1487 	// on exit, eax=this
       
  1488 	_asm jmp __6TRealXf
       
  1489 	}
       
  1490 
       
  1491 
       
  1492 
       
  1493 
       
  1494 __NAKED__ LOCAL_C void __6TRealXd()
       
  1495 	{
       
  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
       
  1506 	_asm pop ebx
       
  1507 	_asm ret 8
       
  1508 	}
       
  1509 
       
  1510 
       
  1511 
       
  1512 
       
  1513 __NAKED__ EXPORT_C TRealX::TRealX(TReal64 /*aReal*/)
       
  1514 /**
       
  1515 Constructs an extended precision object from
       
  1516 a double precision floating point number.
       
  1517 
       
  1518 @param aReal The double precision floating point value.
       
  1519 */
       
  1520 	{
       
  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
       
  1523 	_asm jmp __6TRealXd
       
  1524 	}
       
  1525 
       
  1526 
       
  1527 
       
  1528 
       
  1529 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TReal64 /*aReal*/)
       
  1530 /**
       
  1531 Assigns the specified double precision floating point number to
       
  1532 this extended precision object.
       
  1533 
       
  1534 @param aReal The double precision floating point value.
       
  1535 
       
  1536 @return A reference to this extended precision object.
       
  1537 */
       
  1538 	{
       
  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
       
  1541 	_asm jmp __6TRealXd
       
  1542 	}
       
  1543 
       
  1544 
       
  1545 
       
  1546 
       
  1547 __NAKED__ EXPORT_C TRealX::operator TInt() const
       
  1548 /**
       
  1549 Gets the extended precision value as a signed integer value.
       
  1550 
       
  1551 The operator returns:
       
  1552 
       
  1553 1. zero , if the extended precision value is not a number
       
  1554 
       
  1555 2. 0x7FFFFFFF, if the value is positive and too big to fit into a TInt.
       
  1556 
       
  1557 3. 0x80000000, if the value is negative and too big to fit into a TInt.
       
  1558 */
       
  1559 	{
       
  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
       
  1565 	_asm cmp cx, 0xFFFF
       
  1566 	_asm jz short trealxtoint1	// branch if exp=FFFF
       
  1567 	_asm mov dx, cx
       
  1568 	_asm mov cx, 0x801E
       
  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 +
       
  1576 	_asm neg eax
       
  1577 	trealxtoint3:
       
  1578 	_asm ret
       
  1579 	trealxtoint1:			// come here if exponent=FFFF
       
  1580 	_asm cmp eax, 0x80000000		// check for infinity
       
  1581 	_asm jnz short trealxtoint0	// if NaN, return 0
       
  1582 	_asm test edx, edx
       
  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
       
  1591 	_asm ret
       
  1592 	}
       
  1593 
       
  1594 
       
  1595 
       
  1596 
       
  1597 __NAKED__ EXPORT_C TRealX::operator TUint() const
       
  1598 /**
       
  1599 Returns the extended precision value as an unsigned signed integer value.
       
  1600 
       
  1601 The operator returns:
       
  1602 
       
  1603 1. zero, if the extended precision value is not a number
       
  1604 
       
  1605 2. 0xFFFFFFFF, if the value is positive and too big to fit into a TUint.
       
  1606 
       
  1607 3. zero, if the value is negative and too big to fit into a TUint.
       
  1608 */
       
  1609 	{
       
  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
       
  1615 	_asm cmp cx, 0xFFFF
       
  1616 	_asm jz short trealxtouint1	// branch if exp=FFFF
       
  1617 	_asm mov dx, cx
       
  1618 	_asm mov cx, 0x801E
       
  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
       
  1626 	_asm ret
       
  1627 	trealxtouint1:			// come here if exponent=FFFF
       
  1628 	_asm cmp eax, 0x80000000		// check for infinity
       
  1629 	_asm jnz short trealxtouint0	// if NaN, return 0
       
  1630 	_asm test edx, edx
       
  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
       
  1639 	_asm ret
       
  1640 	}
       
  1641 
       
  1642 
       
  1643 
       
  1644 
       
  1645 __NAKED__ LOCAL_C void ConvertTRealXToTInt64(void)
       
  1646 	{
       
  1647 	// Convert TRealX in ecx,edx:ebx to TInt64 in edx:ebx
       
  1648 	_asm ror ecx, 16				// exponent into cx
       
  1649 	_asm cmp cx, 0xFFFF
       
  1650 	_asm jz short trealxtoint64a	// branch if exp=FFFF
       
  1651 	_asm mov ax, cx
       
  1652 	_asm mov cx, 0x803E
       
  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
       
  1661 	_asm xor edx, edx
       
  1662 	trealxtoint64d:
       
  1663 	_asm shrd ebx, edx, cl			// shift edx:ebx right by cl to give ABS(result)
       
  1664 	_asm shr edx, cl
       
  1665 	_asm test ecx, 0x10000			// test sign
       
  1666 	_asm jz short trealxtoint64c	// skip if +
       
  1667 	_asm neg edx					// if -, negate
       
  1668 	_asm neg ebx
       
  1669 	_asm sbb edx, 0
       
  1670 	trealxtoint64c:
       
  1671 	_asm ret
       
  1672 	trealxtoint64a:			// come here if exponent=FFFF
       
  1673 	_asm cmp edx, 0x80000000			// check for infinity
       
  1674 	_asm jnz short trealxtoint64z	// if NaN, return 0
       
  1675 	_asm test ebx, ebx
       
  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
       
  1686 	_asm xor ebx, ebx
       
  1687 	_asm ret
       
  1688 	}
       
  1689 
       
  1690 
       
  1691 
       
  1692 
       
  1693 /**
       
  1694 Returns the extended precision value as a 64 bit integer value.
       
  1695 
       
  1696 The operator returns:
       
  1697 
       
  1698 1. zero, if the extended precision value is not a number
       
  1699 
       
  1700 2. 0x7FFFFFFF FFFFFFFF, if the value is positive and too big to fit
       
  1701    into a TInt64
       
  1702 
       
  1703 3. 0x80000000 00000000, if the value is negative and too big to fit
       
  1704    into a TInt64.
       
  1705 */
       
  1706 __NAKED__ EXPORT_C TRealX::operator TInt64() const
       
  1707 	{
       
  1708 	// on entry, ecx=this, return value in edx:eax
       
  1709 	_asm push ebx
       
  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
       
  1715 	_asm pop ebx
       
  1716 	_asm ret
       
  1717 	}
       
  1718 
       
  1719 
       
  1720 
       
  1721 
       
  1722 __NAKED__ LOCAL_C void TRealXGetTReal32(void)
       
  1723 	{
       
  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
       
  1728 	_asm xor eax, eax
       
  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
       
  1738 	_asm shr edx, 7
       
  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
       
  1742 	_asm mov eax, edx
       
  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
       
  1747 	trealxgettreal32e:
       
  1748 	_asm ret
       
  1749 	trealxgettreal32b:			// come here if exponent<=7F80
       
  1750 	_asm cmp cx, -24				// check for zero or total underflow
       
  1751 	_asm jle short trealxgettreal32z
       
  1752 	_asm neg cl
       
  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
       
  1756 	_asm shr 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
       
  1763 	_asm test ebx, ebx
       
  1764 	_asm jnz short trealxgettreal32f	// branch to round up
       
  1765 	_asm test eax, eax
       
  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
       
  1776 	_asm rcr edx, 1
       
  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
       
  1781 	_asm xor dl, dl
       
  1782 	_asm add edx, edx					// shift out integer bit
       
  1783 	_asm mov dl, cl
       
  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
       
  1790 	_asm ret
       
  1791 	trealxgettreal32z:				// come here if zero or underflow
       
  1792 	_asm xor eax, eax
       
  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
       
  1797 	trealxgettreal32y:
       
  1798 	_asm xor edx, edx
       
  1799 	_asm shr ecx, 17
       
  1800 	_asm rcr edx, 1						// sign bit into edx bit 31, rest of edx=0
       
  1801 	_asm ret
       
  1802 	}
       
  1803 
       
  1804 
       
  1805 
       
  1806 
       
  1807 __NAKED__ LOCAL_C void TRealXGetTReal64(void)
       
  1808 	{
       
  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
       
  1815 	_asm xor eax, eax
       
  1816 	_asm xor edi, edi
       
  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
       
  1823 	_asm xor ebx, ebx
       
  1824 	trealxgettreal64a:			// come here if infinity or NaN
       
  1825 	_asm mov cl, 10
       
  1826 	_asm shrd ebx, edx, cl
       
  1827 	_asm shr 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
       
  1831 	_asm rcr ebx, 1
       
  1832 	_asm mov eax, edx
       
  1833 	_asm shl eax, 12				// test for infinity or NaN
       
  1834 	_asm mov eax, -9				// eax=KErrOverflow
       
  1835 	_asm jnz short trealxgettreal64n
       
  1836 	_asm test ebx, ebx
       
  1837 	_asm jz short trealxgettreal64e
       
  1838 	trealxgettreal64n:
       
  1839 	_asm mov eax, -6				// if NaN, eax=KErrArgument
       
  1840 	trealxgettreal64e:
       
  1841 	_asm ret
       
  1842 	trealxgettreal64b:			// come here if exponent<=7C00
       
  1843 	_asm cmp cx, -53				// check for zero or total underflow
       
  1844 	_asm jle trealxgettreal64z
       
  1845 	_asm neg cl
       
  1846 	_asm inc cl						// cl=number of right shifts to form denormal mantissa
       
  1847 	_asm cmp cl, 32
       
  1848 	_asm jb trealxgettreal64x
       
  1849 	_asm mov eax, ebx				// if >=32 shifts, do 32 shifts and decrement count by 32
       
  1850 	_asm mov ebx, edx
       
  1851 	_asm xor edx, edx
       
  1852 	trealxgettreal64x:
       
  1853 	_asm shrd edi, eax, cl
       
  1854 	_asm shrd eax, ebx, cl			// shift mantissa right into eax
       
  1855 	_asm shrd ebx, edx, cl
       
  1856 	_asm shr 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
       
  1860 	_asm mov esi, ebx
       
  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
       
  1865 	_asm test eax, eax
       
  1866 	_asm jnz short trealxgettreal64f	// branch to round up
       
  1867 	_asm test edi, edi
       
  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
       
  1877 	_asm adc edx, 0
       
  1878 	_asm jnc short trealxgettreal64g
       
  1879 	_asm rcr edx, 1
       
  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
       
  1885 	_asm and bh, 0xF8
       
  1886 	_asm mov di, cx						// save exponent
       
  1887 	_asm mov cl, 10
       
  1888 	_asm and edx, 0x7FFFFFFF				// clear integer bit
       
  1889 	_asm shrd ebx, edx, cl				// shift mantissa right by 10
       
  1890 	_asm shr edx, cl
       
  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
       
  1895 	_asm test ebx, ebx
       
  1896 	_asm jz short trealxgettreal64h		// branch out if underflow
       
  1897 	trealxgettreal64i:
       
  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
       
  1900 	_asm rcr ebx, 1
       
  1901 	_asm xor eax, eax					// return KErrNone
       
  1902 	_asm ret
       
  1903 	trealxgettreal64z:				// come here if zero or underflow
       
  1904 	_asm xor eax, eax
       
  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
       
  1909 	trealxgettreal64y:
       
  1910 	_asm xor edx, edx
       
  1911 	_asm xor ebx, ebx
       
  1912 	_asm shr ecx, 17
       
  1913 	_asm rcr edx, 1						// sign bit into edx bit 31, rest of edx=0, ebx=0
       
  1914 	_asm ret
       
  1915 	}
       
  1916 
       
  1917 
       
  1918 
       
  1919 
       
  1920 __NAKED__ EXPORT_C TRealX::operator TReal32() const
       
  1921 /**
       
  1922 Returns the extended precision value as
       
  1923 a single precision floating point value.
       
  1924 */
       
  1925 	{
       
  1926 	// On entry, ecx=this
       
  1927 	// On exit, TReal32 value on top of FPU stack
       
  1928 	_asm push ebx
       
  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
       
  1935 	_asm pop edx
       
  1936 	_asm pop ebx
       
  1937 	_asm ret
       
  1938 	}
       
  1939 
       
  1940 
       
  1941 
       
  1942 
       
  1943 __NAKED__ EXPORT_C TRealX::operator TReal64() const
       
  1944 /**
       
  1945 Returns the extended precision value as
       
  1946 a double precision floating point value.
       
  1947 */
       
  1948 	{
       
  1949 	// On entry, ecx=this
       
  1950 	// On exit, TReal64 value on top of FPU stack
       
  1951 	_asm push ebx
       
  1952 	_asm push esi
       
  1953 	_asm push edi
       
  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
       
  1959 	_asm push ebx
       
  1960 	_asm fld qword ptr [esp]	// push TReal64 onto FPU stack
       
  1961 	_asm add esp, 8
       
  1962 	_asm pop edi
       
  1963 	_asm pop esi
       
  1964 	_asm pop ebx
       
  1965 	_asm ret
       
  1966 	}
       
  1967 
       
  1968 
       
  1969 
       
  1970 
       
  1971 __NAKED__ EXPORT_C TInt TRealX::GetTReal(TReal32& /*aVal*/) const
       
  1972 /**
       
  1973 Extracts the extended precision value as
       
  1974 a single precision floating point value.
       
  1975 
       
  1976 @param aVal A reference to a single precision object which contains
       
  1977             the result of the operation.
       
  1978 
       
  1979 @return KErrNone, if the operation is successful;
       
  1980         KErrOverflow, if the operation results in overflow;
       
  1981         KErrUnderflow, if the operation results in underflow.
       
  1982 */
       
  1983 	{
       
  1984 	// On entry, ecx=this, [esp+4]=address of aVal
       
  1985 	// On exit, eax=return code
       
  1986 	_asm push ebx
       
  1987 	_asm mov ebx, [ecx]			// *this into ecx,edx:ebx
       
  1988 	_asm mov edx, [ecx+4]
       
  1989 	_asm mov ecx, [ecx+8]
       
  1990 	_asm call TRealXGetTReal32
       
  1991 	_asm mov ecx, [esp+8]		// ecx=address of aVal
       
  1992 	_asm mov [ecx], edx			// store result
       
  1993 	_asm pop ebx
       
  1994 	_asm ret 4					// return with error code in eax
       
  1995 	}
       
  1996 
       
  1997 
       
  1998 
       
  1999 
       
  2000 __NAKED__ EXPORT_C TInt TRealX::GetTReal(TReal64& /*aVal*/) const
       
  2001 /**
       
  2002 Extracts the extended precision value as
       
  2003 a double precision floating point value.
       
  2004 
       
  2005 @param aVal A reference to a double precision object which
       
  2006             contains the result of the operation.
       
  2007 
       
  2008 @return KErrNone, if the operation is successful;
       
  2009         KErrOverflow, if the operation results in overflow;
       
  2010         KErrUnderflow, if the operation results in underflow.
       
  2011 */
       
  2012 	{
       
  2013 	// On entry, ecx=this, [esp+4]=address of aVal
       
  2014 	// On exit, eax=return code
       
  2015 	_asm push ebx
       
  2016 	_asm push esi
       
  2017 	_asm push edi
       
  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
       
  2025 	_asm pop edi
       
  2026 	_asm pop esi
       
  2027 	_asm pop ebx
       
  2028 	_asm ret 4					// return with error code in eax
       
  2029 	}
       
  2030 
       
  2031 
       
  2032 
       
  2033 
       
  2034 __NAKED__ EXPORT_C void TRealX::SetZero(TBool /*aNegative*/)
       
  2035 /**
       
  2036 Sets the value of this extended precision object to zero.
       
  2037 
       
  2038 @param aNegative ETrue, the value is a negative zero;
       
  2039                  EFalse, the value is a positive zero, this is the default.
       
  2040 */
       
  2041 	{
       
  2042 	_asm mov edx, [esp+4]		// aNegative into edx
       
  2043 	_asm xor eax, eax			// eax=0
       
  2044 	_asm mov [ecx], eax
       
  2045 	_asm mov [ecx+4], eax
       
  2046 	_asm test edx, edx
       
  2047 	_asm jz short setzero1
       
  2048 	_asm inc eax				// eax=1 if aNegative!=0
       
  2049 	setzero1:
       
  2050 	_asm mov [ecx+8], eax		// generate positive or negative zero
       
  2051 	_asm ret 4
       
  2052 	}
       
  2053 
       
  2054 
       
  2055 
       
  2056 
       
  2057 __NAKED__ EXPORT_C void TRealX::SetNaN()
       
  2058 /**
       
  2059 Sets the value of this extended precision object to 'not a number'.
       
  2060 */
       
  2061 	{
       
  2062 	_asm xor eax, eax			// set *this to 'real indefinite'
       
  2063 	_asm mov [ecx], eax
       
  2064 	_asm mov eax, 0xC0000000
       
  2065 	_asm mov [ecx+4], eax
       
  2066 	_asm mov eax, 0xFFFF0001
       
  2067 	_asm mov [ecx+8], eax
       
  2068 	_asm ret
       
  2069 	}
       
  2070 
       
  2071 
       
  2072 
       
  2073 
       
  2074 __NAKED__ EXPORT_C void TRealX::SetInfinite(TBool /*aNegative*/)
       
  2075 /**
       
  2076 Sets the value of this extended precision object to infinity.
       
  2077 
       
  2078 @param aNegative ETrue, the value is a negative zero;
       
  2079                  EFalse, the value is a positive zero.
       
  2080 */
       
  2081 	{
       
  2082 	_asm mov edx, [esp+4]		// aNegative into edx
       
  2083 	_asm mov eax, 0xFFFF0000	// exponent=FFFF, sign=0 initially
       
  2084 	_asm test edx, edx
       
  2085 	_asm jz short setinf1
       
  2086 	_asm inc eax				// sign=1 if aNegative!=0
       
  2087 	setinf1:
       
  2088 	_asm mov [ecx+8], eax		// generate positive or negative infinity
       
  2089 	_asm mov eax, 0x80000000
       
  2090 	_asm mov [ecx+4], eax
       
  2091 	_asm xor eax, eax
       
  2092 	_asm mov [ecx], eax
       
  2093 	_asm ret 4
       
  2094 	}
       
  2095 
       
  2096 
       
  2097 
       
  2098 
       
  2099 __NAKED__ EXPORT_C TBool TRealX::IsZero() const
       
  2100 /**
       
  2101 Determines whether the extended precision value is zero.
       
  2102 
       
  2103 @return True, if the extended precision value is zero, false, otherwise.
       
  2104 */
       
  2105 	{
       
  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
       
  2110 	_asm ret
       
  2111 	iszero1:
       
  2112 	_asm inc eax				// if zero, return 1
       
  2113 	_asm ret
       
  2114 	}
       
  2115 
       
  2116 
       
  2117 
       
  2118 
       
  2119 __NAKED__ EXPORT_C TBool TRealX::IsNaN() const
       
  2120 /**
       
  2121 Determines whether the extended precision value is 'not a number'.
       
  2122 
       
  2123 @return True, if the extended precision value is 'not a number',
       
  2124         false, otherwise.
       
  2125 */
       
  2126 	{
       
  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
       
  2133 	_asm mov eax, [ecx]
       
  2134 	_asm test eax, eax
       
  2135 	_asm jne short isnan1
       
  2136 	isnan0:
       
  2137 	_asm xor eax, eax			// return 0 if not NaN
       
  2138 	_asm ret
       
  2139 	isnan1:
       
  2140 	_asm mov eax, 1				// return 1 if NaN
       
  2141 	_asm ret
       
  2142 	}
       
  2143 
       
  2144 
       
  2145 
       
  2146 
       
  2147 __NAKED__ EXPORT_C TBool TRealX::IsInfinite() const
       
  2148 /**
       
  2149 Determines whether the extended precision value has a finite value.
       
  2150 
       
  2151 @return True, if the extended precision value is finite,
       
  2152         false, if the value is 'not a number' or is infinite,
       
  2153 */
       
  2154 	{
       
  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
       
  2161 	_asm mov eax, [ecx]
       
  2162 	_asm test eax, eax
       
  2163 	_asm jne short isinf0
       
  2164 	_asm inc eax				// return 1 if infinity
       
  2165 	_asm ret
       
  2166 	isinf0:
       
  2167 	_asm xor eax, eax			// return 0 if not infinity
       
  2168 	_asm ret
       
  2169 	}
       
  2170 
       
  2171 
       
  2172 
       
  2173 
       
  2174 __NAKED__ EXPORT_C TBool TRealX::IsFinite() const
       
  2175 /**
       
  2176 Determines whether the extended precision value has a finite value.
       
  2177 
       
  2178 @return True, if the extended precision value is finite,
       
  2179         false, if the value is 'not a number' or is infinite,
       
  2180 */
       
  2181 	{
       
  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
       
  2186 	_asm ret
       
  2187 	isfinite0:
       
  2188 	_asm xor eax, eax			// return 0 if NaN or infinity
       
  2189 	_asm ret
       
  2190 	}
       
  2191 
       
  2192 
       
  2193 
       
  2194 
       
  2195 __NAKED__ EXPORT_C const TRealX& TRealX::operator+=(const TRealX& /*aVal*/)
       
  2196 /**
       
  2197 Adds an extended precision value to this extended precision number.
       
  2198 
       
  2199 @param aVal The extended precision value to be added.
       
  2200 
       
  2201 @return A reference to this object.
       
  2202 
       
  2203 @panic MATHX KErrOverflow if the operation results in overflow.
       
  2204 @panic MATHX KErrUnderflow if  the operation results in underflow.
       
  2205 */
       
  2206 	{
       
  2207 	// on entry ecx=this, [esp+4]=address of aVal
       
  2208 	_asm push ebx				// save registers
       
  2209 	_asm push ebp
       
  2210 	_asm push esi
       
  2211 	_asm push edi
       
  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
       
  2221 	_asm test eax, eax
       
  2222 	_ASM_jn(z,TRealXPanicEax)	// panic if error
       
  2223 	_asm mov eax, esi			// return this in eax
       
  2224 	_asm pop edi				// restore registers
       
  2225 	_asm pop esi
       
  2226 	_asm pop ebp
       
  2227 	_asm pop ebx
       
  2228 	_asm ret 4
       
  2229 	}
       
  2230 
       
  2231 
       
  2232 
       
  2233 
       
  2234 __NAKED__ EXPORT_C const TRealX& TRealX::operator-=(const TRealX& /*aVal*/)
       
  2235 /**
       
  2236 Subtracts an extended precision value from this extended precision number. 
       
  2237 
       
  2238 @param aVal The extended precision value to be subtracted.
       
  2239 
       
  2240 @return A reference to this object.
       
  2241 
       
  2242 @panic MATHX KErrOverflow if the operation results in overflow.
       
  2243 @panic MATHX KErrUnderflow if  the operation results in underflow.
       
  2244 */
       
  2245 	{
       
  2246 	// on entry ecx=this, [esp+4]=address of aVal
       
  2247 	_asm push ebx				// save registers
       
  2248 	_asm push ebp
       
  2249 	_asm push esi
       
  2250 	_asm push edi
       
  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
       
  2260 	_asm test eax, eax
       
  2261 	_ASM_jn(z,TRealXPanicEax)	// panic if error
       
  2262 	_asm mov eax, esi			// return this in eax
       
  2263 	_asm pop edi				// restore registers
       
  2264 	_asm pop esi
       
  2265 	_asm pop ebp
       
  2266 	_asm pop ebx
       
  2267 	_asm ret 4
       
  2268 	}
       
  2269 
       
  2270 
       
  2271 
       
  2272 
       
  2273 __NAKED__ EXPORT_C const TRealX& TRealX::operator*=(const TRealX& /*aVal*/)
       
  2274 /**
       
  2275 Multiplies this extended precision number by an extended precision value.
       
  2276 
       
  2277 @param aVal The extended precision value to be subtracted.
       
  2278 
       
  2279 @return A reference to this object.
       
  2280 
       
  2281 @panic MATHX KErrOverflow if the operation results in overflow.
       
  2282 @panic MATHX KErrUnderflow if  the operation results in underflow.
       
  2283 */
       
  2284 	{
       
  2285 	// on entry ecx=this, [esp+4]=address of aVal
       
  2286 	_asm push ebx				// save registers
       
  2287 	_asm push ebp
       
  2288 	_asm push esi
       
  2289 	_asm push edi
       
  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
       
  2299 	_asm test eax, eax
       
  2300 	_ASM_jn(z,TRealXPanicEax)	// panic if error
       
  2301 	_asm mov eax, esi			// return this in eax
       
  2302 	_asm pop edi				// restore registers
       
  2303 	_asm pop esi
       
  2304 	_asm pop ebp
       
  2305 	_asm pop ebx
       
  2306 	_asm ret 4
       
  2307 	}
       
  2308 
       
  2309 
       
  2310 
       
  2311 
       
  2312 __NAKED__ EXPORT_C const TRealX& TRealX::operator/=(const TRealX& /*aVal*/)
       
  2313 /**
       
  2314 Divides this extended precision number by an extended precision value.
       
  2315 
       
  2316 @param aVal The extended precision value to be used as the divisor. 
       
  2317 
       
  2318 @return A reference to this object.
       
  2319 
       
  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.
       
  2323 */
       
  2324 	{
       
  2325 	// on entry ecx=this, [esp+4]=address of aVal
       
  2326 	_asm push ebx				// save registers
       
  2327 	_asm push ebp
       
  2328 	_asm push esi
       
  2329 	_asm push edi
       
  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
       
  2339 	_asm test eax, eax
       
  2340 	_ASM_jn(z,TRealXPanicEax)	// panic if error
       
  2341 	_asm mov eax, esi			// return this in eax
       
  2342 	_asm pop edi				// restore registers
       
  2343 	_asm pop esi
       
  2344 	_asm pop ebp
       
  2345 	_asm pop ebx
       
  2346 	_asm ret 4
       
  2347 	}
       
  2348 
       
  2349 
       
  2350 
       
  2351 
       
  2352 __NAKED__ EXPORT_C const TRealX& TRealX::operator%=(const TRealX& /*aVal*/)
       
  2353 /**
       
  2354 Modulo-divides this extended precision number by an extended precision value.
       
  2355 
       
  2356 @param aVal The extended precision value to be used as the divisor. 
       
  2357 
       
  2358 @return A reference to this object.
       
  2359 
       
  2360 @panic MATHX KErrTotalLossOfPrecision panic if precision is lost.
       
  2361 @panic MATHX KErrUnderflow if  the operation results in underflow.
       
  2362 */
       
  2363 	{
       
  2364 	// on entry ecx=this, [esp+4]=address of aVal
       
  2365 	_asm push ebx				// save registers
       
  2366 	_asm push ebp
       
  2367 	_asm push esi
       
  2368 	_asm push edi
       
  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
       
  2378 	_asm test eax, eax
       
  2379 	_ASM_jn(z,TRealXPanicEax)	// panic if error
       
  2380 	_asm mov eax, esi			// return this in eax
       
  2381 	_asm pop edi				// restore registers
       
  2382 	_asm pop esi
       
  2383 	_asm pop ebp
       
  2384 	_asm pop ebx
       
  2385 	_asm ret 4
       
  2386 	}
       
  2387 
       
  2388 
       
  2389 
       
  2390 
       
  2391 __NAKED__ EXPORT_C TInt TRealX::AddEq(const TRealX& /*aVal*/)
       
  2392 /**
       
  2393 Adds an extended precision value to this extended precision number.
       
  2394 
       
  2395 @param aVal The extended precision value to be added.
       
  2396 
       
  2397 @return KErrNone, if the operation is successful;
       
  2398         KErrOverflow,if the operation results in overflow;
       
  2399         KErrUnderflow, if the operation results in underflow. 
       
  2400 */
       
  2401 	{
       
  2402 	// on entry ecx=this, [esp+4]=address of aVal
       
  2403 	_asm push ebx				// save registers
       
  2404 	_asm push ebp
       
  2405 	_asm push esi
       
  2406 	_asm push edi
       
  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
       
  2417 	_asm pop esi
       
  2418 	_asm pop ebp
       
  2419 	_asm pop ebx
       
  2420 	_asm ret 4					// return with error code in eax
       
  2421 	}
       
  2422 
       
  2423 
       
  2424 
       
  2425 
       
  2426 __NAKED__ EXPORT_C TInt TRealX::SubEq(const TRealX& /*aVal*/)
       
  2427 /**
       
  2428 Subtracts an extended precision value from this extended precision number.
       
  2429 
       
  2430 @param aVal The extended precision value to be subtracted.
       
  2431 
       
  2432 @return KErrNone, if the operation is successful;
       
  2433         KErrOverflow, if the operation results in overflow;
       
  2434         KErrUnderflow, if the operation results in underflow.
       
  2435 */
       
  2436 	{
       
  2437 	// on entry ecx=this, [esp+4]=address of aVal
       
  2438 	_asm push ebx				// save registers
       
  2439 	_asm push ebp
       
  2440 	_asm push esi
       
  2441 	_asm push edi
       
  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
       
  2452 	_asm pop esi
       
  2453 	_asm pop ebp
       
  2454 	_asm pop ebx
       
  2455 	_asm ret 4					// return with error code in eax
       
  2456 	}
       
  2457 
       
  2458 
       
  2459 
       
  2460 
       
  2461 __NAKED__ EXPORT_C TInt TRealX::MultEq(const TRealX& /*aVal*/)
       
  2462 /**
       
  2463 Multiplies this extended precision number by an extended precision value.
       
  2464 
       
  2465 @param aVal The extended precision value to be used as the multiplier.
       
  2466 
       
  2467 @return KErrNone, if the operation is successful;
       
  2468         KErrOverflow, if the operation results in overflow;
       
  2469         KErrUnderflow, if the operation results in underflow
       
  2470 */
       
  2471 	{
       
  2472 	// on entry ecx=this, [esp+4]=address of aVal
       
  2473 	_asm push ebx				// save registers
       
  2474 	_asm push ebp
       
  2475 	_asm push esi
       
  2476 	_asm push edi
       
  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
       
  2487 	_asm pop esi
       
  2488 	_asm pop ebp
       
  2489 	_asm pop ebx
       
  2490 	_asm ret 4					// return with error code in eax
       
  2491 	}
       
  2492 
       
  2493 
       
  2494 
       
  2495 
       
  2496 __NAKED__ EXPORT_C TInt TRealX::DivEq(const TRealX& /*aVal*/)
       
  2497 /**
       
  2498 Divides this extended precision number by an extended precision value.
       
  2499 
       
  2500 @param aVal The extended precision value to be used as the divisor.
       
  2501 
       
  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. 
       
  2506 */
       
  2507 	{
       
  2508 	// on entry ecx=this, [esp+4]=address of aVal
       
  2509 	_asm push ebx				// save registers
       
  2510 	_asm push ebp
       
  2511 	_asm push esi
       
  2512 	_asm push edi
       
  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
       
  2523 	_asm pop esi
       
  2524 	_asm pop ebp
       
  2525 	_asm pop ebx
       
  2526 	_asm ret 4					// return with error code in eax
       
  2527 	}
       
  2528 
       
  2529 
       
  2530 
       
  2531 
       
  2532 __NAKED__ EXPORT_C TInt TRealX::ModEq(const TRealX& /*aVal*/)
       
  2533 /**
       
  2534 Modulo-divides this extended precision number by an extended precision value.
       
  2535 
       
  2536 @param aVal The extended precision value to be used as the divisor. 
       
  2537 
       
  2538 @return KErrNone, if the operation is successful;
       
  2539         KErrTotalLossOfPrecision, if precision is lost;
       
  2540         KErrUnderflow, if the operation results in underflow.
       
  2541 */
       
  2542 	{
       
  2543 	// on entry ecx=this, [esp+4]=address of aVal
       
  2544 	_asm push ebx				// save registers
       
  2545 	_asm push ebp
       
  2546 	_asm push esi
       
  2547 	_asm push edi
       
  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
       
  2558 	_asm pop esi
       
  2559 	_asm pop ebp
       
  2560 	_asm pop ebx
       
  2561 	_asm ret 4					// return with error code in eax
       
  2562 	}
       
  2563 
       
  2564 
       
  2565 
       
  2566 
       
  2567 __NAKED__ EXPORT_C TRealX TRealX::operator+() const
       
  2568 /**
       
  2569 Returns this extended precision number unchanged.
       
  2570 
       
  2571 Note that this may also be referred to as a unary plus operator. 
       
  2572 
       
  2573 @return The extended precision number.
       
  2574 */
       
  2575 	{
       
  2576 	_asm mov eax, [esp+4]		// eax=address to write return value
       
  2577 	_asm mov edx, [ecx]
       
  2578 	_asm mov [eax], edx
       
  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
       
  2584 	}
       
  2585 
       
  2586 
       
  2587 
       
  2588 
       
  2589 __NAKED__ EXPORT_C TRealX TRealX::operator-() const
       
  2590 /**
       
  2591 Negates this extended precision number.
       
  2592 
       
  2593 This may also be referred to as a unary minus operator.
       
  2594 
       
  2595 @return The negative of the extended precision number.
       
  2596 */
       
  2597 	{
       
  2598 	_asm mov eax, [esp+4]		// eax=address to write return value
       
  2599 	_asm mov edx, [ecx]
       
  2600 	_asm mov [eax], edx
       
  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
       
  2607 	}
       
  2608 
       
  2609 
       
  2610 
       
  2611 
       
  2612 __NAKED__ EXPORT_C TRealX& TRealX::operator++()
       
  2613 /**
       
  2614 Increments this extended precision number by one,
       
  2615 and then returns a reference to it.
       
  2616 
       
  2617 This is also referred to as a prefix operator. 
       
  2618 
       
  2619 @return A reference to this object.
       
  2620 
       
  2621 @panic MATHX KErrOverflow if the operation results in overflow.
       
  2622 @panic MATHX KErrUnderflow if  the operation results in underflow.
       
  2623 */
       
  2624 	{
       
  2625 	// pre-increment
       
  2626 	// on entry ecx=this, return this in eax
       
  2627 	_asm push ebx				// save registers
       
  2628 	_asm push ebp
       
  2629 	_asm push esi
       
  2630 	_asm push edi
       
  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
       
  2634 	_asm xor ebx, ebx
       
  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
       
  2642 	_asm pop edi
       
  2643 	_asm pop esi
       
  2644 	_asm pop ebp
       
  2645 	_asm pop ebx
       
  2646 	_asm ret
       
  2647 	}
       
  2648 
       
  2649 
       
  2650 
       
  2651 
       
  2652 __NAKED__ EXPORT_C TRealX TRealX::operator++(TInt)
       
  2653 /**
       
  2654 Returns this extended precision number before incrementing it by one.
       
  2655 
       
  2656 This is also referred to as a postfix operator. 
       
  2657 
       
  2658 @return A reference to this object.
       
  2659 
       
  2660 @panic MATHX KErrOverflow if the operation results in overflow.
       
  2661 @panic MATHX KErrUnderflow if  the operation results in underflow.
       
  2662 */
       
  2663 	{
       
  2664 	// post-increment
       
  2665 	// on entry ecx=this, [esp+4]=address of return value, [esp+8]=dummy int
       
  2666 	_asm push ebx				// save registers
       
  2667 	_asm push ebp
       
  2668 	_asm push esi
       
  2669 	_asm push edi
       
  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]
       
  2673 	_asm mov [edi], eax
       
  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
       
  2680 	_asm xor ebx, ebx
       
  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
       
  2688 	_asm pop edi
       
  2689 	_asm pop esi
       
  2690 	_asm pop ebp
       
  2691 	_asm pop ebx
       
  2692 	_asm ret 8
       
  2693 	}
       
  2694 
       
  2695 
       
  2696 
       
  2697 
       
  2698 __NAKED__ EXPORT_C TRealX& TRealX::operator--()
       
  2699 /**
       
  2700 Decrements this extended precision number by one,
       
  2701 and then returns a reference to it.
       
  2702 
       
  2703 This is also referred to as a prefix operator. 
       
  2704 
       
  2705 @return A reference to this object.
       
  2706 
       
  2707 @panic MATHX KErrOverflow if the operation results in overflow.
       
  2708 @panic MATHX KErrUnderflow if  the operation results in underflow.
       
  2709 */
       
  2710 	{
       
  2711 	// pre-decrement
       
  2712 	// on entry ecx=this, return this in eax
       
  2713 	_asm push ebx				// save registers
       
  2714 	_asm push ebp
       
  2715 	_asm push esi
       
  2716 	_asm push edi
       
  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
       
  2720 	_asm xor ebx, ebx
       
  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
       
  2728 	_asm pop edi
       
  2729 	_asm pop esi
       
  2730 	_asm pop ebp
       
  2731 	_asm pop ebx
       
  2732 	_asm ret
       
  2733 	}
       
  2734 
       
  2735 
       
  2736 
       
  2737 
       
  2738 __NAKED__ EXPORT_C TRealX TRealX::operator--(TInt)
       
  2739 /**
       
  2740 Returns this extended precision number before decrementing it by one.
       
  2741 
       
  2742 This is also referred to as a postfix operator. 
       
  2743 
       
  2744 @return A reference to this object.
       
  2745 
       
  2746 @panic MATHX KErrOverflow if the operation results in overflow.
       
  2747 @panic MATHX KErrUnderflow if  the operation results in underflow.
       
  2748 */
       
  2749 	{
       
  2750 	// post-decrement
       
  2751 	// on entry ecx=this, [esp+4]=address of return value, [esp+8]=dummy int
       
  2752 	_asm push ebx				// save registers
       
  2753 	_asm push ebp
       
  2754 	_asm push esi
       
  2755 	_asm push edi
       
  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]
       
  2759 	_asm mov [edi], eax
       
  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
       
  2766 	_asm xor ebx, ebx
       
  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
       
  2774 	_asm pop edi
       
  2775 	_asm pop esi
       
  2776 	_asm pop ebp
       
  2777 	_asm pop ebx
       
  2778 	_asm ret 8
       
  2779 	}
       
  2780 
       
  2781 
       
  2782 
       
  2783 
       
  2784 __NAKED__ EXPORT_C TRealX TRealX::operator+(const TRealX& /*aVal*/) const
       
  2785 /**
       
  2786 Adds an extended precision value to this extended precision number.
       
  2787 
       
  2788 @param aVal The extended precision value to be added. 
       
  2789 
       
  2790 @return An extended precision object containing the result.
       
  2791 
       
  2792 @panic MATHX KErrOverflow if the operation results in overflow.
       
  2793 @panic MATHX KErrUnderflow if  the operation results in underflow.
       
  2794 */
       
  2795 	{
       
  2796 	// on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
       
  2797 	_asm push ebx				// save registers
       
  2798 	_asm push ebp
       
  2799 	_asm push esi
       
  2800 	_asm push edi
       
  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
       
  2811 	_asm test eax, eax
       
  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
       
  2815 	_asm pop esi
       
  2816 	_asm pop ebp
       
  2817 	_asm pop ebx
       
  2818 	_asm ret 8
       
  2819 	}
       
  2820 
       
  2821 
       
  2822 
       
  2823 
       
  2824 __NAKED__ EXPORT_C TRealX TRealX::operator-(const TRealX& /*aVal*/) const
       
  2825 /**
       
  2826 Subtracts an extended precision value from this extended precision number. 
       
  2827 
       
  2828 @param aVal The extended precision value to be subtracted. 
       
  2829 
       
  2830 @return An extended precision object containing the result. 
       
  2831 
       
  2832 @panic MATHX KErrOverflow if the operation results in overflow.
       
  2833 @panic MATHX KErrUnderflow if  the operation results in underflow.
       
  2834 */
       
  2835 	{
       
  2836 	// on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
       
  2837 	_asm push ebx				// save registers
       
  2838 	_asm push ebp
       
  2839 	_asm push esi
       
  2840 	_asm push edi
       
  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
       
  2851 	_asm test eax, eax
       
  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
       
  2855 	_asm pop esi
       
  2856 	_asm pop ebp
       
  2857 	_asm pop ebx
       
  2858 	_asm ret 8
       
  2859 	}
       
  2860 
       
  2861 
       
  2862 
       
  2863 
       
  2864 __NAKED__ EXPORT_C TRealX TRealX::operator*(const TRealX& /*aVal*/) const
       
  2865 /**
       
  2866 Multiplies this extended precision number by an extended precision value.
       
  2867 
       
  2868 @param aVal The extended precision value to be used as the multiplier. 
       
  2869 
       
  2870 @return An extended precision object containing the result. 
       
  2871 
       
  2872 @panic MATHX KErrOverflow if the operation results in overflow.
       
  2873 @panic MATHX KErrUnderflow if  the operation results in underflow.
       
  2874 */
       
  2875 	{
       
  2876 	// on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
       
  2877 	_asm push ebx				// save registers
       
  2878 	_asm push ebp
       
  2879 	_asm push esi
       
  2880 	_asm push edi
       
  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
       
  2891 	_asm test eax, eax
       
  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
       
  2895 	_asm pop esi
       
  2896 	_asm pop ebp
       
  2897 	_asm pop ebx
       
  2898 	_asm ret 8
       
  2899 	}
       
  2900 
       
  2901 
       
  2902 
       
  2903 
       
  2904 __NAKED__ EXPORT_C TRealX TRealX::operator/(const TRealX& /*aVal*/) const
       
  2905 /**
       
  2906 Divides this extended precision number by an extended precision value.
       
  2907 
       
  2908 @param aVal The extended precision value to be used as the divisor. 
       
  2909 
       
  2910 @return An extended precision object containing the result. 
       
  2911 
       
  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.
       
  2915 */
       
  2916 	{
       
  2917 	// on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
       
  2918 	_asm push ebx				// save registers
       
  2919 	_asm push ebp
       
  2920 	_asm push esi
       
  2921 	_asm push edi
       
  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
       
  2932 	_asm test eax, eax
       
  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
       
  2936 	_asm pop esi
       
  2937 	_asm pop ebp
       
  2938 	_asm pop ebx
       
  2939 	_asm ret 8
       
  2940 	}
       
  2941 
       
  2942 
       
  2943 
       
  2944 
       
  2945 __NAKED__ EXPORT_C TRealX TRealX::operator%(const TRealX& /*aVal*/) const
       
  2946 /**
       
  2947 Modulo-divides this extended precision number by an extended precision value.
       
  2948 
       
  2949 @param aVal The extended precision value to be used as the divisor. 
       
  2950 
       
  2951 @return An extended precision object containing the result. 
       
  2952 
       
  2953 @panic MATHX KErrTotalLossOfPrecision if precision is lost.
       
  2954 @panic MATHX KErrUnderflow if the operation results in underflow.
       
  2955 */
       
  2956 	{
       
  2957 	// on entry ecx=this, [esp+4]=address of return value, [esp+8]=address of aVal
       
  2958 	_asm push ebx				// save registers
       
  2959 	_asm push ebp
       
  2960 	_asm push esi
       
  2961 	_asm push edi
       
  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
       
  2972 	_asm test eax, eax
       
  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
       
  2976 	_asm pop esi
       
  2977 	_asm pop ebp
       
  2978 	_asm pop ebx
       
  2979 	_asm ret 8
       
  2980 	}
       
  2981 
       
  2982 
       
  2983 
       
  2984 
       
  2985 __NAKED__ EXPORT_C TInt TRealX::Add(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
       
  2986 /**
       
  2987 Adds an extended precision value to this extended precision number.
       
  2988 
       
  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. 
       
  2992 
       
  2993 @return KErrNone, if the operation is successful;
       
  2994         KErrOverflow, if the operation results in overflow;
       
  2995         KErrUnderflow, if the operation results in underflow. 
       
  2996 */
       
  2997 	{
       
  2998 	// on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
       
  2999 	_asm push ebx				// save registers
       
  3000 	_asm push ebp
       
  3001 	_asm push esi
       
  3002 	_asm push edi
       
  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
       
  3014 	_asm pop esi
       
  3015 	_asm pop ebp
       
  3016 	_asm pop ebx
       
  3017 	_asm ret 8					// return with error code in eax
       
  3018 	}
       
  3019 
       
  3020 
       
  3021 
       
  3022 
       
  3023 __NAKED__ EXPORT_C TInt TRealX::Sub(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
       
  3024 /**
       
  3025 Subtracts an extended precision value from this extended precision number.
       
  3026 
       
  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. 
       
  3030 
       
  3031 @return KErrNone, if the operation is successful;
       
  3032         KErrOverflow, if the operation results in overflow;
       
  3033         KErrUnderflow, if the operation results in underflow. 
       
  3034 */
       
  3035 	{
       
  3036 	// on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
       
  3037 	_asm push ebx				// save registers
       
  3038 	_asm push ebp
       
  3039 	_asm push esi
       
  3040 	_asm push edi
       
  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
       
  3052 	_asm pop esi
       
  3053 	_asm pop ebp
       
  3054 	_asm pop ebx
       
  3055 	_asm ret 8					// return with error code in eax
       
  3056 	}
       
  3057 
       
  3058 
       
  3059 
       
  3060 
       
  3061 __NAKED__ EXPORT_C TInt TRealX::Mult(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
       
  3062 /**
       
  3063 Multiplies this extended precision number by an extended precision value.
       
  3064 
       
  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. 
       
  3068 
       
  3069 @return KErrNone, if the operation is successful;
       
  3070         KErrOverflow, if the operation results in overflow;
       
  3071         KErrUnderflow, if the operation results in underflow. 
       
  3072 */
       
  3073 	{
       
  3074 	// on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
       
  3075 	_asm push ebx				// save registers
       
  3076 	_asm push ebp
       
  3077 	_asm push esi
       
  3078 	_asm push edi
       
  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
       
  3090 	_asm pop esi
       
  3091 	_asm pop ebp
       
  3092 	_asm pop ebx
       
  3093 	_asm ret 8					// return with error code in eax
       
  3094 	}
       
  3095 
       
  3096 
       
  3097 
       
  3098 
       
  3099 __NAKED__ EXPORT_C TInt TRealX::Div(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
       
  3100 /**
       
  3101 Divides this extended precision number by an extended precision value.
       
  3102 
       
  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.
       
  3106 
       
  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.
       
  3111 */
       
  3112 	{
       
  3113 	// on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
       
  3114 	_asm push ebx				// save registers
       
  3115 	_asm push ebp
       
  3116 	_asm push esi
       
  3117 	_asm push edi
       
  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
       
  3129 	_asm pop esi
       
  3130 	_asm pop ebp
       
  3131 	_asm pop ebx
       
  3132 	_asm ret 8					// return with error code in eax
       
  3133 	}
       
  3134 
       
  3135 
       
  3136 
       
  3137 
       
  3138 __NAKED__ EXPORT_C TInt TRealX::Mod(TRealX& /*aResult*/, const TRealX& /*aVal*/) const
       
  3139 /**
       
  3140 Modulo-divides this extended precision number by an extended precision value.
       
  3141 
       
  3142 @param aResult On return, a reference to an extended precision object
       
  3143                containing the result of the operation.
       
  3144 
       
  3145 @param aVal    The extended precision value to be used as the divisor. 
       
  3146 
       
  3147 @return KErrNone, if the operation is successful;
       
  3148         KErrTotalLossOfPrecision, if precision is lost;
       
  3149         KErrUnderflow, if the operation results in underflow.
       
  3150 */
       
  3151 	{
       
  3152 	// on entry ecx=this, [esp+4]=address of aResult, [esp+8]=address of aVal
       
  3153 	_asm push ebx				// save registers
       
  3154 	_asm push ebp
       
  3155 	_asm push esi
       
  3156 	_asm push edi
       
  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
       
  3168 	_asm pop esi
       
  3169 	_asm pop ebp
       
  3170 	_asm pop ebx
       
  3171 	_asm ret 8					// return with error code in eax
       
  3172 	}
       
  3173 
       
  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)
       
  3181 	{
       
  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
       
  3186 	_asm test ebx, ebx
       
  3187 	_asm jz short fpcmp1		// if infinity, process normally
       
  3188 	fpcmpunord:					// come here if unordered
       
  3189 	_asm mov eax, 8				// return 8
       
  3190 	_asm ret
       
  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]
       
  3194 	_asm mov ebp, [esi]
       
  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
       
  3199 	_asm test ebp, ebp
       
  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
       
  3207 	_asm test al, 1
       
  3208 	_asm jnz short fpcmp4		// branch if different
       
  3209 	_asm push ecx
       
  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
       
  3213 	_asm pop ecx
       
  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
       
  3222 	fpcmp0:
       
  3223 	_asm mov eax, 2				// numbers exactly equal
       
  3224 	_asm ret
       
  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
       
  3231 	fpcmp4a:
       
  3232 	_asm ret
       
  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
       
  3238 	fpcmp5a:
       
  3239 	_asm ret
       
  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
       
  3247 	fpcmpop1z2n:
       
  3248 	_asm ret
       
  3249 	}
       
  3250 
       
  3251 
       
  3252 
       
  3253 
       
  3254 __NAKED__ EXPORT_C TRealX::TRealXOrder TRealX::Compare(const TRealX& /*aVal*/) const
       
  3255 /**
       
  3256 */
       
  3257 	{
       
  3258 	// On entry ecx=this, [esp+4]=address of aVal
       
  3259 	_asm push ebx				// save registers
       
  3260 	_asm push ebp
       
  3261 	_asm push esi
       
  3262 	_asm push edi
       
  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
       
  3268 	_asm pop edi
       
  3269 	_asm pop esi
       
  3270 	_asm pop ebp
       
  3271 	_asm pop ebx
       
  3272 	_asm ret 4
       
  3273 	}
       
  3274 
       
  3275 
       
  3276 
       
  3277 
       
  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
       
  3281