os/kernelhwsrv/kernel/eka/euser/epoc/win32/uc_realx.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     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