symport/e32/euser/epoc/x86/uc_realx.cia
changeset 1 0a7b44b10206
child 2 806186ab5e14
equal deleted inserted replaced
0:c55016431358 1:0a7b44b10206
       
     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 "Symbian Foundation License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.symbianfoundation.org/legal/sfl-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