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