os/kernelhwsrv/kernel/eka/euser/epoc/arm/uc_realx.cia
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\euser\epoc\arm\uc_realx.cia
    15 // 
    16 //
    17 
    18 #include <e32cia.h>
    19 #include <u32std.h>
    20 #include <e32math.h>
    21 #ifdef __USE_VFP_MATH
    22 #include <arm_vfp.h>
    23 #endif
    24 
    25 #if defined(__USE_VFP_MATH) && !defined(__CPU_HAS_VFP)
    26 #error	__USE_VFP_MATH was defined but not __CPU_HAS_VFP - impossible combination, check variant.mmh 
    27 #endif	
    28 
    29 #ifndef __EABI_CTORS__
    30 __NAKED__ EXPORT_C TRealX::TRealX()
    31 /**
    32 Constructs a default extended precision object.
    33 
    34 This sets the value to zero.
    35 */
    36 	{
    37 	asm("mov r1, #0 ");
    38 	asm("str r1, [r0] ");
    39 	asm("str r1, [r0, #4] ");
    40 	asm("str r1, [r0, #8] ");
    41 	__JUMP(,lr);
    42 	}
    43 
    44 
    45 
    46 
    47 __NAKED__ EXPORT_C TRealX::TRealX(TUint /*anExp*/, TUint /*aMantHi*/, TUint /*aMantLo*/)
    48 /**
    49 Constructs an extended precision object from an explicit exponent and
    50 a 64 bit mantissa.
    51 
    52 @param anExp   The exponent 
    53 @param aMantHi The high order 32 bits of the 64 bit mantissa 
    54 @param aMantLo The low order 32 bits of the 64 bit mantissa 
    55 */
    56 	{
    57 	asm("str r1, [r0, #8] ");
    58 	asm("str r2, [r0, #4] ");
    59 	asm("str r3, [r0, #0] ");
    60 	__JUMP(,lr);
    61 	}
    62 #endif
    63 
    64 
    65 
    66 
    67 
    68 __NAKED__ EXPORT_C TInt TRealX::Set(TInt /*anInt*/)
    69 /**
    70 Gives this extended precision object a new value taken
    71 from a signed integer.
    72 
    73 @param anInt The signed integer value.
    74 
    75 @return KErrNone, always.
    76 */
    77 	{
    78 	asm("stmfd sp!, {lr} ");
    79 	asm("mov r2, r1 ");
    80 	asm("bl ConvertIntToTRealX ");
    81 	asm("stmia r0, {r1,r2,r3} ");
    82 	asm("mov r0, #0 ");				// return KErrNone
    83 	__POPRET("");
    84 	}
    85 
    86 
    87 
    88 
    89 #ifndef __EABI_CTORS__
    90 __NAKED__ EXPORT_C TRealX::TRealX(TInt /*anInt*/)
    91 /**
    92 Constructs an extended precision object from a signed integer value.
    93 
    94 @param anInt The signed integer value.
    95 */
    96 	{
    97 	// fall through
    98 	}
    99 #endif
   100 
   101 
   102 
   103 
   104 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TInt /*anInt*/)
   105 /**
   106 Assigns the specified signed integer value to this extended precision object.
   107 
   108 @param anInt The signed integer value.
   109 
   110 @return A reference to this extended precision object.
   111 */
   112 	{
   113 	asm("stmfd sp!, {lr} ");
   114 	asm("mov r2, r1 ");
   115 	asm("bl ConvertIntToTRealX ");
   116 	asm("stmia r0, {r1,r2,r3} ");
   117 	__POPRET("");
   118 
   119 	asm("ConvertIntToTRealX: ");
   120 	asm("cmp r2, #0 ");
   121 	asm("movpl r3, #0 ");				// if int>0, r3=0
   122 	asm("beq ConvertIntToTRealX0 ");	// if int=0, return 0
   123 	asm("movmi r3, #1 ");				// if int<0, r3=1
   124 	asm("rsbmi r2, r2, #0 ");			// if int -ve, negate it
   125 	asm("orr r3, r3, #0x001E0000 ");
   126 	asm("orr r3, r3, #0x80000000 ");	// r3=exponent 801E + sign bit
   127 #ifdef __CPU_ARM_HAS_CLZ
   128 	CLZ(12,2);
   129 	asm("mov r2, r2, lsl r12 ");
   130 	asm("sub r3, r3, r12, lsl #16 ");
   131 #else
   132 	asm("cmp r2, #0x10000 ");			// normalise mantissa, decrementing exponent as needed
   133 	asm("movcc r2, r2, lsl #16 ");
   134 	asm("subcc r3, r3, #0x100000 ");
   135 	asm("cmp r2, #0x1000000 ");
   136 	asm("movcc r2, r2, lsl #8 ");
   137 	asm("subcc r3, r3, #0x080000 ");
   138 	asm("cmp r2, #0x10000000 ");
   139 	asm("movcc r2, r2, lsl #4 ");
   140 	asm("subcc r3, r3, #0x040000 ");
   141 	asm("cmp r2, #0x40000000 ");
   142 	asm("movcc r2, r2, lsl #2 ");
   143 	asm("subcc r3, r3, #0x020000 ");
   144 	asm("cmp r2, #0x80000000 ");
   145 	asm("movcc r2, r2, lsl #1 ");
   146 	asm("subcc r3, r3, #0x010000 ");
   147 #endif
   148 	asm("ConvertIntToTRealX0: ");
   149 	asm("mov r1, #0 ");					// low order word of mantissa = 0
   150 	__JUMP(,lr);
   151 	}
   152 
   153 
   154 
   155 
   156 __NAKED__ EXPORT_C TInt TRealX::Set(const TInt64& /*anInt*/)
   157 /**
   158 Gives this extended precision object a new value taken from
   159 a 64 bit integer.
   160 
   161 @param anInt The 64 bit integer value.
   162 
   163 @return KErrNone, always.
   164 */
   165 	{
   166 	asm("stmfd sp!, {lr} ");
   167 	asm("ldmia r1, {r1,r2} ");
   168 	asm("bl ConvertInt64ToTRealX ");
   169 	asm("stmia r0, {r1,r2,r3} ");
   170 	asm("mov r0, #0 ");					// return KErrNone
   171 	__POPRET("");
   172 	}
   173 
   174 
   175 
   176 
   177 #ifndef __EABI_CTORS__
   178 __NAKED__ EXPORT_C TRealX::TRealX(const TInt64& /*anInt*/)
   179 /**
   180 Constructs an extended precision object from a 64 bit integer.
   181 
   182 @param anInt A reference to a 64 bit integer. 
   183 */
   184 	{
   185 	// fall through
   186 	}
   187 #endif
   188 
   189 
   190 
   191 
   192 __NAKED__ EXPORT_C TRealX& TRealX::operator=(const TInt64& /*anInt*/)
   193 /**
   194 Assigns the specified 64 bit integer value to this extended precision object.
   195 
   196 @param anInt A reference to a 64 bit integer. 
   197 
   198 @return A reference to this extended precision object.
   199 */
   200 	{
   201 	asm("stmfd sp!, {lr} ");
   202 	asm("ldmia r1, {r1,r2} ");
   203 	asm("bl ConvertInt64ToTRealX ");
   204 	asm("stmia r0, {r1,r2,r3} ");
   205 	__POPRET("");
   206 
   207 	asm("ConvertInt64ToTRealX: ");
   208 	asm("movs r3, r2, lsr #31 ");		// sign bit into r3 bit 0
   209 	asm("beq ConvertInt64ToTRealX1 ");	// skip if plus
   210 	asm("rsbs r1, r1, #0 ");			// take absolute value
   211 	asm("rsc r2, r2, #0 ");
   212 	asm("ConvertInt64ToTRealX1: ");
   213 	asm("cmp r2, #0 ");					// does it fit into 32 bits?
   214 	asm("moveq r2, r1 ");				// if it does, do 32 bit conversion
   215 	asm("beq ConvertUintToTRealX1 ");
   216 #ifdef __CPU_ARM_HAS_CLZ
   217 	CLZ(12,2);
   218 	asm("mov r2, r2, lsl r12 ");
   219 	asm("rsb r12, r12, #32 ");
   220 	asm("orr r2, r2, r1, lsr r12 ");
   221 	asm("rsb r12, r12, #32 ");
   222 #else
   223 	asm("mov r12, #32 ");				// 32-number of left-shifts needed to normalise
   224 	asm("cmp r2, #0x10000 ");			// calculate number required
   225 	asm("movcc r2, r2, lsl #16 ");
   226 	asm("subcc r12, r12, #16 ");
   227 	asm("cmp r2, #0x1000000 ");
   228 	asm("movcc r2, r2, lsl #8 ");
   229 	asm("subcc r12, r12, #8 ");
   230 	asm("cmp r2, #0x10000000 ");
   231 	asm("movcc r2, r2, lsl #4 ");
   232 	asm("subcc r12, r12, #4 ");
   233 	asm("cmp r2, #0x40000000 ");
   234 	asm("movcc r2, r2, lsl #2 ");
   235 	asm("subcc r12, r12, #2 ");
   236 	asm("cmp r2, #0x80000000 ");
   237 	asm("movcc r2, r2, lsl #1 ");
   238 	asm("subcc r12, r12, #1 ");			// r2 is now normalised
   239 	asm("orr r2, r2, r1, lsr r12 ");	// shift r1 left into r2
   240 	asm("rsb r12, r12, #32 ");
   241 #endif
   242 	asm("mov r1, r1, lsl r12 ");
   243 	asm("add r3, r3, #0x80000000 ");	// exponent = 803E-r12
   244 	asm("add r3, r3, #0x003E0000 ");
   245 	asm("sub r3, r3, r12, lsl #16 ");
   246 	__JUMP(,lr);
   247 	}
   248 
   249 
   250 
   251 
   252 __NAKED__ EXPORT_C TInt TRealX::Set(TUint /*anInt*/)
   253 /**
   254 Gives this extended precision object a new value taken from
   255 an unsigned integer.
   256 
   257 @param The unsigned integer value.
   258 
   259 @return KErrNone, always.
   260 */
   261 	{
   262 	asm("stmfd sp!, {lr} ");
   263 	asm("mov r2, r1 ");
   264 	asm("bl ConvertUintToTRealX ");
   265 	asm("stmia r0, {r1,r2,r3} ");
   266 	asm("mov r0, #0 ");				// return KErrNone
   267 	__POPRET("");
   268 	}
   269 
   270 
   271 
   272 
   273 #ifndef __EABI_CTORS__
   274 __NAKED__ EXPORT_C TRealX::TRealX(TUint /*anInt*/)
   275 /**
   276 Constructs an extended precision object from an unsigned integer value.
   277 
   278 @param anInt The unsigned integer value.
   279 */
   280 	{
   281 	// fall through
   282 	}
   283 #endif
   284 
   285 
   286 
   287 
   288 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TUint /*anInt*/)
   289 /**
   290 Assigns the specified unsigned integer value to this extended precision object.
   291 
   292 @param anInt The unsigned integer value.
   293 
   294 @return A reference to this extended precision object.
   295 */
   296 	{
   297 	asm("stmfd sp!, {lr} ");
   298 	asm("mov r2, r1 ");
   299 	asm("bl ConvertUintToTRealX ");
   300 	asm("stmia r0, {r1,r2,r3} ");
   301 	__POPRET("");
   302 
   303 	asm("ConvertUintToTRealX: ");
   304 	asm("mov r3, #0 ");
   305 	asm("ConvertUintToTRealX1: ");
   306 	asm("cmp r2, #0 ");					// check for zero
   307 	asm("beq ConvertUintToTRealX0 ");
   308 	asm("orr r3, r3, #0x001E0000 ");
   309 	asm("orr r3, r3, #0x80000000 ");	// r3=exponent 801E
   310 #ifdef __CPU_ARM_HAS_CLZ
   311 	CLZ(12,2);
   312 	asm("mov r2, r2, lsl r12 ");
   313 	asm("sub r3, r3, r12, lsl #16 ");
   314 #else
   315 	asm("cmp r2, #0x10000 ");			// normalise mantissa, decrementing exponent as needed
   316 	asm("movcc r2, r2, lsl #16 ");
   317 	asm("subcc r3, r3, #0x100000 ");
   318 	asm("cmp r2, #0x1000000 ");
   319 	asm("movcc r2, r2, lsl #8 ");
   320 	asm("subcc r3, r3, #0x080000 ");
   321 	asm("cmp r2, #0x10000000 ");
   322 	asm("movcc r2, r2, lsl #4 ");
   323 	asm("subcc r3, r3, #0x040000 ");
   324 	asm("cmp r2, #0x40000000 ");
   325 	asm("movcc r2, r2, lsl #2 ");
   326 	asm("subcc r3, r3, #0x020000 ");
   327 	asm("cmp r2, #0x80000000 ");
   328 	asm("movcc r2, r2, lsl #1 ");
   329 	asm("subcc r3, r3, #0x010000 ");
   330 #endif
   331 	asm("ConvertUintToTRealX0: ");
   332 	asm("mov r1, #0 ");					// low order word of mantissa = 0
   333 	__JUMP(,lr);
   334 	}
   335 
   336 
   337 
   338 
   339 __NAKED__ EXPORT_C void TRealX::SetZero(TBool /*aNegative*/)
   340 /**
   341 Sets the value of this extended precision object to zero.
   342 
   343 @param aNegative ETrue, the value is a negative zero;
   344                  EFalse, the value is a positive zero, this is the default.
   345 */
   346 	{
   347 	asm("mov r3, #0 ");
   348 	asm("cmp r1, #0 ");
   349 	asm("movne r3, #1 ");
   350 	asm("mov r2, #0 ");
   351 	asm("mov r1, #0 ");
   352 	asm("stmia r0, {r1,r2,r3} ");
   353 	__JUMP(,lr);
   354 	}
   355 
   356 
   357 
   358 
   359 __NAKED__ EXPORT_C void TRealX::SetNaN()
   360 /**
   361 Sets the value of this extended precision object to 'not a number'.
   362 */
   363 	{
   364 	asm("ldr r3, [pc, #__RealIndefiniteExponent-.-8] ");
   365 	asm("mov r2, #0xC0000000 ");
   366 	asm("mov r1, #0 ");
   367 	asm("stmia r0, {r1,r2,r3} ");
   368 	__JUMP(,lr);
   369 	asm("__RealIndefiniteExponent: ");
   370 	asm(".word 0xFFFF0001 ");
   371 	}
   372 
   373 
   374 
   375 
   376 
   377 __NAKED__ EXPORT_C void TRealX::SetInfinite(TBool /*aNegative*/)
   378 /**
   379 Sets the value of this extended precision object to infinity.
   380 
   381 @param aNegative ETrue, the value is a negative zero;
   382                  EFalse, the value is a positive zero.
   383 */
   384 	{
   385 	asm("ldr r3, [pc, #__InfiniteExponent-.-8] ");
   386 	asm("cmp r1, #0 ");
   387 	asm("orrne r3, r3, #1 ");
   388 	asm("mov r2, #0x80000000 ");
   389 	asm("mov r1, #0 ");
   390 	asm("stmia r0, {r1,r2,r3} ");
   391 	__JUMP(,lr);
   392 	asm("__InfiniteExponent: ");
   393 	asm(".word 0xFFFF0000 ");
   394 	}
   395 
   396 
   397 
   398 
   399 __NAKED__ EXPORT_C TBool TRealX::IsZero() const
   400 /**
   401 Determines whether the extended precision value is zero.
   402 
   403 @return True, if the extended precision value is zero, false, otherwise.
   404 */
   405 	{
   406 	asm("ldr r1, [r0, #8] ");	// get exponent word
   407 	asm("mov r0, #0 ");			// default return value is 0
   408 	asm("cmp r1, #0x10000 ");	// is exponent=0 ?
   409 	asm("movcc r0, #1 ");		// if so return 1
   410 	__JUMP(,lr);
   411 	}
   412 
   413 
   414 
   415 
   416 __NAKED__ EXPORT_C TBool TRealX::IsNaN() const
   417 /**
   418 Determines whether the extended precision value is 'not a number'.
   419 
   420 @return True, if the extended precision value is 'not a number',
   421         false, otherwise.
   422 */
   423 	{
   424 	asm("ldmia r0, {r1,r2,r3} ");
   425 	asm("mov r0, #0 ");					// default return value is 0
   426 	asm("cmn r3, #0x10000 ");			// check for exponent 65535
   427 	asm("bcc 1f ");						// branch if not
   428 	asm("cmp r2, #0x80000000 ");		// check if infinity
   429 	asm("cmpeq r1, #0 ");
   430 	asm("movne r0, #1 ");				// if not, return 1
   431 	asm("1: ");
   432 	__JUMP(,lr);
   433 	}
   434 
   435 
   436 
   437 
   438 __NAKED__ EXPORT_C TBool TRealX::IsInfinite() const
   439 /**
   440 Determines whether the extended precision value has a finite value.
   441 
   442 @return True, if the extended precision value is finite,
   443         false, if the value is 'not a number' or is infinite,
   444 */
   445 	{
   446 	asm("ldmia r0, {r1,r2,r3} ");
   447 	asm("mov r0, #0 ");						// default return value is 0
   448 	asm("cmn r3, #0x10000 ");				// check for exponent 65535
   449 	asm("bcc 1f ");							// branch if not
   450 	asm("cmp r2, #0x80000000 ");			// check if infinity
   451 	asm("cmpeq r1, #0 ");
   452 	asm("moveq r0, #1 ");					// if it is, return 1
   453 	asm("1: ");
   454 	__JUMP(,lr);
   455 	}
   456 
   457 
   458 
   459 
   460 __NAKED__ EXPORT_C TBool TRealX::IsFinite() const
   461 /**
   462 Determines whether the extended precision value has a finite value.
   463 
   464 @return True, if the extended precision value is finite,
   465         false, if the value is 'not a number' or is infinite,
   466 */
   467 	{
   468 	asm("ldr r1, [r0, #8] ");	// get exponent word
   469 	asm("mov r0, #0 ");			// default return value is 0
   470 	asm("cmn r1, #0x10000 ");	// is exponent=65535 (infinity or NaN) ?
   471 	asm("movcc r0, #1 ");		// if not return 1
   472 	__JUMP(,lr);
   473 	}
   474 
   475 
   476 
   477 
   478 #ifndef __EABI_CTORS__
   479 __NAKED__ EXPORT_C TRealX::TRealX(TReal32 /*aReal*/) __SOFTFP
   480 /**
   481 Constructs an extended precision object from
   482 a single precision floating point number.
   483 
   484 @param aReal The single precision floating point value.
   485 */
   486 	{
   487 	// fall through
   488 	}
   489 #endif
   490 
   491 
   492 
   493 
   494 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TReal32 /*aReal*/) __SOFTFP
   495 /**
   496 Assigns the specified single precision floating point number to
   497 this extended precision object.
   498 
   499 @param aReal The single precision floating point value.
   500 
   501 @return A reference to this extended precision object.
   502 */
   503 	{
   504 	asm("stmfd sp!, {lr} ");
   505 	asm("bl ConvertTReal32ToTRealX ");
   506 	asm("stmia r0, {r1,r2,r3} ");
   507 	__POPRET("");
   508 	}
   509 
   510 
   511 
   512 
   513 __NAKED__ EXPORT_C TInt TRealX::Set(TReal32 /*aReal*/) __SOFTFP
   514 /**
   515 Gives this extended precision object a new value taken from
   516 a single precision floating point number.
   517 
   518 @param aReal The single precision floating point value. 
   519 
   520 @return KErrNone, if a valid number;
   521         KErrOverflow, if the number is infinite;
   522         KErrArgument, if not a number.
   523 */
   524 	{
   525 	// aReal is in r1 on entry
   526 	// sign in bit 31, exponent in 30-23, mantissa (non-integer bits) in 22-0
   527 	asm("stmfd sp!, {lr} ");
   528 	asm("bl ConvertTReal32ToTRealX ");
   529 	asm("stmia r0, {r1,r2,r3} ");
   530 	asm("cmn r3, #0x10000 ");			// check for infinity or NaN
   531 	asm("movcc r0, #0 ");				// if neither, return KErrNone
   532 	asm("bcc trealx_set_treal32_0 ");
   533 	asm("cmp r2, #0x80000000 ");		// check for infinity
   534 	asm("mvneq r0, #8 ");				// if so, return KErrOverflow
   535 	asm("mvnne r0, #5 ");				// else return KErrArgument
   536 	asm("trealx_set_treal32_0: ");
   537 	__POPRET("");
   538 
   539 	// Convert 32-bit real in r1 to TRealX in r1,r2,r3
   540 	// r0 unmodified, r1,r2,r3,r12 modified
   541 	asm("ConvertTReal32ToTRealX: ");
   542 	asm("mov r3, r1, lsr #7 ");			// r3 bits 16-31 = TReal32 exponent
   543 	asm("ands r3, r3, #0x00FF0000 ");
   544 	asm("mov r2, r1, lsl #8 ");			// r2 = TReal32 mantissa << 8, bit 31 not yet in
   545 	asm("orrne r2, r2, #0x80000000 ");	// if not zero/denormal, put in implied integer bit
   546 	asm("orr r3, r3, r1, lsr #31 ");	// r3 bit 0 = sign bit
   547 	asm("mov r1, #0 ");					// low word of mantissa = 0
   548 	asm("beq ConvertTReal32ToTRealX0 ");	// branch if zero/denormal
   549 	asm("cmp r3, #0x00FF0000 ");		// check for infinity or NaN
   550 	asm("orrcs r3, r3, #0xFF000000 ");	// if infinity or NaN, exponent = FFFF
   551 	asm("addcc r3, r3, #0x7F000000 ");	// else exponent = TReal32 exponent + 7F80
   552 	asm("addcc r3, r3, #0x00800000 ");
   553 	__JUMP(,lr);
   554 	asm("ConvertTReal32ToTRealX0: ");	// come here if zero or denormal
   555 	asm("adds r2, r2, r2 ");			// shift mantissa left one more and check if zero
   556 	__JUMP(eq,lr);
   557 	asm("add r3, r3, #0x7F000000 ");	// else exponent = 7F80 (highest denormal exponent)
   558 	asm("add r3, r3, #0x00800000 ");
   559 #ifdef __CPU_ARM_HAS_CLZ
   560 	CLZ(12,2);
   561 	asm("mov r2, r2, lsl r12 ");
   562 	asm("sub r3, r3, r12, lsl #16 ");
   563 #else
   564 	asm("cmp r2, #0x10000 ");			// normalise mantissa, decrementing exponent as needed
   565 	asm("movcc r2, r2, lsl #16 ");
   566 	asm("subcc r3, r3, #0x100000 ");
   567 	asm("cmp r2, #0x1000000 ");
   568 	asm("movcc r2, r2, lsl #8 ");
   569 	asm("subcc r3, r3, #0x080000 ");
   570 	asm("cmp r2, #0x10000000 ");
   571 	asm("movcc r2, r2, lsl #4 ");
   572 	asm("subcc r3, r3, #0x040000 ");
   573 	asm("cmp r2, #0x40000000 ");
   574 	asm("movcc r2, r2, lsl #2 ");
   575 	asm("subcc r3, r3, #0x020000 ");
   576 	asm("cmp r2, #0x80000000 ");
   577 	asm("movcc r2, r2, lsl #1 ");
   578 	asm("subcc r3, r3, #0x010000 ");
   579 #endif
   580 	__JUMP(,lr);
   581 	}
   582 
   583 
   584 
   585 
   586 #ifndef __EABI_CTORS__
   587 __NAKED__ EXPORT_C TRealX::TRealX(TReal64 /*aReal*/) __SOFTFP
   588 /**
   589 Constructs an extended precision object from
   590 a double precision floating point number.
   591 
   592 @param aReal The double precision floating point value.
   593 */
   594 	{
   595 	// fall through
   596 	}
   597 #endif
   598 
   599 
   600 
   601 
   602 __NAKED__ EXPORT_C TRealX& TRealX::operator=(TReal64 /*aReal*/) __SOFTFP
   603 /**
   604 Assigns the specified double precision floating point number to
   605 this extended precision object.
   606 
   607 @param aReal The double precision floating point value.
   608 
   609 @return A reference to this extended precision object.
   610 */
   611 	{
   612 	asm("stmfd sp!, {lr} ");
   613 	asm("bl ConvertTReal64ToTRealX ");
   614 	asm("stmia r0, {r1,r2,r3} ");
   615 	__POPRET("");
   616 	}
   617 
   618 
   619 
   620 
   621 __NAKED__ EXPORT_C TInt TRealX::Set(TReal64 /*aReal*/) __SOFTFP
   622 /**
   623 Gives this extended precision object a new value taken from
   624 a double precision floating point number.
   625 
   626 @param aReal The double precision floating point value. 
   627 
   628 @return KErrNone, if a valid number;
   629         KErrOverflow, if the number is infinite;
   630         KErrArgument, if not a number.
   631 */
   632 	{
   633 	// aReal is in r1,r2 on entry
   634 	// sign in bit 31 of r1, exponent in 30-20 of r1
   635 	// mantissa (non-integer bits) in 19-0 of r1 (high) and r2 (low)
   636 	asm("stmfd sp!, {lr} ");
   637 	asm("bl ConvertTReal64ToTRealX ");
   638 	asm("stmia r0, {r1,r2,r3} ");
   639 	asm("cmn r3, #0x10000 ");			// check for infinity or NaN
   640 	asm("movcc r0, #0 ");				// if neither, return KErrNone
   641 	asm("bcc trealx_set_treal64_0 ");
   642 	asm("cmp r2, #0x80000000 ");		// check for infinity
   643 	asm("cmpeq r1, #0 ");
   644 	asm("mvneq r0, #8 ");				// if so, return KErrOverflow
   645 	asm("mvnne r0, #5 ");				// else return KErrArgument
   646 	asm("trealx_set_treal64_0: ");
   647 	__POPRET("");
   648 
   649 	// convert TReal64 in r1,r2 in GCC and r2 and r3 in RVCT
   650 	// if __DOUBLE_WORDS_SWAPPED__ r1=sign,exp,high mant, r2=low mant
   651 	// else r1 unused , r2=low mant, r3=sign,exp,high mant (as a result of EABI alignment reqs)
   652 	// into TRealX in r1,r2,r3 (r2,r1=mant high,low r3=exp,flag,sign)
   653 	// r0 unmodified, r1,r2,r3,r12 modified
   654 	asm("ConvertTReal64ToTRealX: ");
   655 #ifdef __DOUBLE_WORDS_SWAPPED__
   656 	asm("mov r12, r2 ");				// ls word of mantissa into r12
   657 #else
   658 	asm("mov r12, r2 ");				// ls word of mantissa into r12
   659 	asm("mov r1, r3 ");
   660 #endif
   661 	asm("mov r3, r1, lsr #20 ");		// sign and exp into bottom 12 bits of r3
   662 	asm("mov r2, r1, lsl #11 ");		// left justify mantissa in r2,r1
   663 	asm("mov r3, r3, lsl #16 ");		// and into bits 16-27
   664 	asm("bics r3, r3, #0x08000000 ");	// remove sign, leaving exponent in bits 16-26
   665 	asm("orr r2, r2, r12, lsr #21 ");
   666 	asm("orrne r2, r2, #0x80000000 ");	// if not zero/denormal, put in implied integer bit
   667 	asm("orr r3, r3, r1, lsr #31 ");	// sign bit into bit 0 of r3
   668 	asm("mov r1, r12, lsl #11 ");
   669 	asm("beq ConvertTReal64ToTRealX0 ");	// branch if zero or denormal
   670 	asm("mov r12, r3, lsl #5 ");		// exponent into bits 21-31 of r12
   671 	asm("cmn r12, #0x00200000 ");		// check if exponent=7FF (infinity or NaN)
   672 	asm("addcs r3, r3, #0xF8000000 ");	// if so, result exponent=FFFF
   673 	asm("addcc r3, r3, #0x7C000000 ");	// else result exponent = TReal64 exponent + 7C00
   674 	__JUMP(,lr);
   675 	asm("ConvertTReal64ToTRealX0: ");	// come here if zero or denormal
   676 	asm("adds r1, r1, r1 ");			// shift mantissa left one more bit
   677 	asm("adcs r2, r2, r2 ");
   678 	asm("cmpeq r1, #0 ");				// and test for zero
   679 	__JUMP(eq,lr);
   680 	asm("add r3, r3, #0x7C000000 ");	// else exponent=7C00 (highest denormal exponent)
   681 	asm("cmp r2, #0 ");					// normalise - first check if r2=0
   682 	asm("moveq r2, r1 ");				// if so, shift up by 32
   683 	asm("moveq r1, #0 ");
   684 	asm("subeq r3, r3, #0x200000 ");	// and subtract 32 from exponent
   685 #ifdef __CPU_ARM_HAS_CLZ
   686 	CLZ(12,2);
   687 	asm("mov r2, r2, lsl r12 ");
   688 	asm("rsb r12, r12, #32 ");
   689 	asm("orr r2, r2, r1, lsr r12 ");
   690 	asm("rsb r12, r12, #32 ");
   691 #else
   692 	asm("mov r12, #32 ");				// 32-number of left-shifts needed to normalise
   693 	asm("cmp r2, #0x10000 ");			// calculate number required
   694 	asm("movcc r2, r2, lsl #16 ");
   695 	asm("subcc r12, r12, #16 ");
   696 	asm("cmp r2, #0x1000000 ");
   697 	asm("movcc r2, r2, lsl #8 ");
   698 	asm("subcc r12, r12, #8 ");
   699 	asm("cmp r2, #0x10000000 ");
   700 	asm("movcc r2, r2, lsl #4 ");
   701 	asm("subcc r12, r12, #4 ");
   702 	asm("cmp r2, #0x40000000 ");
   703 	asm("movcc r2, r2, lsl #2 ");
   704 	asm("subcc r12, r12, #2 ");
   705 	asm("cmp r2, #0x80000000 ");
   706 	asm("movcc r2, r2, lsl #1 ");
   707 	asm("subcc r12, r12, #1 ");			// r2 is now normalised
   708 	asm("orr r2, r2, r1, lsr r12 ");	// shift r1 left into r2
   709 	asm("rsb r12, r12, #32 ");
   710 #endif
   711 	asm("mov r1, r1, lsl r12 ");
   712 	asm("sub r3, r3, r12, lsl #16 ");	// exponent -= number of left shifts
   713 	__JUMP(,lr);
   714 	}
   715 
   716 
   717 
   718 
   719 
   720 __NAKED__ EXPORT_C TRealX::operator TInt() const
   721 /**
   722 Gets the extended precision value as a signed integer value.
   723 
   724 The operator returns:
   725 
   726 1. zero , if the extended precision value is not a number
   727 
   728 2. 0x7FFFFFFF, if the value is positive and too big to fit into a TInt.
   729 
   730 3. 0x80000000, if the value is negative and too big to fit into a TInt.
   731 */
   732 	{
   733 	asm("ldmia r0, {r1,r2,r3} ");		// get value into r1,r2,r3
   734 
   735 	asm("ConvertTRealXToInt: ");
   736 	asm("mov r12, #0x8000 ");			// r12=0x801E
   737 	asm("orr r12, r12, #0x001E ");
   738 	asm("subs r12, r12, r3, lsr #16 ");	// r12=801E-exponent
   739 	asm("bls ConvertTRealXToInt1 ");	// branch if exponent>=801E
   740 	asm("cmp r12, #31 ");				// test if exponent<7FFF
   741 	asm("movhi r0, #0 ");				// if so, underflow result to zero
   742 	__JUMP(hi,lr);
   743 	asm("mov r0, r2, lsr r12 ");		// shift mantissa right to form integer
   744 	asm("tst r3, #1 ");					// check sign bit
   745 	asm("rsbne r0, r0, #0 ");			// if negative, r0=-r0
   746 	__JUMP(,lr);
   747 	asm("ConvertTRealXToInt1: ");
   748 	asm("cmn r3, #0x10000 ");			// check for infinity or NaN
   749 	asm("bcc ConvertTRealXToInt2 ");	// branch if neither
   750 	asm("cmp r2, #0x80000000 ");		// check for infinity
   751 	asm("cmpeq r1, #0 ");
   752 	asm("movne r0, #0 ");				// if NaN, return 0
   753 	__JUMP(ne,lr);
   754 	asm("ConvertTRealXToInt2: ");
   755 	asm("mov r0, #0x80000000 ");		// return 0x80000000 if -ve overflow, 0x7FFFFFFF if +ve
   756 	asm("movs r3, r3, lsr #1 ");
   757 	asm("sbc r0, r0, #0 ");
   758 	__JUMP(,lr);
   759 	}
   760 
   761 
   762 
   763 
   764 __NAKED__ EXPORT_C TRealX::operator TUint() const
   765 /**
   766 Returns the extended precision value as an unsigned signed integer value.
   767 
   768 The operator returns:
   769 
   770 1. zero, if the extended precision value is not a number
   771 
   772 2. 0xFFFFFFFF, if the value is positive and too big to fit into a TUint.
   773 
   774 3. zero, if the value is negative and too big to fit into a TUint.
   775 */
   776 	{
   777 	asm("ldmia r0, {r1,r2,r3} ");		// get value into r1,r2,r3
   778 
   779 	asm("ConvertTRealXToUint: ");
   780 	asm("mov r12, #0x8000 ");			// r12=0x801E
   781 	asm("orr r12, r12, #0x001E ");
   782 	asm("subs r12, r12, r3, lsr #16 ");	// r12=801E-exponent
   783 	asm("bcc ConvertTRealXToUint1 ");	// branch if exponent>801E
   784 	asm("cmp r12, #31 ");				// test if exponent<7FFF
   785 	asm("movhi r0, #0 ");				// if so, underflow result to zero
   786 	__JUMP(hi,lr);
   787 	asm("tst r3, #1 ");					// check sign bit
   788 	asm("moveq r0, r2, lsr r12 ");		// if +ve, shift mantissa right to form integer
   789 	asm("movne r0, #0 ");				// if negative, r0=0
   790 	__JUMP(,lr);
   791 	asm("ConvertTRealXToUint1: ");
   792 	asm("mov r0, #0 ");					// r0=0 initially
   793 	asm("cmn r3, #0x10000 ");			// check for infinity or NaN
   794 	asm("bcc ConvertTRealXToUint2 ");	// branch if neither
   795 	asm("cmp r2, #0x80000000 ");		// check for infinity
   796 	asm("cmpeq r1, #0 ");
   797 	__JUMP(ne,lr);
   798 	asm("ConvertTRealXToUint2: ");
   799 	asm("movs r3, r3, lsr #1 ");		// sign bit into carry
   800 	asm("sbc r0, r0, #0 ");				// r0=0 if -ve, 0xFFFFFFFF if +ve
   801 	__JUMP(,lr);
   802 	}
   803 
   804 
   805 
   806 
   807 __NAKED__ EXPORT_C TRealX::operator TInt64() const
   808 /**
   809 Returns the extended precision value as a 64 bit integer value.
   810 
   811 The operator returns:
   812 
   813 1. zero, if the extended precision value is not a number
   814 
   815 2. 0x7FFFFFFF FFFFFFFF, if the value is positive and too big to fit
   816    into a TInt64
   817 
   818 3. 0x80000000 00000000, if the value is negative and too big to fit
   819    into a TInt.
   820 */
   821 	{
   822 	// r0 = this, result in r1:r0
   823 	asm("ldmia r0, {r0,r1,r2} ");		// get value into r0,r1,r2
   824 	asm("ConvertTRealXToInt64: ");
   825 	asm("mov r3, #0x8000 ");			// r3=0x803E
   826 	asm("orr r3, r3, #0x003E ");
   827 	asm("subs r3, r3, r2, lsr #16 ");	// r3=803E-exponent
   828 	asm("bls ConvertTRealXToInt64a ");	// branch if exponent>=803E
   829 	asm("cmp r3, #63 ");				// test if exponent<7FFF
   830 	asm("movhi r1, #0 ");				// if so, underflow result to zero
   831 	asm("movhi r0, #0 ");
   832 	__JUMP(hi,lr);
   833 	asm("cmp r3, #32 ");				// >=32 shifts required?
   834 	asm("subcs r3, r3, #32 ");			// if so, r3-=32
   835 	asm("movcs r0, r1, lsr r3 ");		// r1:r0 >>= (r3+32)
   836 	asm("movcs r1, #0 ");
   837 	asm("movcc r0, r0, lsr r3 ");		// else r1:r0>>=r3
   838 	asm("rsbcc r3, r3, #32 ");
   839 	asm("orrcc r0, r0, r1, lsl r3 ");
   840 	asm("rsbcc r3, r3, #32 ");
   841 	asm("movcc r1, r1, lsr r3 ");		// r1:r0 = absolute integer
   842 	asm("tst r2, #1 ");					// check sign bit
   843 	__JUMP(eq,lr);
   844 	asm("rsbs r0, r0, #0 ");			// else negate answer
   845 	asm("rsc r1, r1, #0 ");
   846 	__JUMP(,lr);
   847 	asm("ConvertTRealXToInt64a: ");
   848 	asm("cmn r2, #0x10000 ");			// check for infinity or NaN
   849 	asm("bcc ConvertTRealXToInt64b ");	// branch if neither
   850 	asm("cmp r1, #0x80000000 ");		// check for infinity
   851 	asm("cmpeq r0, #0 ");
   852 	asm("movne r1, #0 ");				// if NaN, return 0
   853 	asm("movne r0, #0 ");
   854 	__JUMP(ne,lr);
   855 	asm("ConvertTRealXToInt64b: ");
   856 	asm("mov r1, #0x80000000 ");		// return KMaxTInt64/KMinTInt64 depending on sign
   857 	asm("mov r0, #0 ");
   858 	asm("movs r2, r2, lsr #1 ");
   859 	asm("sbcs r0, r0, #0 ");
   860 	asm("sbc r1, r1, #0 ");
   861 	__JUMP(,lr);
   862 	}
   863 
   864 
   865 
   866 
   867 __NAKED__ EXPORT_C TRealX::operator TReal32() const __SOFTFP
   868 /**
   869 Returns the extended precision value as
   870 a single precision floating point value.
   871 */
   872 	{
   873 	asm("ldmia r0, {r1,r2,r3} ");			// r1,r2,r3=input value
   874 
   875 	// Convert TRealX in r1,r2,r3 to TReal32 in r0
   876 	asm("ConvertTRealXToTReal32: ");
   877 	asm("mov r12, #0x8000 ");
   878 	asm("orr r12, r12, #0x007F ");			// r12=0x807F
   879 	asm("cmp r3, r12, lsl #16 ");			// check if exponent>=807F
   880 	asm("bcs ConvertTRealXToTReal32a ");	// branch if it is
   881 	asm("sub r12, r12, #0x00FF ");			// r12=0x7F80
   882 	asm("rsbs r12, r12, r3, lsr #16 ");		// r12=exp in - 7F80 = result exponent if in range
   883 	asm("bgt ConvertTRealXToTReal32b ");	// branch if normalised result
   884 	asm("cmn r12, #23 ");					// check for total underflow or zero
   885 	asm("movlt r0, r3, lsl #31 ");			// in this case, return zero with appropriate sign
   886 	__JUMP(lt,lr);
   887 	asm("add r12, r12, #31 ");				// r12=32-mantissa shift required = 32-(1-r12)
   888 	asm("movs r0, r1, lsl r12 ");			// r0=lost bits when r2:r1 is shifted
   889 	asm("bicne r3, r3, #0x300 ");			// if these are not zero, set rounded down flag
   890 	asm("orrne r3, r3, #0x100 ");
   891 	asm("rsb r0, r12, #32 ");
   892 	asm("mov r1, r1, lsr r0 ");
   893 	asm("orr r1, r1, r2, lsl r12 ");
   894 	asm("mov r2, r2, lsr r0 ");				// r2 top 24 bits now give unrounded result mantissa
   895 	asm("mov r12, #0 ");					// result exponent will be zero
   896 	asm("ConvertTRealXToTReal32b: ");
   897 	asm("movs r0, r2, lsl #24 ");			// top 8 truncated bits into top byte of r0
   898 	asm("bpl ConvertTRealXToTReal32c ");	// if top bit clear, truncate
   899 	asm("cmp r0, #0x80000000 ");
   900 	asm("cmpeq r1, #0 ");					// compare rounding bits to 1000...
   901 	asm("bhi ConvertTRealXToTReal32d ");	// if >, round up
   902 	asm("movs r0, r3, lsl #23 ");			// round up flag into C, round down flag into N
   903 	asm("bcs ConvertTRealXToTReal32c ");	// if rounded up, truncate
   904 	asm("bmi ConvertTRealXToTReal32d ");	// if rounded down, round up
   905 	asm("tst r2, #0x100 ");					// else round to even - test LSB of result mantissa
   906 	asm("beq ConvertTRealXToTReal32c ");	// if zero, truncate, else round up
   907 	asm("ConvertTRealXToTReal32d: ");		// come here to round up
   908 	asm("adds r2, r2, #0x100 ");			// increment the mantissa
   909 	asm("movcs r2, #0x80000000 ");			// if carry, mantissa=800000
   910 	asm("addcs r12, r12, #1 ");				// and increment exponent
   911 	asm("cmpmi r12, #1 ");					// if mantissa normalised, check exponent>0
   912 	asm("movmi r12, #1 ");					// if normalised and exponent=0, set exponent to 1
   913 	asm("ConvertTRealXToTReal32c: ");		// come here to truncate
   914 	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
   915 	asm("orr r0, r0, r12, lsl #23 ");		// exponent into r0 bits 23-30
   916 	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
   917 	asm("orr r0, r0, r2, lsr #8 ");			// non-integer mantissa bits into r0 bits 0-22
   918 	__JUMP(,lr);
   919 	asm("ConvertTRealXToTReal32a: ");		// come here if overflow, infinity or NaN
   920 	asm("cmn r3, #0x10000 ");				// check for infinity or NaN
   921 	asm("movcc r2, #0 ");					// if not, set mantissa to 0 for infinity result
   922 	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
   923 	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
   924 	asm("orr r0, r0, #0x7F000000 ");		// r0 bits 23-30 = FF = exponent
   925 	asm("orr r0, r0, #0x00800000 ");
   926 	asm("orr r0, r0, r2, lsr #8 ");			// r0 bits 0-22 = result mantissa
   927 	__JUMP(,lr);
   928 	}
   929 
   930 
   931 
   932 
   933 __NAKED__ EXPORT_C TRealX::operator TReal64() const __SOFTFP
   934 /**
   935 Returns the extended precision value as
   936 a double precision floating point value.
   937 */
   938 	{
   939 	asm("ldmia r0, {r1,r2,r3} ");			// r1,r2,r3=input value
   940 
   941 	// Convert TRealX in r1,r2,r3 to TReal64 in r0,r1
   942 	// if __DOUBLE_WORDS_SWAPPED__ r0=sign,exp,high mant, r1=low mant
   943 	// else r0, r1 reversed
   944 	asm("ConvertTRealXToTReal64: ");
   945 	asm("mov r12, #0x8300 ");
   946 	asm("orr r12, r12, #0x00FF ");			// r12=0x83FF
   947 	asm("cmp r3, r12, lsl #16 ");			// check if exponent>=83FF
   948 	asm("bcs ConvertTRealXToTReal64a ");	// branch if it is
   949 	asm("mov r12, #0x7C00 ");
   950 	asm("rsbs r12, r12, r3, lsr #16 ");		// r12=exp in - 7C00 = result exponent if in range
   951 	asm("bgt ConvertTRealXToTReal64b ");	// branch if normalised result
   952 	asm("cmn r12, #52 ");					// check for total underflow or zero
   953 	asm("movlt r0, r3, lsl #31 ");			// in this case, return zero with appropriate sign
   954 	asm("movlt r1, #0 ");
   955 	asm("blt ConvertTRealXToTReal64_end ");
   956 
   957 	asm("adds r12, r12, #31 ");				// check if >=32 shifts needed, r12=32-shift count
   958 	asm("ble ConvertTRealXToTReal64e ");	// branch if >=32 shifts needed
   959 	asm("movs r0, r1, lsl r12 ");			// r0=lost bits when r2:r1 is shifted
   960 	asm("bicne r3, r3, #0x300 ");			// if these are not zero, set rounded down flag
   961 	asm("orrne r3, r3, #0x100 ");
   962 	asm("rsb r0, r12, #32 ");				// r0=shift count
   963 	asm("mov r1, r1, lsr r0 ");
   964 	asm("orr r1, r1, r2, lsl r12 ");
   965 	asm("mov r2, r2, lsr r0 ");				// r2:r1 top 53 bits = unrounded result mantissa
   966 	asm("b ConvertTRealXToTReal64f ");
   967 	asm("ConvertTRealXToTReal64e: ");
   968 	asm("add r12, r12, #32 ");				// r12=64-shift count
   969 	asm("cmp r1, #0 ");						// r1 bits are all lost - test them
   970 	asm("moveqs r0, r2, lsl r12 ");			// if zero, test lost bits from r2
   971 	asm("bicne r3, r3, #0x300 ");			// if lost bits not all zero, set rounded down flag
   972 	asm("orrne r3, r3, #0x100 ");
   973 	asm("rsb r0, r12, #32 ");				// r0=shift count-32
   974 	asm("mov r1, r2, lsr r0 ");				// shift r2:r1 right
   975 	asm("mov r2, #0 ");
   976 	asm("ConvertTRealXToTReal64f: ");
   977 	asm("mov r12, #0 ");					// result exponent will be zero for denormals
   978 	asm("ConvertTRealXToTReal64b: ");
   979 	asm("movs r0, r1, lsl #21 ");			// 11 rounding bits to top of r0
   980 	asm("bpl ConvertTRealXToTReal64c ");	// if top bit clear, truncate
   981 	asm("cmp r0, #0x80000000 ");			// compare rounding bits to 10000000000
   982 	asm("bhi ConvertTRealXToTReal64d ");	// if >, round up
   983 	asm("movs r0, r3, lsl #23 ");			// round up flag into C, round down flag into N
   984 	asm("bcs ConvertTRealXToTReal64c ");	// if rounded up, truncate
   985 	asm("bmi ConvertTRealXToTReal64d ");	// if rounded down, round up
   986 	asm("tst r1, #0x800 ");					// else round to even - test LSB of result mantissa
   987 	asm("beq ConvertTRealXToTReal64c ");	// if zero, truncate, else round up
   988 	asm("ConvertTRealXToTReal64d: ");		// come here to round up
   989 	asm("adds r1, r1, #0x800 ");			// increment the mantissa
   990 	asm("adcs r2, r2, #0 ");
   991 	asm("movcs r2, #0x80000000 ");			// if carry, mantissa=10000...0
   992 	asm("addcs r12, r12, #1 ");				// and increment exponent
   993 	asm("cmpmi r12, #1 ");					// if mantissa normalised, check exponent>0
   994 	asm("movmi r12, #1 ");					// if normalised and exponent=0, set exponent to 1
   995 	asm("ConvertTRealXToTReal64c: ");		// come here to truncate
   996 	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
   997 	asm("orr r0, r0, r12, lsl #20 ");		// exponent into r0 bits 20-30
   998 	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
   999 	asm("orr r0, r0, r2, lsr #11 ");		// non-integer mantissa bits into r0 bits 0-19
  1000 	asm("mov r1, r1, lsr #11 ");			// and r1
  1001 	asm("orr r1, r1, r2, lsl #21 ");
  1002 	asm("b ConvertTRealXToTReal64_end ");
  1003 
  1004 	asm("ConvertTRealXToTReal64a: ");		// come here if overflow, infinity or NaN
  1005 	asm("cmn r3, #0x10000 ");				// check for infinity or NaN
  1006 	asm("movcc r2, #0 ");					// if not, set mantissa to 0 for infinity result
  1007 	asm("movcc r1, #0 ");
  1008 	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
  1009 	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
  1010 	asm("orr r0, r0, #0x7F000000 ");		// r0 bits 20-30 = 7FF = exponent
  1011 	asm("orr r0, r0, #0x00F00000 ");
  1012 	asm("orr r0, r0, r2, lsr #11 ");		// r0 bits 0-19 = result mantissa high bits
  1013 	asm("mov r1, r1, lsr #11 ");			// and r1=result mantissa low bits
  1014 	asm("orr r1, r1, r2, lsl #21 ");
  1015 	asm("ConvertTRealXToTReal64_end: ");
  1016 #ifndef __DOUBLE_WORDS_SWAPPED__
  1017 	asm("mov r2, r0 ");
  1018 	asm("mov r0, r1 ");
  1019 	asm("mov r1, r2 ");
  1020 #endif
  1021 	__JUMP(,lr);
  1022 	}
  1023 
  1024 
  1025 
  1026 
  1027 __NAKED__ EXPORT_C TInt TRealX::GetTReal(TReal32& /*aVal*/) const
  1028 /**
  1029 Extracts the extended precision value as
  1030 a single precision floating point value.
  1031 
  1032 @param aVal A reference to a single precision object which contains
  1033             the result of the operation.
  1034 
  1035 @return KErrNone, if the operation is successful;
  1036         KErrOverflow, if the operation results in overflow;
  1037         KErrUnderflow, if the operation results in underflow.
  1038 */
  1039 	{
  1040 	asm("stmfd sp!, {r4,lr} ");
  1041 	asm("mov r4, r1 ");
  1042 	asm("ldmia r0, {r1,r2,r3} ");			// r1,r2,r3=input value
  1043 	asm("bl TRealXGetTReal32 ");
  1044 	asm("str r0, [r4] ");					// store converted TReal32
  1045 	asm("mov r0, r12 ");					// return value into r0
  1046 	__POPRET("r4,");
  1047 
  1048 	// Convert TRealX in r1,r2,r3 to TReal32 in r0
  1049 	// Return error code in r12
  1050 	// r0-r3, r12 modified
  1051 	asm("TRealXGetTReal32: ");
  1052 	asm("mov r12, #0x8000 ");
  1053 	asm("orr r12, r12, #0x007F ");			// r12=0x807F
  1054 	asm("cmp r3, r12, lsl #16 ");			// check if exponent>=807F
  1055 	asm("bcs TRealXGetTReal32a ");			// branch if it is
  1056 	asm("sub r12, r12, #0x00FF ");			// r12=0x7F80
  1057 	asm("rsbs r12, r12, r3, lsr #16 ");		// r12=exp in - 7F80 = result exponent if in range
  1058 	asm("bgt TRealXGetTReal32b ");			// branch if normalised result
  1059 	asm("cmn r12, #23 ");					// check for total underflow or zero
  1060 	asm("bge TRealXGetTReal32e ");			// skip if not
  1061 	asm("mov r0, r3, lsl #31 ");			// else return zero with appropriate sign
  1062 	asm("mov r1, #0 ");
  1063 	asm("cmp r3, #0x10000 ");				// check for zero
  1064 	asm("movcc r12, #0 ");					// if zero return KErrNone
  1065 	asm("mvncs r12, #9 ");					// else return KErrUnderflow
  1066 	__JUMP(,lr);
  1067 	asm("TRealXGetTReal32e: ");
  1068 	asm("add r12, r12, #31 ");				// r12=32-mantissa shift required = 32-(1-r12)
  1069 	asm("movs r0, r1, lsl r12 ");			// r0=lost bits when r2:r1 is shifted
  1070 	asm("bicne r3, r3, #0x300 ");			// if these are not zero, set rounded down flag
  1071 	asm("orrne r3, r3, #0x100 ");
  1072 	asm("rsb r0, r12, #32 ");
  1073 	asm("mov r1, r1, lsr r0 ");
  1074 	asm("orr r1, r1, r2, lsl r12 ");
  1075 	asm("mov r2, r2, lsr r0 ");				// r2 top 24 bits now give unrounded result mantissa
  1076 	asm("mov r12, #0 ");					// result exponent will be zero
  1077 	asm("TRealXGetTReal32b: ");
  1078 	asm("movs r0, r2, lsl #24 ");			// top 8 truncated bits into top byte of r0
  1079 	asm("bpl TRealXGetTReal32c ");			// if top bit clear, truncate
  1080 	asm("cmp r0, #0x80000000 ");
  1081 	asm("cmpeq r1, #0 ");					// compare rounding bits to 1000...
  1082 	asm("bhi TRealXGetTReal32d ");			// if >, round up
  1083 	asm("movs r0, r3, lsl #23 ");			// round up flag into C, round down flag into N
  1084 	asm("bcs TRealXGetTReal32c ");			// if rounded up, truncate
  1085 	asm("bmi TRealXGetTReal32d ");			// if rounded down, round up
  1086 	asm("tst r2, #0x100 ");					// else round to even - test LSB of result mantissa
  1087 	asm("beq TRealXGetTReal32c ");			// if zero, truncate, else round up
  1088 	asm("TRealXGetTReal32d: ");				// come here to round up
  1089 	asm("adds r2, r2, #0x100 ");			// increment the mantissa
  1090 	asm("movcs r2, #0x80000000 ");			// if carry, mantissa=800000
  1091 	asm("addcs r12, r12, #1 ");				// and increment exponent
  1092 	asm("cmpmi r12, #1 ");					// if mantissa normalised, check exponent>0
  1093 	asm("movmi r12, #1 ");					// if normalised and exponent=0, set exponent to 1
  1094 	asm("TRealXGetTReal32c: ");				// come here to truncate
  1095 	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
  1096 	asm("orr r0, r0, r12, lsl #23 ");		// exponent into r0 bits 23-30
  1097 	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
  1098 	asm("orr r0, r0, r2, lsr #8 ");			// non-integer mantissa bits into r0 bits 0-22
  1099 	asm("cmp r12, #0xFF ");					// check for overflow
  1100 	asm("mvneq r12, #8 ");					// if overflow, return KErrOverflow
  1101 	__JUMP(eq,lr);
  1102 	asm("bics r1, r0, #0x80000000 ");		// check for underflow
  1103 	asm("mvneq r12, #9 ");					// if underflow return KErrUnderflow
  1104 	asm("movne r12, #0 ");					// else return KErrNone
  1105 	__JUMP(,lr);
  1106 	asm("TRealXGetTReal32a: ");				// come here if overflow, infinity or NaN
  1107 	asm("cmn r3, #0x10000 ");				// check for infinity or NaN
  1108 	asm("movcc r2, #0 ");					// if not, set mantissa to 0 for infinity result
  1109 	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
  1110 	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
  1111 	asm("orr r0, r0, #0x7F000000 ");		// r0 bits 23-30 = FF = exponent
  1112 	asm("orr r0, r0, #0x00800000 ");
  1113 	asm("orr r0, r0, r2, lsr #8 ");			// r0 bits 0-22 = result mantissa
  1114 	asm("movs r12, r0, lsl #9 ");			// check if result is infinity or NaN
  1115 	asm("mvneq r12, #8 ");					// if infinity return KErrOverflow
  1116 	asm("mvnne r12, #5 ");					// else return KErrArgument
  1117 	__JUMP(,lr);
  1118 	}
  1119 
  1120 
  1121 
  1122 
  1123 __NAKED__ EXPORT_C TInt TRealX::GetTReal(TReal64& /*aVal*/) const
  1124 /**
  1125 Extracts the extended precision value as
  1126 a double precision floating point value.
  1127 
  1128 @param aVal A reference to a double precision object which
  1129             contains the result of the operation.
  1130 
  1131 @return KErrNone, if the operation is successful;
  1132         KErrOverflow, if the operation results in overflow;
  1133         KErrUnderflow, if the operation results in underflow.
  1134 */
  1135 	{
  1136 	asm("stmfd sp!, {r4,lr} ");
  1137 	asm("mov r4, r1 ");
  1138 	asm("ldmia r0, {r1,r2,r3} ");			// r1,r2,r3=input value
  1139 	asm("bl TRealXGetTReal64 ");
  1140 	asm("stmia r4, {r0,r1} ");				// store converted TReal64
  1141 	asm("mov r0, r12 ");					// return value into r0
  1142 	__POPRET("r4,");
  1143 
  1144 	// Convert TRealX in r1,r2,r3 to TReal64 in r0,r1
  1145 	// Return error code in r12
  1146 	// r0-r3, r12 modified
  1147 	asm("TRealXGetTReal64: ");
  1148 	asm("mov r12, #0x8300 ");
  1149 	asm("orr r12, r12, #0x00FF ");			// r12=0x83FF
  1150 	asm("cmp r3, r12, lsl #16 ");			// check if exponent>=83FF
  1151 	asm("bcs TRealXGetTReal64a ");			// branch if it is
  1152 	asm("mov r12, #0x7C00 ");
  1153 	asm("rsbs r12, r12, r3, lsr #16 ");		// r12=exp in - 7C00 = result exponent if in range
  1154 	asm("bgt TRealXGetTReal64b ");			// branch if normalised result
  1155 	asm("cmn r12, #52 ");					// check for total underflow or zero
  1156 	asm("bge TRealXGetTReal64g ");			// skip if not
  1157 	asm("mov r0, r3, lsl #31 ");			// else return zero with appropriate sign
  1158 	asm("mov r1, #0 ");
  1159 	asm("cmp r3, #0x10000 ");				// check for zero
  1160 	asm("movcc r12, #0 ");					// if zero return KErrNone
  1161 	asm("mvncs r12, #9 ");					// else return KErrUnderflow
  1162 	asm("b TRealXGetTReal64_end ");
  1163 
  1164 	asm("TRealXGetTReal64g: ");
  1165 	asm("adds r12, r12, #31 ");				// check if >=32 shifts needed, r12=32-shift count
  1166 	asm("ble TRealXGetTReal64e ");			// branch if >=32 shifts needed
  1167 	asm("movs r0, r1, lsl r12 ");			// r0=lost bits when r2:r1 is shifted
  1168 	asm("bicne r3, r3, #0x300 ");			// if these are not zero, set rounded down flag
  1169 	asm("orrne r3, r3, #0x100 ");
  1170 	asm("rsb r0, r12, #32 ");				// r0=shift count
  1171 	asm("mov r1, r1, lsr r0 ");
  1172 	asm("orr r1, r1, r2, lsl r12 ");
  1173 	asm("mov r2, r2, lsr r0 ");				// r2:r1 top 53 bits = unrounded result mantissa
  1174 	asm("b TRealXGetTReal64f ");
  1175 	asm("TRealXGetTReal64e: ");
  1176 	asm("add r12, r12, #32 ");				// r12=64-shift count
  1177 	asm("cmp r1, #0 ");						// r1 bits are all lost - test them
  1178 	asm("moveqs r0, r2, lsl r12 ");			// if zero, test lost bits from r2
  1179 	asm("bicne r3, r3, #0x300 ");			// if lost bits not all zero, set rounded down flag
  1180 	asm("orrne r3, r3, #0x100 ");
  1181 	asm("rsb r0, r12, #32 ");				// r0=shift count-32
  1182 	asm("mov r1, r2, lsr r0 ");				// shift r2:r1 right
  1183 	asm("mov r2, #0 ");
  1184 	asm("TRealXGetTReal64f: ");
  1185 	asm("mov r12, #0 ");					// result exponent will be zero for denormals
  1186 	asm("TRealXGetTReal64b: ");
  1187 	asm("movs r0, r1, lsl #21 ");			// 11 rounding bits to top of r0
  1188 	asm("bpl TRealXGetTReal64c ");			// if top bit clear, truncate
  1189 	asm("cmp r0, #0x80000000 ");			// compare rounding bits to 10000000000
  1190 	asm("bhi TRealXGetTReal64d ");			// if >, round up
  1191 	asm("movs r0, r3, lsl #23 ");			// round up flag into C, round down flag into N
  1192 	asm("bcs TRealXGetTReal64c ");			// if rounded up, truncate
  1193 	asm("bmi TRealXGetTReal64d ");			// if rounded down, round up
  1194 	asm("tst r1, #0x800 ");					// else round to even - test LSB of result mantissa
  1195 	asm("beq TRealXGetTReal64c ");			// if zero, truncate, else round up
  1196 	asm("TRealXGetTReal64d: ");				// come here to round up
  1197 	asm("adds r1, r1, #0x800 ");			// increment the mantissa
  1198 	asm("adcs r2, r2, #0 ");
  1199 	asm("movcs r2, #0x80000000 ");			// if carry, mantissa=10000...0
  1200 	asm("addcs r12, r12, #1 ");				// and increment exponent
  1201 	asm("cmpmi r12, #1 ");					// if mantissa normalised, check exponent>0
  1202 	asm("movmi r12, #1 ");					// if normalised and exponent=0, set exponent to 1
  1203 	asm("TRealXGetTReal64c: ");				// come here to truncate
  1204 	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
  1205 	asm("orr r0, r0, r12, lsl #20 ");		// exponent into r0 bits 20-30
  1206 	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
  1207 	asm("orr r0, r0, r2, lsr #11 ");		// non-integer mantissa bits into r0 bits 0-19
  1208 	asm("mov r1, r1, lsr #11 ");			// and r1
  1209 	asm("orr r1, r1, r2, lsl #21 ");
  1210 	asm("add r12, r12, #1 ");
  1211 	asm("cmp r12, #0x800 ");				// check for overflow
  1212 	asm("mvneq r12, #8 ");					// if overflow, return KErrOverflow
  1213 	asm("beq TRealXGetTReal64_end ");
  1214 
  1215 	asm("bics r12, r0, #0x80000000 ");		// check for underflow
  1216 	asm("cmpeq r1, #0 ");
  1217 	asm("mvneq r12, #9 ");					// if underflow return KErrUnderflow
  1218 	asm("movne r12, #0 ");					// else return KErrNone
  1219 	asm("b TRealXGetTReal64_end ");
  1220 
  1221 	asm("TRealXGetTReal64a: ");				// come here if overflow, infinity or NaN
  1222 	asm("cmn r3, #0x10000 ");				// check for infinity or NaN
  1223 	asm("movcc r2, #0 ");					// if not, set mantissa to 0 for infinity result
  1224 	asm("movcc r1, #0 ");
  1225 	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
  1226 	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
  1227 	asm("orr r0, r0, #0x7F000000 ");		// r0 bits 20-30 = 7FF = exponent
  1228 	asm("orr r0, r0, #0x00F00000 ");
  1229 	asm("orr r0, r0, r2, lsr #11 ");		// r0 bits 0-19 = result mantissa high bits
  1230 	asm("mov r1, r1, lsr #11 ");			// and r1=result mantissa low bits
  1231 	asm("orr r1, r1, r2, lsl #21 ");
  1232 	asm("movs r12, r0, lsl #12 ");			// check if result is infinity or NaN
  1233 	asm("cmpeq r1, #0 ");
  1234 	asm("mvneq r12, #8 ");					// if infinity return KErrOverflow
  1235 	asm("mvnne r12, #5 ");					// else return KErrArgument
  1236 	asm("TRealXGetTReal64_end: ");
  1237 #ifndef __DOUBLE_WORDS_SWAPPED__
  1238 	asm("mov r2, r0 ");
  1239 	asm("mov r0, r1 ");
  1240 	asm("mov r1, r2 ");
  1241 #endif
  1242 	__JUMP(,lr);
  1243 	}
  1244 
  1245 
  1246 
  1247 
  1248 __NAKED__ EXPORT_C TRealX TRealX::operator+() const
  1249 /**
  1250 Returns this extended precision number unchanged.
  1251 
  1252 Note that this may also be referred to as a unary plus operator. 
  1253 
  1254 @return The extended precision number.
  1255 */
  1256 	{
  1257 	asm("ldmia r1, {r2,r3,r12} ");
  1258 	asm("stmia r0, {r2,r3,r12} ");
  1259 	__JUMP(,lr);
  1260 	}
  1261 
  1262 
  1263 
  1264 
  1265 __NAKED__ EXPORT_C TRealX TRealX::operator-() const
  1266 /**
  1267 Negates this extended precision number.
  1268 
  1269 This may also be referred to as a unary minus operator.
  1270 
  1271 @return The negative of the extended precision number.
  1272 */
  1273 	{
  1274 	asm("ldmia r1, {r2,r3,r12} ");
  1275 	asm("eor r12, r12, #1 ");			// unary - changes sign bit
  1276 	asm("stmia r0, {r2,r3,r12} ");
  1277 	__JUMP(,lr);
  1278 	}
  1279 
  1280 
  1281 
  1282 
  1283 __NAKED__ EXPORT_C TRealX::TRealXOrder TRealX::Compare(const TRealX& /*aVal*/) const
  1284 /**
  1285 */
  1286 	{
  1287 	asm("stmfd sp!, {r4,r5,r6,lr} ");
  1288 	asm("ldmia r1, {r4,r5,r6} ");
  1289 	asm("ldmia r0, {r1,r2,r3} ");
  1290 	asm("bl TRealXCompare ");
  1291 	__POPRET("r4-r6,");
  1292 
  1293 	// Compare TRealX in r1,r2,r3 to TRealX in r4,r5,r6
  1294 	// Return TRealXOrder result in r0
  1295 	asm("TRealXCompare: ");
  1296 	asm("cmn r3, #0x10000 ");				// check for NaNs/infinity
  1297 	asm("bcs TRealXCompare1 ");
  1298 	asm("TRealXCompare6: ");				// will come back here if infinity
  1299 	asm("cmn r6, #0x10000 ");
  1300 	asm("bcs TRealXCompare2 ");
  1301 	asm("TRealXCompare7: ");				// will come back here if infinity
  1302 	asm("cmp r3, #0x10000 ");				// check for zeros
  1303 	asm("bcc TRealXCompare3 ");
  1304 	asm("cmp r6, #0x10000 ");
  1305 	asm("bcc TRealXCompare4 ");
  1306 	asm("mov r12, r6, lsl #31 ");
  1307 	asm("cmp r12, r3, lsl #31 ");			// compare signs
  1308 	asm("movne r0, #4 ");
  1309 	asm("bne TRealXCompare5 ");				// branch if signs different
  1310 	asm("mov r12, r3, lsr #16 ");			// r12=first exponent
  1311 	asm("cmp r12, r6, lsr #16 ");			// compare exponents
  1312 	asm("cmpeq r2, r5 ");					// if equal compare high words of mantissa
  1313 	asm("cmpeq r1, r4 ");					// if equal compare low words of mantissa
  1314 	asm("moveq r0, #2 ");					// if equal return 2
  1315 	__JUMP(eq,lr);
  1316 	asm("movhi r0, #4 ");					// r0=4 if first exp bigger
  1317 	asm("movcc r0, #1 ");					// else r0=1
  1318 	asm("TRealXCompare5: ");
  1319 	asm("tst r3, #1 ");						// if signs negative
  1320 	asm("eorne r0, r0, #5 ");				// then switch 1 and 4
  1321 	__JUMP(,lr);
  1322 	asm("TRealXCompare3: ");				// first operand zero
  1323 	asm("cmp r6, #0x10000 ");				// check if second also zero
  1324 	asm("movcc r0, #2 ");					// if so, return 2
  1325 	__JUMP(cc,lr);
  1326 	asm("tst r6, #1 ");						// else check sign of operand 2
  1327 	asm("moveq r0, #1 ");					// if +, return 1
  1328 	asm("movne r0, #4 ");					// else return 4
  1329 	__JUMP(,lr);
  1330 	asm("TRealXCompare4: ");				// second operand zero, first nonzero
  1331 	asm("tst r3, #1 ");						// check sign of operand 1
  1332 	asm("moveq r0, #4 ");					// if +, return 4
  1333 	asm("movne r0, #1 ");					// else return 1
  1334 	__JUMP(,lr);
  1335 	asm("TRealXCompare1: ");				// first operand NaN or infinity
  1336 	asm("cmp r2, #0x80000000 ");			// check for infinity
  1337 	asm("cmpeq r1, #0 ");
  1338 	asm("beq TRealXCompare6 ");				// if infinity, can handle normally
  1339 	asm("mov r0, #8 ");						// if NaN, return 8 (unordered)
  1340 	__JUMP(,lr);
  1341 	asm("TRealXCompare2: ");				// second operand NaN or infinity
  1342 	asm("cmp r5, #0x80000000 ");			// check for infinity
  1343 	asm("cmpeq r4, #0 ");
  1344 	asm("beq TRealXCompare7 ");				// if infinity, can handle normally
  1345 	asm("mov r0, #8 ");						// if NaN, return 8 (unordered)
  1346 	__JUMP(,lr);
  1347 	}
  1348 
  1349 
  1350 
  1351 
  1352 __NAKED__ EXPORT_C TInt TRealX::SubEq(const TRealX& /*aVal*/)
  1353 /**
  1354 Subtracts an extended precision value from this extended precision number.
  1355 
  1356 @param aVal The extended precision value to be subtracted.
  1357 
  1358 @return KErrNone, if the operation is successful;
  1359         KErrOverflow, if the operation results in overflow;
  1360         KErrUnderflow, if the operation results in underflow.
  1361 */
  1362 	{
  1363 	asm("stmfd sp!, {r0,r4-r8,lr} ");
  1364 	asm("ldmia r1, {r4,r5,r6} ");
  1365 	asm("ldmia r0, {r1,r2,r3} ");
  1366 	asm("bl TRealXSubtract ");
  1367 	asm("ldmfd sp!, {r0,r4-r8,lr} ");
  1368 	asm("stmia r0, {r1,r2,r3} ");
  1369 	asm("mov r0, r12 ");
  1370 	__JUMP(,lr);
  1371 	}
  1372 
  1373 
  1374 
  1375 
  1376 __NAKED__ EXPORT_C TInt TRealX::AddEq(const TRealX& /*aVal*/)
  1377 /**
  1378 Adds an extended precision value to this extended precision number.
  1379 
  1380 @param aVal The extended precision value to be added.
  1381 
  1382 @return KErrNone, if the operation is successful;
  1383         KErrOverflow,if the operation results in overflow;
  1384         KErrUnderflow, if the operation results in underflow. 
  1385 */
  1386 	{
  1387 	asm("stmfd sp!, {r0,r4-r8,lr} ");
  1388 	asm("ldmia r1, {r4,r5,r6} ");
  1389 	asm("ldmia r0, {r1,r2,r3} ");
  1390 	asm("bl TRealXAdd ");
  1391 	asm("ldmfd sp!, {r0,r4-r8,lr} ");
  1392 	asm("stmia r0, {r1,r2,r3} ");
  1393 	asm("mov r0, r12 ");
  1394 	__JUMP(,lr);
  1395 
  1396 	// TRealX subtraction r1,r2,r3 - r4,r5,r6 result in r1,r2,r3
  1397 	// Error code returned in r12
  1398 	// Registers r0-r8,r12 modified
  1399 	// NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE.
  1400 	asm("TRealXSubtract: ");
  1401 	asm("eor r6, r6, #1 ");					// negate second operand and add
  1402 
  1403 	// TRealX addition r1,r2,r3 + r4,r5,r6 result in r1,r2,r3
  1404 	// Error code returned in r12
  1405 	// Registers r0-r8,r12 modified
  1406 	// NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE.
  1407 	// Note:	+0 + +0 = +0, -0 + -0 = -0, +0 + -0 = -0 + +0 = +0,
  1408 	//			+/-0 + X = X + +/-0 = X, X + -X = -X + X = +0
  1409 	asm("TRealXAdd: ");
  1410 	asm("mov r12, #0 ");					// initialise return value to KErrNone
  1411 	asm("bic r3, r3, #0x300 ");				// clear rounding flags
  1412 	asm("bic r6, r6, #0x300 ");				// clear rounding flags
  1413 	asm("cmn r3, #0x10000 ");				// check if first operand is NaN or infinity
  1414 	asm("bcs TRealXAdd1 ");					// branch if it is
  1415 	asm("cmn r6, #0x10000 ");				// check if second operand is NaN or infinity
  1416 	asm("bcs TRealXAdd2 ");					// branch if it is
  1417 	asm("cmp r6, #0x10000 ");				// check if second operand zero
  1418 	asm("bcc TRealXAdd3a ");				// branch if it is
  1419 	asm("cmp r3, #0x10000 ");				// check if first operand zero
  1420 	asm("bcc TRealXAdd3 ");					// branch if it is
  1421 	asm("mov r7, #0 ");						// r7 will be rounding word
  1422 	asm("mov r0, r3, lsr #16 ");			// r0 = first operand exponent
  1423 	asm("subs r0, r0, r6, lsr #16 ");		// r0 = first exponent - second exponent
  1424 	asm("beq TRealXAdd8 ");					// if equal, no mantissa shifting needed
  1425 	asm("bhi TRealXAdd4 ");					// skip if first exponent bigger
  1426 	asm("rsb r0, r0, #0 ");					// need to shift first mantissa right by r0 to align
  1427 	asm("mov r8, r1 ");						// swap the numbers to the one to be shifted is 2nd
  1428 	asm("mov r1, r4 ");
  1429 	asm("mov r4, r8 ");
  1430 	asm("mov r8, r2 ");
  1431 	asm("mov r2, r5 ");
  1432 	asm("mov r5, r8 ");
  1433 	asm("mov r8, r3 ");
  1434 	asm("mov r3, r6 ");
  1435 	asm("mov r6, r8 ");
  1436 	asm("TRealXAdd4: ");					// need to shift 2nd mantissa right by r0 to align
  1437 	asm("cmp r0, #64 ");					// more than 64 shifts needed?
  1438 	asm("bhi TRealXAdd6 ");					// if so, smaller number cannot affect larger
  1439 	asm("cmp r0, #32 ");
  1440 	asm("bhi TRealXAdd7 ");					// branch if shift count>32
  1441 	asm("rsb r8, r0, #32 ");
  1442 	asm("mov r7, r4, lsl r8 ");				// shift r5:r4 right into r7
  1443 	asm("mov r4, r4, lsr r0 ");
  1444 	asm("orr r4, r4, r5, lsl r8 ");
  1445 	asm("mov r5, r5, lsr r0 ");
  1446 	asm("b TRealXAdd8 ");
  1447 	asm("TRealXAdd7: ");					// 64 >= shift count > 32
  1448 	asm("sub r0, r0, #32 ");
  1449 	asm("rsb r8, r0, #32 ");
  1450 	asm("movs r7, r4, lsl r8 ");			// test bits lost in shift
  1451 	asm("orrne r6, r6, #0x100 ");			// if not all zero, flag 2nd mantissa rounded down
  1452 	asm("mov r7, r4, lsr r0 ");				// shift r5:r4 right into r7 by 32+r0
  1453 	asm("orr r7, r7, r5, lsl r8 ");
  1454 	asm("mov r4, r5, lsr r0 ");
  1455 	asm("mov r5, #0 ");
  1456 	asm("TRealXAdd8: ");					// mantissas are now aligned
  1457 	asm("mov r8, r3, lsl #31 ");			// r8=sign of first operand
  1458 	asm("cmp r8, r6, lsl #31 ");			// compare signs
  1459 	asm("bne TRealXSub1 ");					// if different, need to do a subtraction
  1460 	asm("adds r1, r1, r4 ");				// signs the same - add mantissas
  1461 	asm("adcs r2, r2, r5 ");
  1462 	asm("bcc TRealXAdd9 ");					// skip if no carry
  1463 	asm(".word 0xE1B02062 ");				// movs r2, r2, rrx shift carry into mantissa
  1464 	asm(".word 0xE1B01061 ");				// movs r1, r1, rrx
  1465 	asm(".word 0xE1B07067 ");				// movs r7, r7, rrx
  1466 	asm("orrcs r6, r6, #0x100 ");			// if 1 shifted out, flag 2nd mantissa rounded down
  1467 	asm("add r3, r3, #0x10000 ");			// increment exponent
  1468 	asm("TRealXAdd9: ");
  1469 	asm("cmp r7, #0x80000000 ");			// check rounding word
  1470 	asm("bcc TRealXAdd10 ");				// if <0x80000000 round down
  1471 	asm("bhi TRealXAdd11 ");				// if >0x80000000 round up
  1472 	asm("tst r6, #0x100 ");					// if =0x80000000 check if 2nd mantissa rounded down
  1473 	asm("bne TRealXAdd11 ");				// if so, round up
  1474 	asm("tst r6, #0x200 ");					// if =0x80000000 check if 2nd mantissa rounded up
  1475 	asm("bne TRealXAdd10 ");				// if so, round down
  1476 	asm("tst r1, #1 ");						// else round to even - check LSB
  1477 	asm("beq TRealXAdd10 ");				// if zero, round down
  1478 	asm("TRealXAdd11: ");					// come here to round up
  1479 	asm("adds r1, r1, #1 ");				// increment mantissa
  1480 	asm("adcs r2, r2, #0 ");
  1481 	asm("movcs r2, #0x80000000 ");			// if carry, mantissa = 80000000 00000000
  1482 	asm("addcs r3, r3, #0x10000 ");			// and increment exponent
  1483 	asm("cmn r3, #0x10000 ");				// check overflow
  1484 	asm("orrcc r3, r3, #0x200 ");			// if no overflow, set rounded-up flag ...
  1485 	__JUMP(cc,lr);
  1486 	asm("b TRealXAdd12 ");					// if overflow, return infinity
  1487 	asm("TRealXAdd10: ");					// come here to round down
  1488 	asm("cmn r3, #0x10000 ");				// check overflow
  1489 	asm("bcs TRealXAdd12 ");				// if overflow, return infinity
  1490 	asm("cmp r7, #0 ");						// if no overflow check if rounding word is zero
  1491 	asm("orrne r3, r3, #0x100 ");			// if not, set rounded-down flag ...
  1492 	__JUMP(ne,lr);
  1493 	asm("and r6, r6, #0x300 ");				// else transfer 2nd mantissa rounding flags
  1494 	asm("orr r3, r3, r6 ");					// to result
  1495 	__JUMP(,lr);
  1496 
  1497 	asm("TRealXAdd12: ");					// come here if overflow - return infinity
  1498 	asm("mov r2, #0x80000000 ");
  1499 	asm("mov r1, #0 ");
  1500 	asm("mvn r12, #8 ");					// and return KErrOverflow
  1501 	__JUMP(,lr);
  1502 
  1503 	asm("TRealXSub1: ");					// come here if operand signs differ
  1504 	asm("tst r6, #0x300 ");					// check if 2nd mantissa rounded
  1505 	asm("eorne r6, r6, #0x300 ");			// if so, change rounding
  1506 	asm("rsbs r7, r7, #0 ");				// subtract mantissas r2:r1:0 -= r5:r4:r7
  1507 	asm("sbcs r1, r1, r4 ");
  1508 	asm("sbcs r2, r2, r5 ");
  1509 	asm("bcs TRealXSub2 ");					// skip if no borrow
  1510 	asm("tst r6, #0x300 ");					// check if 2nd mantissa rounded
  1511 	asm("eorne r6, r6, #0x300 ");			// if so, change rounding
  1512 	asm("rsbs r7, r7, #0 ");				// negate result
  1513 	asm("rscs r1, r1, #0 ");
  1514 	asm("rscs r2, r2, #0 ");
  1515 	asm("eor r3, r3, #1 ");					// and change result sign
  1516 	asm("TRealXSub2: ");
  1517 	asm("bne TRealXSub3 ");					// skip if mantissa top word is not zero
  1518 	asm("movs r2, r1 ");					// else shift up by 32
  1519 	asm("mov r1, r7 ");
  1520 	asm("mov r7, #0 ");
  1521 	asm("bne TRealXSub3a ");				// skip if mantissa top word is not zero now
  1522 	asm("movs r2, r1 ");					// else shift up by 32 again
  1523 	asm("mov r1, #0 ");
  1524 	asm("moveq r3, #0 ");					// if r2 still zero, result is zero - return +0
  1525 	__JUMP(eq,lr);
  1526 	asm("subs r3, r3, #0x00400000 ");		// else, decrement exponent by 64
  1527 	asm("bcs TRealXSub3 ");					// if no borrow, proceed
  1528 	asm("b TRealXSub4 ");					// if borrow, underflow
  1529 	asm("TRealXSub3a: ");					// needed one 32-bit shift
  1530 	asm("subs r3, r3, #0x00200000 ");		// so decrement exponent by 32
  1531 	asm("bcc TRealXSub4 ");					// if borrow, underflow
  1532 	asm("TRealXSub3: ");					// r2 is now non-zero; still may need up to 31 shifts
  1533 #ifdef __CPU_ARM_HAS_CLZ
  1534 	CLZ(0,2);
  1535 	asm("mov r2, r2, lsl r0 ");
  1536 #else
  1537 	asm("mov r0, #0 ");						// r0 will be shift count
  1538 	asm("cmp r2, #0x00010000 ");
  1539 	asm("movcc r2, r2, lsl #16 ");
  1540 	asm("addcc r0, r0, #16 ");
  1541 	asm("cmp r2, #0x01000000 ");
  1542 	asm("movcc r2, r2, lsl #8 ");
  1543 	asm("addcc r0, r0, #8 ");
  1544 	asm("cmp r2, #0x10000000 ");
  1545 	asm("movcc r2, r2, lsl #4 ");
  1546 	asm("addcc r0, r0, #4 ");
  1547 	asm("cmp r2, #0x40000000 ");
  1548 	asm("movcc r2, r2, lsl #2 ");
  1549 	asm("addcc r0, r0, #2 ");
  1550 	asm("cmp r2, #0x80000000 ");
  1551 	asm("movcc r2, r2, lsl #1 ");
  1552 	asm("addcc r0, r0, #1 ");
  1553 #endif
  1554 	asm("rsb r8, r0, #32 ");
  1555 	asm("subs r3, r3, r0, lsl #16 ");		// subtract shift count from exponent
  1556 	asm("bcc TRealXSub4 ");					// if borrow, underflow
  1557 	asm("orr r2, r2, r1, lsr r8 ");			// else shift mantissa up
  1558 	asm("mov r1, r1, lsl r0 ");
  1559 	asm("orr r1, r1, r7, lsr r8 ");
  1560 	asm("mov r7, r7, lsl r0 ");
  1561 	asm("cmp r3, #0x10000 ");				// check for underflow
  1562 	asm("bcs TRealXAdd9 ");					// if no underflow, branch to round result
  1563 
  1564 	asm("TRealXSub4: ");					// come here if underflow
  1565 	asm("and r3, r3, #1 ");					// set exponent to zero, leave sign
  1566 	asm("mov r2, #0 ");
  1567 	asm("mov r1, #0 ");
  1568 	asm("mvn r12, #9 ");					// return KErrUnderflow
  1569 	__JUMP(,lr);
  1570 
  1571 	asm("TRealXAdd6: ");					// come here if exponents differ by more than 64
  1572 	asm("mov r8, r3, lsl #31 ");			// r8=sign of first operand
  1573 	asm("cmp r8, r6, lsl #31 ");			// compare signs
  1574 	asm("orreq r3, r3, #0x100 ");			// if same, result has been rounded down
  1575 	asm("orrne r3, r3, #0x200 ");			// else result has been rounded up
  1576 	__JUMP(,lr);
  1577 
  1578 	asm("TRealXAdd3a: ");					// come here if second operand zero
  1579 	asm("cmp r3, #0x10000 ");				// check if first operand also zero
  1580 	asm("andcc r3, r3, r6 ");				// if so, result is negative iff both zeros negative
  1581 	asm("andcc r3, r3, #1 ");
  1582 	__JUMP(,lr);
  1583 
  1584 	asm("TRealXAdd3: ");					// come here if first operand zero, second nonzero
  1585 	asm("mov r1, r4 ");						// return second operand unchanged
  1586 	asm("mov r2, r5 ");
  1587 	asm("mov r3, r6 ");
  1588 	__JUMP(,lr);
  1589 
  1590 	asm("TRealXAdd1: ");					// come here if first operand NaN or infinity
  1591 	asm("cmp r2, #0x80000000 ");			// check for infinity
  1592 	asm("cmpeq r1, #0 ");
  1593 	asm("bne TRealXBinOpNan ");				// branch if NaN
  1594 	asm("cmn r6, #0x10000 ");				// check 2nd operand for NaN/infinity
  1595 	asm("mvncc r12, #8 ");					// if neither, return KErrOverflow
  1596 	__JUMP(cc,lr);
  1597 	asm("cmp r5, #0x80000000 ");			// check 2nd operand for infinity
  1598 	asm("cmpeq r4, #0 ");
  1599 	asm("bne TRealXBinOpNan ");				// branch if NaN
  1600 	asm("mov r0, r3, lsl #31 ");			// both operands are infinity - check signs
  1601 	asm("cmp r0, r6, lsl #31 ");
  1602 	asm("mvneq r12, #8 ");					// if same, return KErrOverflow
  1603 	__JUMP(eq,lr);
  1604 
  1605 	// Return 'real indefinite'
  1606 	asm("TRealXRealIndefinite: ");
  1607 	asm("ldr r3, [pc, #__RealIndefiniteExponent-.-8] ");
  1608 	asm("mov r2, #0xC0000000 ");
  1609 	asm("mov r1, #0 ");
  1610 	asm("mvn r12, #5 ");					// return KErrArgument
  1611 	__JUMP(,lr);
  1612 
  1613 	asm("TRealXAdd2: ");					// come here if 2nd operand NaN/infinity, first finite
  1614 	asm("cmp r5, #0x80000000 ");			// check for infinity
  1615 	asm("cmpeq r4, #0 ");
  1616 	asm("bne TRealXBinOpNan ");				// branch if NaN
  1617 	asm("mov r1, r4 ");						// else return 2nd operand (infinity)
  1618 	asm("mov r2, r5 ");
  1619 	asm("mov r3, r6 ");
  1620 	asm("mvn r12, #8 ");					// return KErrOverflow
  1621 	__JUMP(,lr);
  1622 
  1623 	asm("TRealXBinOpNan: ");				// generic routine to process NaNs in binary
  1624 											// operations
  1625 	asm("cmn r3, #0x10000 ");				// check if first operand is NaN
  1626 	asm("movcc r0, r1 ");					// if not, swap the operands
  1627 	asm("movcc r1, r4 ");
  1628 	asm("movcc r4, r0 ");
  1629 	asm("movcc r0, r2 ");
  1630 	asm("movcc r2, r5 ");
  1631 	asm("movcc r5, r0 ");
  1632 	asm("movcc r0, r3 ");
  1633 	asm("movcc r3, r6 ");
  1634 	asm("movcc r6, r0 ");
  1635 	asm("cmn r6, #0x10000 ");				// both operands NaNs?
  1636 	asm("bcc TRealXBinOpNan1 ");			// skip if not
  1637 	asm("cmp r2, r5 ");						// if so, compare the significands
  1638 	asm("cmpeq r1, r4 ");
  1639 	asm("movcc r1, r4 ");					// r1,r2,r3 will get NaN with larger significand
  1640 	asm("movcc r2, r5 ");
  1641 	asm("movcc r3, r6 ");
  1642 	asm("TRealXBinOpNan1: ");
  1643 	asm("orr r2, r2, #0x40000000 ");		// convert an SNaN to a QNaN
  1644 	asm("mvn r12, #5 ");					// return KErrArgument
  1645 	__JUMP(,lr);
  1646 	}
  1647 
  1648 
  1649 
  1650 
  1651 __NAKED__ EXPORT_C TInt TRealX::MultEq(const TRealX& /*aVal*/)
  1652 /**
  1653 Multiplies this extended precision number by an extended precision value.
  1654 
  1655 @param aVal The extended precision value to be used as the multiplier.
  1656 
  1657 @return KErrNone, if the operation is successful;
  1658         KErrOverflow, if the operation results in overflow;
  1659         KErrUnderflow, if the operation results in underflow
  1660 */
  1661 	{
  1662 	// Version for ARM 3M or later
  1663 	// Uses umull/umlal
  1664 	asm("stmfd sp!, {r0,r4-r7,lr} ");
  1665 	asm("ldmia r1, {r4,r5,r6} ");
  1666 	asm("ldmia r0, {r1,r2,r3} ");
  1667 	asm("bl TRealXMultiply ");
  1668 	asm("ldmfd sp!, {r0,r4-r7,lr} ");
  1669 	asm("stmia r0, {r1,r2,r3} ");
  1670 	asm("mov r0, r12 ");
  1671 	__JUMP(,lr);
  1672 
  1673 	// TRealX multiplication r1,r2,r3 * r4,r5,r6 result in r1,r2,r3
  1674 	// Error code returned in r12
  1675 	// Registers r0-r7,r12 modified
  1676 	// NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE.
  1677 	asm("TRealXMultiply: ");
  1678 	asm("mov r12, #0 ");					// initialise return value to KErrNone
  1679 	asm("bic r3, r3, #0x300 ");				// clear rounding flags
  1680 	asm("tst r6, #1 ");
  1681 	asm("eorne r3, r3, #1 ");				// Exclusive-OR signs
  1682 	asm("cmn r3, #0x10000 ");				// check if first operand is NaN or infinity
  1683 	asm("bcs TRealXMultiply1 ");			// branch if it is
  1684 	asm("cmn r6, #0x10000 ");				// check if second operand is NaN or infinity
  1685 	asm("bcs TRealXMultiply2 ");			// branch if it is
  1686 	asm("cmp r3, #0x10000 ");				// check if first operand zero
  1687 	__JUMP(cc,lr);							// if so, exit
  1688 
  1689 	// Multiply mantissas in r2:r1 and r5:r4, result in r2:r1:r12:r7
  1690 	asm("umull r7, r12, r1, r4 ");			// r7:r12=m1.low*m2.low
  1691 	asm("movs r0, r6, lsr #16 ");			// r0=2nd operand exponent
  1692 	asm("beq TRealXMultiply3 ");			// if zero, return zero
  1693 	asm("mov r6, #0 ");						// clear r6 initially
  1694 	asm("umlal r12, r6, r1, r5 ");			// r6:r12:r7=m1.low*m2, r1 no longer needed
  1695 	asm("add r0, r0, r3, lsr #16 ");		// r0=sum of exponents
  1696 	asm("tst r3, #1 ");
  1697 	asm("mov r3, #0 ");						// clear r3 initially
  1698 	asm("umlal r6, r3, r2, r5 ");			// r3:r6:r12:r7=m2.low*m1+m2.high*m1.high<<64
  1699 											// r1,r5 no longer required
  1700 	asm("orrne lr, lr, #1 ");				// save sign in bottom bit of lr
  1701 	asm("sub r0, r0, #0x7F00 ");
  1702 	asm("sub r0, r0, #0x00FE ");			// r0 now contains result exponent
  1703 	asm("umull r1, r5, r2, r4 ");			// r5:r1=m2.high*m1.low
  1704 	asm("adds r12, r12, r1 ");				// shift left by 32 and add to give final result
  1705 	asm("adcs r1, r6, r5 ");
  1706 	asm("adcs r2, r3, #0 ");				// final result now in r2:r1:r12:r7
  1707 											// set flags on final value of r2 (ms word of result)
  1708 
  1709 	// normalise the result mantissa
  1710 	asm("bmi TRealXMultiply4 ");			// skip if already normalised
  1711 	asm("adds r7, r7, r7 ");				// else shift left (will only ever need one shift)
  1712 	asm("adcs r12, r12, r12 ");
  1713 	asm("adcs r1, r1, r1 ");
  1714 	asm("adcs r2, r2, r2 ");
  1715 	asm("sub r0, r0, #1 ");					// and decrement exponent by one
  1716 
  1717 	// round the result mantissa
  1718 	asm("TRealXMultiply4: ");
  1719 	asm("and r3, lr, #1 ");					// result sign bit back into r3
  1720 	asm("orrs r4, r7, r12 ");				// check for exact result
  1721 	asm("beq TRealXMultiply5 ");			// skip if exact
  1722 	asm("cmp r12, #0x80000000 ");			// compare bottom 64 bits to 80000000 00000000
  1723 	asm("cmpeq r7, #0 ");
  1724 	asm("moveqs r4, r1, lsr #1 ");			// if exactly equal, set carry=lsb of result
  1725 											// so we round up if lsb=1
  1726 	asm("orrcc r3, r3, #0x100 ");			// if rounding down, set rounded-down flag
  1727 	asm("orrcs r3, r3, #0x200 ");			// if rounding up, set rounded-up flag
  1728 	asm("adcs r1, r1, #0 ");				// increment mantissa if necessary
  1729 	asm("adcs r2, r2, #0 ");
  1730 	asm("movcs r2, #0x80000000 ");			// if carry, set mantissa to 80000000 00000000
  1731 	asm("addcs r0, r0, #1 ");				// and increment result exponent
  1732 
  1733 	// check for overflow or underflow and assemble final result
  1734 	asm("TRealXMultiply5: ");
  1735 	asm("add r4, r0, #1 ");					// need to add 1 to get usable threshold
  1736 	asm("cmp r4, #0x10000 ");				// check if exponent >= 0xFFFF
  1737 	asm("bge TRealXMultiply6 ");			// if so, overflow
  1738 	asm("cmp r0, #0 ");						// check for underflow
  1739 	asm("orrgt r3, r3, r0, lsl #16 ");		// if no underflow, result exponent into r3, ...
  1740 	asm("movgt r12, #0 ");					// ... return KErrNone ...
  1741 	asm("bicgt pc, lr, #3 ");
  1742 
  1743 	// underflow
  1744 	asm("mvn r12, #9 ");					// return KErrUnderflow
  1745 	asm("bic pc, lr, #3 ");
  1746 
  1747 	// overflow
  1748 	asm("TRealXMultiply6: ");
  1749 	asm("bic r3, r3, #0x0000FF00 ");		// clear rounding flags
  1750 	asm("orr r3, r3, #0xFF000000 ");		// make exponent FFFF for infinity
  1751 	asm("orr r3, r3, #0x00FF0000 ");
  1752 	asm("mov r2, #0x80000000 ");			// mantissa = 80000000 00000000
  1753 	asm("mov r1, #0 ");
  1754 	asm("mvn r12, #8 ");					// return KErrOverflow
  1755 	asm("bic pc, lr, #3 ");
  1756 
  1757 	// come here if second operand zero
  1758 	asm("TRealXMultiply3: ");
  1759 	asm("mov r1, #0 ");
  1760 	asm("mov r2, #0 ");
  1761 	asm("and r3, r3, #1 ");					// zero exponent, keep xor sign
  1762 	asm("mov r12, #0 ");					// return KErrNone
  1763 	asm("bic pc, lr, #3 ");
  1764 
  1765 	// First operand NaN or infinity
  1766 	asm("TRealXMultiply1: ");
  1767 	asm("cmp r2, #0x80000000 ");			// check for infinity
  1768 	asm("cmpeq r1, #0 ");
  1769 	asm("bne TRealXBinOpNan ");				// branch if NaN
  1770 	asm("cmn r6, #0x10000 ");				// check 2nd operand for NaN/infinity
  1771 	asm("bcs TRealXMultiply1a ");			// branch if it is
  1772 	asm("cmp r6, #0x10000 ");				// else check if second operand zero
  1773 	asm("mvncs r12, #8 ");					// if not, return infinity and KErrOverflow
  1774 	asm("biccs pc, lr, #3 ");
  1775 	asm("b TRealXRealIndefinite ");			// else return 'real indefinite'
  1776 
  1777 	asm("TRealXMultiply1a: ");
  1778 	asm("cmp r5, #0x80000000 ");			// check 2nd operand for infinity
  1779 	asm("cmpeq r4, #0 ");
  1780 	asm("bne TRealXBinOpNan ");				// branch if NaN
  1781 	asm("mvn r12, #8 ");					// else (infinity), return KErrOverflow
  1782 	asm("bic pc, lr, #3 ");
  1783 
  1784 	// Second operand NaN or infinity, first operand finite
  1785 	asm("TRealXMultiply2: ");
  1786 	asm("cmp r5, #0x80000000 ");			// check for infinity
  1787 	asm("cmpeq r4, #0 ");
  1788 	asm("bne TRealXBinOpNan ");				// branch if NaN
  1789 	asm("cmp r3, #0x10000 ");				// if infinity, check if first operand zero
  1790 	asm("bcc TRealXRealIndefinite ");		// if it is, return 'real indefinite'
  1791 	asm("orr r3, r3, #0xFF000000 ");		// else return infinity with xor sign
  1792 	asm("orr r3, r3, #0x00FF0000 ");
  1793 	asm("mov r2, #0x80000000 ");
  1794 	asm("mov r1, #0 ");
  1795 	asm("mvn r12, #8 ");					// return KErrOverflow
  1796 	asm("bic pc, lr, #3 ");
  1797 	}
  1798 
  1799 
  1800 
  1801 
  1802 __NAKED__ EXPORT_C TInt TRealX::DivEq(const TRealX& /*aVal*/)
  1803 /**
  1804 Divides this extended precision number by an extended precision value.
  1805 
  1806 @param aVal The extended precision value to be used as the divisor.
  1807 
  1808 @return KErrNone, if the operation is successful;
  1809         KErrOverflow, if the operation results in overflow;
  1810         KErrUnderflow, if the operation results in underflow;
  1811         KErrDivideByZero, if the divisor is zero. 
  1812 */
  1813 	{
  1814 	asm("stmfd sp!, {r0,r4-r9,lr} ");
  1815 	asm("ldmia r1, {r4,r5,r6} ");
  1816 	asm("ldmia r0, {r1,r2,r3} ");
  1817 	asm("bl TRealXDivide ");
  1818 	asm("ldmfd sp!, {r0,r4-r9,lr} ");
  1819 	asm("stmia r0, {r1,r2,r3} ");
  1820 	asm("mov r0, r12 ");
  1821 	__JUMP(,lr);
  1822 
  1823 	// TRealX division r1,r2,r3 / r4,r5,r6 result in r1,r2,r3
  1824 	// Error code returned in r12
  1825 	// Registers r0-r9,r12 modified
  1826 	// NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE.
  1827 	asm("TRealXDivide: ");
  1828 	asm("mov r12, #0 ");					// initialise return value to KErrNone
  1829 	asm("bic r3, r3, #0x300 ");				// clear rounding flags
  1830 	asm("tst r6, #1 ");
  1831 	asm("eorne r3, r3, #1 ");				// Exclusive-OR signs
  1832 	asm("cmn r3, #0x10000 ");				// check if dividend is NaN or infinity
  1833 	asm("bcs TRealXDivide1 ");				// branch if it is
  1834 	asm("cmn r6, #0x10000 ");				// check if divisor is NaN or infinity
  1835 	asm("bcs TRealXDivide2 ");				// branch if it is
  1836 	asm("cmp r6, #0x10000 ");				// check if divisor zero
  1837 	asm("bcc TRealXDivide3 ");				// branch if it is
  1838 	asm("cmp r3, #0x10000 ");				// check if dividend zero
  1839 	__JUMP(cc,lr);							// if zero, exit
  1840 	asm("tst r3, #1 ");
  1841 	asm("orrne lr, lr, #1 ");				// save sign in bottom bit of lr
  1842 
  1843 	// calculate result exponent
  1844 	asm("mov r0, r3, lsr #16 ");			// r0=dividend exponent
  1845 	asm("sub r0, r0, r6, lsr #16 ");		// r0=dividend exponent - divisor exponent
  1846 	asm("add r0, r0, #0x7F00 ");
  1847 	asm("add r0, r0, #0x00FF ");			// r0 now contains result exponent
  1848 	asm("mov r6, r1 ");						// move dividend into r6,r7,r8
  1849 	asm("mov r7, r2 ");
  1850 	asm("mov r8, #0 ");						// use r8 to hold extra bit shifted up
  1851 											// r2:r1 will hold result mantissa
  1852 	asm("mov r2, #1 ");						// we will make sure first bit is 1
  1853 	asm("cmp r7, r5 ");						// compare dividend mantissa to divisor mantissa
  1854 	asm("cmpeq r6, r4 ");
  1855 	asm("bcs TRealXDivide4 ");				// branch if dividend >= divisor
  1856 	asm("adds r6, r6, r6 ");				// else shift dividend left one
  1857 	asm("adcs r7, r7, r7 ");				// ignore carry here
  1858 	asm("sub r0, r0, #1 ");					// decrement result exponent by one
  1859 	asm("TRealXDivide4: ");
  1860 	asm("subs r6, r6, r4 ");				// subtract divisor from dividend
  1861 	asm("sbcs r7, r7, r5 ");
  1862 
  1863 	// Main mantissa division code
  1864 	// First calculate the top 32 bits of the result
  1865 	// Top bit is 1, do 10 lots of 3 bits the one more bit
  1866 	asm("mov r12, #10 ");
  1867 	asm("TRealXDivide5: ");
  1868 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
  1869 	asm("adcs r7, r7, r7 ");
  1870 	asm("adcs r8, r8, r8 ");
  1871 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
  1872 	asm("sbcs r3, r7, r5 ");
  1873 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
  1874 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
  1875 	asm("movcs r7, r3 ");
  1876 	asm("adcs r2, r2, r2 ");				// shift in new result bit
  1877 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
  1878 	asm("adcs r7, r7, r7 ");
  1879 	asm("adcs r8, r8, r8 ");
  1880 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
  1881 	asm("sbcs r3, r7, r5 ");
  1882 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
  1883 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
  1884 	asm("movcs r7, r3 ");
  1885 	asm("adcs r2, r2, r2 ");				// shift in new result bit
  1886 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
  1887 	asm("adcs r7, r7, r7 ");
  1888 	asm("adcs r8, r8, r8 ");
  1889 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
  1890 	asm("sbcs r3, r7, r5 ");
  1891 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
  1892 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
  1893 	asm("movcs r7, r3 ");
  1894 	asm("adcs r2, r2, r2 ");				// shift in new result bit
  1895 	asm("subs r12, r12, #1 ");
  1896 	asm("bne TRealXDivide5 ");				// iterate the loop
  1897 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
  1898 	asm("adcs r7, r7, r7 ");
  1899 	asm("adcs r8, r8, r8 ");
  1900 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
  1901 	asm("sbcs r3, r7, r5 ");
  1902 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
  1903 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
  1904 	asm("movcs r7, r3 ");
  1905 	asm("adcs r2, r2, r2 ");				// shift in new result bit - now have 32 bits
  1906 
  1907 	// Now calculate the bottom 32 bits of the result
  1908 	// Do 8 lots of 4 bits
  1909 	asm("mov r12, #8 ");
  1910 	asm("TRealXDivide5a: ");
  1911 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
  1912 	asm("adcs r7, r7, r7 ");
  1913 	asm("adcs r8, r8, r8 ");
  1914 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
  1915 	asm("sbcs r3, r7, r5 ");
  1916 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
  1917 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
  1918 	asm("movcs r7, r3 ");
  1919 	asm("adcs r1, r1, r1 ");				// shift in new result bit
  1920 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
  1921 	asm("adcs r7, r7, r7 ");
  1922 	asm("adcs r8, r8, r8 ");
  1923 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
  1924 	asm("sbcs r3, r7, r5 ");
  1925 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
  1926 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
  1927 	asm("movcs r7, r3 ");
  1928 	asm("adcs r1, r1, r1 ");				// shift in new result bit
  1929 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
  1930 	asm("adcs r7, r7, r7 ");
  1931 	asm("adcs r8, r8, r8 ");
  1932 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
  1933 	asm("sbcs r3, r7, r5 ");
  1934 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
  1935 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
  1936 	asm("movcs r7, r3 ");
  1937 	asm("adcs r1, r1, r1 ");				// shift in new result bit
  1938 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
  1939 	asm("adcs r7, r7, r7 ");
  1940 	asm("adcs r8, r8, r8 ");
  1941 	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
  1942 	asm("sbcs r3, r7, r5 ");
  1943 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
  1944 	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
  1945 	asm("movcs r7, r3 ");
  1946 	asm("adcs r1, r1, r1 ");				// shift in new result bit
  1947 	asm("subs r12, r12, #1 ");
  1948 	asm("bne TRealXDivide5a ");				// iterate the loop
  1949 
  1950 	// r2:r1 now contains a 64-bit normalised mantissa
  1951 	// need to do rounding now
  1952 	asm("and r3, lr, #1 ");					// result sign back into r3
  1953 	asm("orrs r9, r6, r7 ");				// check if accumulator zero
  1954 	asm("beq TRealXDivide6 ");				// if it is, result is exact, else generate next bit
  1955 	asm("adds r6, r6, r6 ");				// shift accumulator left by one
  1956 	asm("adcs r7, r7, r7 ");
  1957 	asm("adcs r8, r8, r8 ");
  1958 	asm("subs r6, r6, r4 ");				// subtract divisor from accumulator
  1959 	asm("sbcs r7, r7, r5 ");
  1960 	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
  1961 	asm("orrcc r3, r3, #0x100 ");			// if borrow, round down and set round-down flag
  1962 	asm("bcc TRealXDivide6 ");
  1963 	asm("orrs r9, r6, r7 ");				// if no borrow, check if exactly half-way
  1964 	asm("moveqs r9, r1, lsr #1 ");			// if exactly half-way, round to even
  1965 	asm("orrcc r3, r3, #0x100 ");			// if C=0, round result down and set round-down flag
  1966 	asm("bcc TRealXDivide6 ");
  1967 	asm("orr r3, r3, #0x200 ");				// else set round-up flag
  1968 	asm("adds r1, r1, #1 ");				// and round mantissa up
  1969 	asm("adcs r2, r2, #0 ");
  1970 	asm("movcs r2, #0x80000000 ");			// if carry, mantissa = 80000000 00000000
  1971 	asm("addcs r0, r0, #1 ");				// and increment exponent
  1972 
  1973 	// check for overflow or underflow and assemble final result
  1974 	asm("TRealXDivide6: ");
  1975 	asm("add r4, r0, #1 ");					// need to add 1 to get usable threshold
  1976 	asm("cmp r4, #0x10000 ");				// check if exponent >= 0xFFFF
  1977 	asm("bge TRealXMultiply6 ");			// if so, overflow
  1978 	asm("cmp r0, #0 ");						// check for underflow
  1979 	asm("orrgt r3, r3, r0, lsl #16 ");		// if no underflow, result exponent into r3, ...
  1980 	asm("movgt r12, #0 ");					// ... return KErrNone ...
  1981 	asm("bicgt pc, lr, #3 ");
  1982 
  1983 	// underflow
  1984 	asm("and r3, r3, #1 ");					// set exponent=0, keep sign
  1985 	asm("mvn r12, #9 ");					// return KErrUnderflow
  1986 	asm("bic pc, lr, #3 ");
  1987 
  1988 	// come here if divisor is zero, dividend finite
  1989 	asm("TRealXDivide3: ");
  1990 	asm("cmp r3, #0x10000 ");				// check if dividend also zero
  1991 	asm("bcc TRealXRealIndefinite ");		// if so, return 'real indefinite'
  1992 	asm("orr r3, r3, #0xFF000000 ");		// else return infinity with xor sign
  1993 	asm("orr r3, r3, #0x00FF0000 ");
  1994 	asm("mov r2, #0x80000000 ");
  1995 	asm("mov r1, #0 ");
  1996 	asm("mvn r12, #40 ");					// return KErrDivideByZero
  1997 	asm("bic pc, lr, #3 ");
  1998 
  1999 	// Dividend is NaN or infinity
  2000 	asm("TRealXDivide1: ");
  2001 	asm("cmp r2, #0x80000000 ");			// check for infinity
  2002 	asm("cmpeq r1, #0 ");
  2003 	asm("bne TRealXBinOpNan ");				// branch if NaN
  2004 	asm("cmn r6, #0x10000 ");				// check 2nd operand for NaN/infinity
  2005 	asm("mvncc r12, #8 ");					// if not, return KErrOverflow
  2006 	asm("biccc pc, lr, #3 ");
  2007 
  2008 	// Dividend=infinity, divisor=NaN or infinity
  2009 	asm("cmp r5, #0x80000000 ");			// check 2nd operand for infinity
  2010 	asm("cmpeq r4, #0 ");
  2011 	asm("bne TRealXBinOpNan ");				// branch if NaN
  2012 	asm("b TRealXRealIndefinite ");			// else return 'real indefinite'
  2013 
  2014 	// Divisor is NaN or infinity, dividend finite
  2015 	asm("TRealXDivide2: ");
  2016 	asm("cmp r5, #0x80000000 ");			// check for infinity
  2017 	asm("cmpeq r4, #0 ");
  2018 	asm("bne TRealXBinOpNan ");				// branch if NaN
  2019 	asm("and r3, r3, #1 ");					// else return zero with xor sign
  2020 	asm("bic pc, lr, #3 ");
  2021 	}
  2022 
  2023 
  2024 
  2025 
  2026 __NAKED__ EXPORT_C TInt TRealX::ModEq(const TRealX& /*aVal*/)
  2027 /**
  2028 Modulo-divides this extended precision number by an extended precision value.
  2029 
  2030 @param aVal The extended precision value to be used as the divisor. 
  2031 
  2032 @return KErrNone, if the operation is successful;
  2033         KErrTotalLossOfPrecision, if precision is lost;
  2034         KErrUnderflow, if the operation results in underflow.
  2035 */
  2036 	{
  2037 	asm("stmfd sp!, {r0,r4-r7,lr} ");
  2038 	asm("ldmia r1, {r4,r5,r6} ");
  2039 	asm("ldmia r0, {r1,r2,r3} ");
  2040 	asm("bl TRealXModulo ");
  2041 	asm("ldmfd sp!, {r0,r4-r7,lr} ");
  2042 	asm("stmia r0, {r1,r2,r3} ");
  2043 	asm("mov r0, r12 ");
  2044 	__JUMP(,lr);
  2045 
  2046 	// TRealX remainder r1,r2,r3 % r4,r5,r6 result in r1,r2,r3
  2047 	// Error code returned in r12
  2048 	// Registers r0-r7,r12 modified
  2049 	// NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE.
  2050 	asm("TRealXModulo: ");
  2051 	asm("mov r12, #0 ");					// initialise return value to KErrNone
  2052 	asm("cmn r3, #0x10000 ");				// check if dividend is NaN or infinity
  2053 	asm("bcs TRealXModulo1 ");				// branch if it is
  2054 	asm("cmn r6, #0x10000 ");				// check if divisor is NaN or infinity
  2055 	asm("bcs TRealXModulo2 ");				// branch if it is
  2056 	asm("cmp r6, #0x10000 ");				// check if divisor zero
  2057 	asm("bcc TRealXRealIndefinite ");		// if it is, return 'real indefinite'
  2058 	asm("mov r0, r3, lsr #16 ");			// r0=dividend exponent
  2059 	asm("subs r0, r0, r6, lsr #16 ");		// r0=dividend exponent-divisor exponent
  2060 	__JUMP(lt,lr);
  2061 	asm("cmp r0, #64 ");					// check if difference >= 64 bits
  2062 	asm("bcs TRealXModuloLp ");				// if so, underflow
  2063 	asm("b TRealXModulo4 ");				// skip left shift on first iteration
  2064 
  2065 	asm("TRealXModulo3: ");
  2066 	asm("adds r1, r1, r1 ");				// shift dividend mantissa left one bit
  2067 	asm("adcs r2, r2, r2 ");
  2068 	asm("bcs TRealXModulo5 ");				// if one shifted out, override comparison
  2069 	asm("TRealXModulo4: ");
  2070 	asm("cmp r2, r5 ");						// compare dividend to divisor
  2071 	asm("cmpeq r1, r4 ");
  2072 	asm("bcc TRealXModulo6 ");				// if dividend<divisor, skip
  2073 	asm("TRealXModulo5: ");
  2074 	asm("subs r1, r1, r4 ");				// if dividend>=divisor, dividend-=divisor
  2075 	asm("sbcs r2, r2, r5 ");
  2076 	asm("TRealXModulo6: ");
  2077 	asm("subs r0, r0, #1 ");				// decrement loop count
  2078 	asm("bpl TRealXModulo3 ");				// if more bits to do, loop
  2079 
  2080 	asm("orrs r0, r1, r2 ");				// test for exact zero result
  2081 	asm("andeq r3, r3, #1 ");				// if so, return zero with same sign as dividend
  2082 	__JUMP(eq,lr);
  2083 	asm("and r7, r3, #1 ");					// dividend sign bit into r7
  2084 	asm("mov r3, r6, lsr #16 ");			// r3 lower 16 bits=result exponent=divisor exponent
  2085 	asm("cmp r2, #0 ");						// test if upper 32 bits zero
  2086 	asm("moveq r2, r1 ");					// if so, shift left by 32
  2087 	asm("moveq r1, #0 ");
  2088 	asm("subeqs r3, r3, #32 ");				// and subtract 32 from exponent
  2089 	asm("bls TRealXModuloUnderflow ");		// if borrow from exponent or exponent 0, underflow
  2090 	asm("mov r0, #32 ");					// r0 will hold 32-number of shifts to normalise
  2091 	asm("cmp r2, #0x00010000 ");			// normalise
  2092 	asm("movcc r2, r2, lsl #16 ");
  2093 	asm("subcc r0, r0, #16 ");
  2094 	asm("cmp r2, #0x01000000 ");
  2095 	asm("movcc r2, r2, lsl #8 ");
  2096 	asm("subcc r0, r0, #8 ");
  2097 	asm("cmp r2, #0x10000000 ");
  2098 	asm("movcc r2, r2, lsl #4 ");
  2099 	asm("subcc r0, r0, #4 ");
  2100 	asm("cmp r2, #0x40000000 ");
  2101 	asm("movcc r2, r2, lsl #2 ");
  2102 	asm("subcc r0, r0, #2 ");
  2103 	asm("cmp r2, #0x80000000 ");
  2104 	asm("movcc r2, r2, lsl #1 ");			// top bit of r2 is now set
  2105 	asm("subcc r0, r0, #1 ");
  2106 	asm("orr r2, r2, r1, lsr r0 ");			// top bits of r1 into bottom bits of r2
  2107 	asm("rsb r0, r0, #32 ");				// r0=number of shifts to normalise
  2108 	asm("mov r1, r1, lsl r0 ");				// shift r1 left - mantissa now normalised
  2109 	asm("subs r3, r3, r0 ");				// subtract r0 from exponent
  2110 	asm("bls TRealXModuloUnderflow ");		// if borrow from exponent or exponent 0, underflow
  2111 	asm("orr r3, r7, r3, lsl #16 ");		// else r3=result exponent and sign
  2112 	__JUMP(,lr);
  2113 
  2114 	// dividend=NaN or infinity
  2115 	asm("TRealXModulo1: ");
  2116 	asm("cmp r2, #0x80000000 ");			// check for infinity
  2117 	asm("cmpeq r1, #0 ");
  2118 	asm("bne TRealXBinOpNan ");				// branch if NaN
  2119 	asm("cmn r6, #0x10000 ");				// check 2nd operand for NaN/infinity
  2120 	asm("bcc TRealXRealIndefinite ");		// infinity%finite - return 'real indefinite'
  2121 	asm("cmp r5, #0x80000000 ");			// check if divisor=infinity
  2122 	asm("cmpeq r4, #0 ");
  2123 	asm("bne TRealXBinOpNan ");				// branch if NaN
  2124 	asm("b TRealXRealIndefinite ");			// else infinity%infinity - return 'real indefinite'
  2125 
  2126 	// divisor=NaN or infinity, dividend finite
  2127 	asm("TRealXModulo2: ");
  2128 	asm("cmp r5, #0x80000000 ");			// check for infinity
  2129 	asm("cmpeq r4, #0 ");
  2130 	asm("bne TRealXBinOpNan ");				// branch if NaN
  2131 	__JUMP(,lr);
  2132 
  2133 	asm("TRealXModuloLp: ");
  2134 	asm("mvn r12, #%a0" : : "i" ((TInt)~KErrTotalLossOfPrecision));
  2135 	asm("mov r1, #0 ");
  2136 	asm("mov r2, #0 ");
  2137 	asm("and r3, r3, #1 ");
  2138 	__JUMP(,lr);
  2139 
  2140 	asm("TRealXModuloUnderflow: ");
  2141 	asm("mvn r12, #%a0" : : "i" ((TInt)~KErrUnderflow));
  2142 	asm("mov r1, #0 ");
  2143 	asm("mov r2, #0 ");
  2144 	asm("and r3, r3, #1 ");
  2145 	__JUMP(,lr);
  2146 	}
  2147 
  2148 
  2149 
  2150 
  2151 __NAKED__ EXPORT_C TInt TRealX::Add(TRealX& /*aResult*/,const TRealX& /*aVal*/) const
  2152 /**
  2153 Adds an extended precision value to this extended precision number.
  2154 
  2155 @param aResult On return, a reference to an extended precision object
  2156                containing the result of the operation.
  2157 @param aVal    The extended precision value to be added. 
  2158 
  2159 @return KErrNone, if the operation is successful;
  2160         KErrOverflow, if the operation results in overflow;
  2161         KErrUnderflow, if the operation results in underflow. 
  2162 */
  2163 	{
  2164 	// r0=this, r1=&aResult, r2=&aVal
  2165 	asm("stmfd sp!, {r1,r4-r8,lr} ");
  2166 	asm("ldmia r2, {r4,r5,r6} ");
  2167 	asm("ldmia r0, {r1,r2,r3} ");
  2168 	asm("bl TRealXAdd ");
  2169 	asm("ldmfd sp!, {lr} ");				// lr=&aResult
  2170 	asm("stmia lr, {r1,r2,r3} ");
  2171 	asm("mov r0, r12 ");					// return value into r0
  2172 	__POPRET("r4-r8,");
  2173 	}
  2174 
  2175 
  2176 
  2177 
  2178 __NAKED__ EXPORT_C TInt TRealX::Sub(TRealX& /*aResult*/,const TRealX& /*aVal*/) const
  2179 /**
  2180 Subtracts an extended precision value from this extended precision number.
  2181 
  2182 @param aResult On return, a reference to an extended precision object
  2183                containing the result of the operation.
  2184 @param aVal    The extended precision value to be subtracted. 
  2185 
  2186 @return KErrNone, if the operation is successful;
  2187         KErrOverflow, if the operation results in overflow;
  2188         KErrUnderflow, if the operation results in underflow. 
  2189 */
  2190 	{
  2191 	// r0=this, r1=&aResult, r2=&aVal
  2192 	asm("stmfd sp!, {r1,r4-r8,lr} ");
  2193 	asm("ldmia r2, {r4,r5,r6} ");
  2194 	asm("ldmia r0, {r1,r2,r3} ");
  2195 	asm("bl TRealXSubtract ");
  2196 	asm("ldmfd sp!, {lr} ");				// lr=&aResult
  2197 	asm("stmia lr, {r1,r2,r3} ");
  2198 	asm("mov r0, r12 ");					// return value into r0
  2199 	__POPRET("r4-r8,");
  2200 	}
  2201 
  2202 
  2203 
  2204 
  2205 __NAKED__ EXPORT_C TInt TRealX::Mult(TRealX& /*aResult*/,const TRealX& /*aVal*/) const
  2206 /**
  2207 Multiplies this extended precision number by an extended precision value.
  2208 
  2209 @param aResult On return, a reference to an extended precision object
  2210                containing the result of the operation.
  2211 @param aVal    The extended precision value to be used as the multiplier. 
  2212 
  2213 @return KErrNone, if the operation is successful;
  2214         KErrOverflow, if the operation results in overflow;
  2215         KErrUnderflow, if the operation results in underflow. 
  2216 */
  2217 	{
  2218 	// r0=this, r1=&aResult, r2=&aVal
  2219 	asm("stmfd sp!, {r1,r4-r7,lr} ");
  2220 	asm("ldmia r2, {r4,r5,r6} ");
  2221 	asm("ldmia r0, {r1,r2,r3} ");
  2222 	asm("bl TRealXMultiply ");
  2223 	asm("ldmfd sp!, {lr} ");				// lr=&aResult
  2224 	asm("stmia lr, {r1,r2,r3} ");
  2225 	asm("mov r0, r12 ");					// return value into r0
  2226 	__POPRET("r4-r7,");
  2227 	}
  2228 
  2229 
  2230 
  2231 
  2232 __NAKED__ EXPORT_C TInt TRealX::Div(TRealX& /*aResult*/,const TRealX& /*aVal*/) const
  2233 /**
  2234 Divides this extended precision number by an extended precision value.
  2235 
  2236 @param aResult On return, a reference to an extended precision object
  2237                containing the result of the operation.
  2238 @param aVal    The extended precision value to be used as the divisor.
  2239 
  2240 @return KErrNone, if the operation is successful;
  2241         KErrOverflow, if the operation results in overflow;
  2242         KErrUnderflow, if the operation results in underflow;
  2243         KErrDivideByZero, if the divisor is zero.
  2244 */
  2245 	{
  2246 	// r0=this, r1=&aResult, r2=&aVal
  2247 	asm("stmfd sp!, {r1,r4-r9,lr} ");
  2248 	asm("ldmia r2, {r4,r5,r6} ");
  2249 	asm("ldmia r0, {r1,r2,r3} ");
  2250 	asm("bl TRealXDivide ");
  2251 	asm("ldmfd sp!, {lr} ");				// lr=&aResult
  2252 	asm("stmia lr, {r1,r2,r3} ");
  2253 	asm("mov r0, r12 ");					// return value into r0
  2254 	__POPRET("r4-r9,");
  2255 	}
  2256 
  2257 
  2258 
  2259 
  2260 __NAKED__ EXPORT_C TInt TRealX::Mod(TRealX& /*aResult*/,const TRealX& /*aVal*/) const
  2261 /**
  2262 Modulo-divides this extended precision number by an extended precision value.
  2263 
  2264 @param aResult On return, a reference to an extended precision object
  2265                containing the result of the operation.
  2266 
  2267 @param aVal    The extended precision value to be used as the divisor. 
  2268 
  2269 @return KErrNone, if the operation is successful;
  2270         KErrTotalLossOfPrecision, if precision is lost;
  2271         KErrUnderflow, if the operation results in underflow.
  2272 */
  2273 	{
  2274 	// r0=this, r1=&aResult, r2=&aVal
  2275 	asm("stmfd sp!, {r1,r4-r7,lr} ");
  2276 	asm("ldmia r2, {r4,r5,r6} ");
  2277 	asm("ldmia r0, {r1,r2,r3} ");
  2278 	asm("bl TRealXModulo ");
  2279 	asm("ldmfd sp!, {lr} ");				// lr=&aResult
  2280 	asm("stmia lr, {r1,r2,r3} ");
  2281 	asm("mov r0, r12 ");					// return value into r0
  2282 	__POPRET("r4-r7,");
  2283 	}
  2284 
  2285 extern void PanicOverUnderflowDividebyZero(const TInt aErr);
  2286 
  2287 
  2288 
  2289 
  2290 __NAKED__ EXPORT_C const TRealX& TRealX::operator+=(const TRealX& /*aVal*/)
  2291 /**
  2292 Adds an extended precision value to this extended precision number.
  2293 
  2294 @param aVal The extended precision value to be added.
  2295 
  2296 @return A reference to this object.
  2297 
  2298 @panic MATHX KErrOverflow if the operation results in overflow.
  2299 @panic MATHX KErrUnderflow if  the operation results in underflow.
  2300 */
  2301 	{
  2302 	asm("stmfd sp!, {r0,r4-r8,lr} ");
  2303 	asm("ldmia r1, {r4,r5,r6} ");
  2304 	asm("ldmia r0, {r1,r2,r3} ");
  2305 	asm("bl TRealXAdd ");
  2306 	asm("ldmfd sp!, {r0,r4-r8,lr} ");
  2307 	asm("stmia r0, {r1,r2,r3} ");
  2308 	asm("cmp r12, #0 ");					// check the error code
  2309 	__JUMP(eq,lr);
  2310 	asm("mov r0, r12 ");
  2311 	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
  2312 	}
  2313 
  2314 
  2315 
  2316 
  2317 __NAKED__ EXPORT_C const TRealX& TRealX::operator-=(const TRealX& /*aVal*/)
  2318 /**
  2319 Subtracts an extended precision value from this extended precision number. 
  2320 
  2321 @param aVal The extended precision value to be subtracted.
  2322 
  2323 @return A reference to this object.
  2324 
  2325 @panic MATHX KErrOverflow if the operation results in overflow.
  2326 @panic MATHX KErrUnderflow if  the operation results in underflow.
  2327 */
  2328 	{
  2329 	asm("stmfd sp!, {r0,r4-r8,lr} ");
  2330 	asm("ldmia r1, {r4,r5,r6} ");
  2331 	asm("ldmia r0, {r1,r2,r3} ");
  2332 	asm("bl TRealXSubtract ");
  2333 	asm("ldmfd sp!, {r0,r4-r8,lr} ");
  2334 	asm("stmia r0, {r1,r2,r3} ");
  2335 	asm("cmp r12, #0 ");					// check the error code
  2336 	__JUMP(eq,lr);
  2337 	asm("mov r0, r12 ");
  2338 	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
  2339 	}
  2340 
  2341 
  2342 
  2343 
  2344 __NAKED__ EXPORT_C const TRealX& TRealX::operator*=(const TRealX& /*aVal*/)
  2345 /**
  2346 Multiplies this extended precision number by an extended precision value.
  2347 
  2348 @param aVal The extended precision value to be subtracted.
  2349 
  2350 @return A reference to this object.
  2351 
  2352 @panic MATHX KErrOverflow if the operation results in overflow.
  2353 @panic MATHX KErrUnderflow if  the operation results in underflow.
  2354 */
  2355 	{
  2356 	asm("stmfd sp!, {r0,r4-r7,lr} ");
  2357 	asm("ldmia r1, {r4,r5,r6} ");
  2358 	asm("ldmia r0, {r1,r2,r3} ");
  2359 	asm("bl TRealXMultiply ");
  2360 	asm("ldmfd sp!, {r0,r4-r7,lr} ");
  2361 	asm("stmia r0, {r1,r2,r3} ");
  2362 	asm("cmp r12, #0 ");					// check the error code
  2363 	__JUMP(eq,lr);
  2364 	asm("mov r0, r12 ");
  2365 	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
  2366 	}
  2367 
  2368 
  2369 
  2370 
  2371 __NAKED__ EXPORT_C const TRealX& TRealX::operator/=(const TRealX& /*aVal*/)
  2372 /**
  2373 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 KErrOverflow if the operation results in overflow.
  2380 @panic MATHX KErrUnderflow if  the operation results in underflow.
  2381 @panic MATHX KErrDivideByZero if the divisor is zero.
  2382 */
  2383 	{
  2384 	asm("stmfd sp!, {r0,r4-r9,lr} ");
  2385 	asm("ldmia r1, {r4,r5,r6} ");
  2386 	asm("ldmia r0, {r1,r2,r3} ");
  2387 	asm("bl TRealXDivide ");
  2388 	asm("ldmfd sp!, {r0,r4-r9,lr} ");
  2389 	asm("stmia r0, {r1,r2,r3} ");
  2390 	asm("cmp r12, #0 ");					// check the error code
  2391 	__JUMP(eq,lr);
  2392 	asm("mov r0, r12 ");
  2393 	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
  2394 	}
  2395 
  2396 
  2397 
  2398 
  2399 __NAKED__ EXPORT_C const TRealX& TRealX::operator%=(const TRealX& /*aVal*/)
  2400 /**
  2401 Modulo-divides this extended precision number by an extended precision value.
  2402 
  2403 @param aVal The extended precision value to be used as the divisor. 
  2404 
  2405 @return A reference to this object.
  2406 
  2407 @panic MATHX KErrTotalLossOfPrecision panic if precision is lost.
  2408 @panic MATHX KErrUnderflow if  the operation results in underflow.
  2409 */
  2410 	{
  2411 	asm("stmfd sp!, {r0,r4-r7,lr} ");
  2412 	asm("ldmia r1, {r4,r5,r6} ");
  2413 	asm("ldmia r0, {r1,r2,r3} ");
  2414 	asm("bl TRealXModulo ");
  2415 	asm("ldmfd sp!, {r0,r4-r7,lr} ");
  2416 	asm("stmia r0, {r1,r2,r3} ");
  2417 	asm("cmp r12, #0 ");					// check the error code
  2418 	asm("cmpne r12, #%a0" : : "i" ((TInt)KErrTotalLossOfPrecision));
  2419 	__JUMP(eq,lr);
  2420 	asm("mov r0, r12 ");
  2421 	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
  2422 	}
  2423 
  2424 
  2425 
  2426 
  2427 __NAKED__ EXPORT_C TRealX& TRealX::operator++()
  2428 /**
  2429 Increments this extended precision number by one,
  2430 and then returns a reference to it.
  2431 
  2432 This is also referred to as a prefix operator. 
  2433 
  2434 @return A reference to this object.
  2435 
  2436 @panic MATHX KErrOverflow if the operation results in overflow.
  2437 @panic MATHX KErrUnderflow if  the operation results in underflow.
  2438 */
  2439 	{
  2440 	// pre-increment
  2441 	asm("stmfd sp!, {r0,r4-r8,lr} ");
  2442 	asm("ldmia r0, {r1,r2,r3} ");
  2443 	asm("add r4, pc, #__TRealXOne-.-8 ");
  2444 	asm("ldmia r4, {r4,r5,r6} ");			// r4,r5,r6=1.0
  2445 	asm("bl TRealXAdd ");
  2446 	asm("ldmfd sp!, {r0,r4-r8,lr} ");
  2447 	asm("stmia r0, {r1,r2,r3} ");
  2448 	asm("cmp r12, #0 ");					// check the error code
  2449 	__JUMP(eq,lr);
  2450 	asm("mov r0, r12 ");
  2451 	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
  2452 
  2453 	asm("__TRealXOne: ");
  2454 	asm(".word 0x00000000 ");
  2455 	asm(".word 0x80000000 ");
  2456 	asm(".word 0x7FFF0000 ");
  2457 	}
  2458 
  2459 
  2460 
  2461 
  2462 __NAKED__ EXPORT_C TRealX TRealX::operator++(TInt)
  2463 /**
  2464 Returns this extended precision number before incrementing it by one.
  2465 
  2466 This is also referred to as a postfix operator. 
  2467 
  2468 @return A reference to this object.
  2469 
  2470 @panic MATHX KErrOverflow if the operation results in overflow.
  2471 @panic MATHX KErrUnderflow if  the operation results in underflow.
  2472 */
  2473 	{
  2474 	// post-increment
  2475 	// r0=address of return value, r1=this
  2476 	asm("stmfd sp!, {r0,r1,r4-r8,lr} ");
  2477 	asm("ldmia r1, {r1,r2,r3} ");
  2478 	asm("stmia r0, {r1,r2,r3} ");			// store old value
  2479 	asm("add r4, pc, #__TRealXOne-.-8 ");
  2480 	asm("ldmia r4, {r4,r5,r6} ");			// r4,r5,r6=1.0
  2481 	asm("bl TRealXAdd ");
  2482 	asm("ldmfd sp!, {r0,lr} ");				// restore r0, lr=this
  2483 	asm("stmia lr, {r1,r2,r3} ");			// store incremented value
  2484 	asm("ldmfd sp!, {r4-r8,lr} ");
  2485 	asm("cmp r12, #0 ");					// check the error code
  2486 	__JUMP(eq,lr);
  2487 	asm("mov r0, r12 ");
  2488 	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
  2489 	}
  2490 
  2491 
  2492 
  2493 
  2494 __NAKED__ EXPORT_C TRealX& TRealX::operator--()
  2495 /**
  2496 Decrements this extended precision number by one,
  2497 and then returns a reference to it.
  2498 
  2499 This is also referred to as a prefix operator. 
  2500 
  2501 @return A reference to this object.
  2502 
  2503 @panic MATHX KErrOverflow if the operation results in overflow.
  2504 @panic MATHX KErrUnderflow if  the operation results in underflow.
  2505 */
  2506 	{
  2507 	// pre-decrement
  2508 	asm("stmfd sp!, {r0,r4-r8,lr} ");
  2509 	asm("ldmia r0, {r1,r2,r3} ");
  2510 	asm("add r4, pc, #__TRealXOne-.-8 ");
  2511 	asm("ldmia r4, {r4,r5,r6} ");			// r4,r5,r6=1.0
  2512 	asm("bl TRealXSubtract ");
  2513 	asm("ldmfd sp!, {r0,r4-r8,lr} ");
  2514 	asm("stmia r0, {r1,r2,r3} ");
  2515 	asm("cmp r12, #0 ");					// check the error code
  2516 	__JUMP(eq,lr);
  2517 	asm("mov r0, r12 ");
  2518 	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
  2519 	}
  2520 
  2521 
  2522 
  2523 
  2524 __NAKED__ EXPORT_C TRealX TRealX::operator--(TInt)
  2525 /**
  2526 Returns this extended precision number before decrementing it by one.
  2527 
  2528 This is also referred to as a postfix operator. 
  2529 
  2530 @return A reference to this object.
  2531 
  2532 @panic MATHX KErrOverflow if the operation results in overflow.
  2533 @panic MATHX KErrUnderflow if  the operation results in underflow.
  2534 */
  2535 	{
  2536 	// post-decrement
  2537 	// r0=address of return value, r1=this
  2538 	asm("stmfd sp!, {r0,r1,r4-r8,lr} ");
  2539 	asm("ldmia r1, {r1,r2,r3} ");
  2540 	asm("stmia r0, {r1,r2,r3} ");			// store old value
  2541 	asm("add r4, pc, #__TRealXOne-.-8 ");
  2542 	asm("ldmia r4, {r4,r5,r6} ");			// r4,r5,r6=1.0
  2543 	asm("bl TRealXSubtract ");
  2544 	asm("ldmfd sp!, {r0,lr} ");				// restore r0, lr=this
  2545 	asm("stmia lr, {r1,r2,r3} ");			// store decremented value
  2546 	asm("ldmfd sp!, {r4-r8,lr} ");
  2547 	asm("cmp r12, #0 ");					// check the error code
  2548 	__JUMP(eq,lr);
  2549 	asm("mov r0, r12 ");
  2550 	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
  2551 	}
  2552 
  2553 
  2554 
  2555 
  2556 __NAKED__ EXPORT_C TRealX TRealX::operator+(const TRealX& /*aVal*/) const
  2557 /**
  2558 Adds an extended precision value to this extended precision number.
  2559 
  2560 @param aVal The extended precision value to be added. 
  2561 
  2562 @return An extended precision object containing the result.
  2563 
  2564 @panic MATHX KErrOverflow if the operation results in overflow.
  2565 @panic MATHX KErrUnderflow if  the operation results in underflow.
  2566 */
  2567 	{
  2568 	// r0=address of return value, r1=this, r2=&aVal
  2569 	asm("stmfd sp!, {r0,r4-r8,lr} ");
  2570 	asm("ldmia r2, {r4,r5,r6} ");
  2571 	asm("ldmia r1, {r1,r2,r3} ");
  2572 	asm("bl TRealXAdd ");
  2573 	asm("ldmfd sp!, {r0,r4-r8,lr} ");
  2574 	asm("stmia r0, {r1,r2,r3} ");
  2575 	asm("cmp r12, #0 ");					// check the error code
  2576 	__JUMP(eq,lr);
  2577 	asm("mov r0, r12 ");
  2578 	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
  2579 	}
  2580 
  2581 
  2582 
  2583 
  2584 __NAKED__ EXPORT_C TRealX TRealX::operator-(const TRealX& /*aVal*/) const
  2585 /**
  2586 Subtracts an extended precision value from this extended precision number. 
  2587 
  2588 @param aVal The extended precision value to be subtracted. 
  2589 
  2590 @return An extended precision object containing the result. 
  2591 
  2592 @panic MATHX KErrOverflow if the operation results in overflow.
  2593 @panic MATHX KErrUnderflow if  the operation results in underflow.
  2594 */
  2595 	{
  2596 	// r0=address of return value, r1=this, r2=&aVal
  2597 	asm("stmfd sp!, {r0,r4-r8,lr} ");
  2598 	asm("ldmia r2, {r4,r5,r6} ");
  2599 	asm("ldmia r1, {r1,r2,r3} ");
  2600 	asm("bl TRealXSubtract ");
  2601 	asm("ldmfd sp!, {r0,r4-r8,lr} ");
  2602 	asm("stmia r0, {r1,r2,r3} ");
  2603 	asm("cmp r12, #0 ");					// check the error code
  2604 	__JUMP(eq,lr);
  2605 	asm("mov r0, r12 ");
  2606 	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
  2607 	}
  2608 
  2609 
  2610 
  2611 
  2612 __NAKED__ EXPORT_C TRealX TRealX::operator*(const TRealX& /*aVal*/) const
  2613 /**
  2614 Multiplies this extended precision number by an extended precision value.
  2615 
  2616 @param aVal The extended precision value to be used as the multiplier. 
  2617 
  2618 @return An extended precision object containing the result. 
  2619 
  2620 @panic MATHX KErrOverflow if the operation results in overflow.
  2621 @panic MATHX KErrUnderflow if  the operation results in underflow.
  2622 */
  2623 	{
  2624 	// r0=address of return value, r1=this, r2=&aVal
  2625 	asm("stmfd sp!, {r0,r4-r7,lr} ");
  2626 	asm("ldmia r2, {r4,r5,r6} ");
  2627 	asm("ldmia r1, {r1,r2,r3} ");
  2628 	asm("bl TRealXMultiply ");
  2629 	asm("ldmfd sp!, {r0,r4-r7,lr} ");
  2630 	asm("stmia r0, {r1,r2,r3} ");
  2631 	asm("cmp r12, #0 ");					// check the error code
  2632 	__JUMP(eq,lr);
  2633 	asm("mov r0, r12 ");
  2634 	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
  2635 	}
  2636 
  2637 
  2638 
  2639 
  2640 __NAKED__ EXPORT_C TRealX TRealX::operator/(const TRealX& /*aVal*/) const
  2641 /**
  2642 Divides this extended precision number by an extended precision value.
  2643 
  2644 @param aVal The extended precision value to be used as the divisor. 
  2645 
  2646 @return An extended precision object containing the result. 
  2647 
  2648 @panic MATHX KErrOverflow if the operation results in overflow.
  2649 @panic MATHX KErrUnderflow if  the operation results in underflow.
  2650 @panic MATHX KErrDivideByZero if the divisor is zero.
  2651 */
  2652 	{
  2653 	// r0=address of return value, r1=this, r2=&aVal
  2654 	asm("stmfd sp!, {r0,r4-r9,lr} ");
  2655 	asm("ldmia r2, {r4,r5,r6} ");
  2656 	asm("ldmia r1, {r1,r2,r3} ");
  2657 	asm("bl TRealXDivide ");
  2658 	asm("ldmfd sp!, {r0,r4-r9,lr} ");
  2659 	asm("stmia r0, {r1,r2,r3} ");
  2660 	asm("cmp r12, #0 ");					// check the error code
  2661 	__JUMP(eq,lr);
  2662 	asm("mov r0, r12 ");
  2663 	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
  2664 	}
  2665 
  2666 
  2667 
  2668 
  2669 __NAKED__ EXPORT_C TRealX TRealX::operator%(const TRealX& /*aVal*/) const
  2670 /**
  2671 Modulo-divides this extended precision number by an extended precision value.
  2672 
  2673 @param aVal The extended precision value to be used as the divisor. 
  2674 
  2675 @return An extended precision object containing the result. 
  2676 
  2677 @panic MATHX KErrTotalLossOfPrecision if precision is lost.
  2678 @panic MATHX KErrUnderflow if the operation results in underflow.
  2679 */
  2680 	{
  2681 	// r0=address of return value, r1=this, r2=&aVal
  2682 	asm("stmfd sp!, {r0,r4-r7,lr} ");
  2683 	asm("ldmia r2, {r4,r5,r6} ");
  2684 	asm("ldmia r1, {r1,r2,r3} ");
  2685 	asm("bl TRealXModulo ");
  2686 	asm("ldmfd sp!, {r0,r4-r7,lr} ");
  2687 	asm("stmia r0, {r1,r2,r3} ");
  2688 	asm("cmp r12, #0 ");					// check the error code
  2689 	asm("cmpne r12, #%a0" : : "i" ((TInt)KErrTotalLossOfPrecision));
  2690 	__JUMP(eq,lr);
  2691 	asm("mov r0, r12 ");
  2692 	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
  2693 	}
  2694 
  2695 
  2696 
  2697 
  2698 #ifdef __REALS_MACHINE_CODED__
  2699 __NAKED__ EXPORT_C TInt Math::Sqrt( TReal &/*aDest*/, const TReal &/*aSrc*/ )
  2700 /**
  2701 Calculates the square root of a number.
  2702 
  2703 @param aDest A reference containing the result. 
  2704 @param aSrc  The number whose square-root is required.
  2705 
  2706 @return KErrNone if successful, otherwise another of
  2707         the system-wide error codes. 
  2708 */
  2709 	{
  2710 	// r0=address of aDest, r1=address of aSrc
  2711 
  2712 
  2713 #ifdef __USE_VFP_MATH
  2714 	VFP_FLDD(CC_AL,0,1,0);
  2715 	VFP_FSQRTD(,0,0);
  2716 	VFP_FMRRD(CC_AL,3,2,0);
  2717 	asm("bic r1, r2, #0x80000000 ");	// remove sign bit
  2718 	asm("cmn r1, #0x00100000 ");		// check if exp=7FF
  2719 	asm("movpl r1, #0 ");				// if not return KErrNone
  2720 	asm("bpl donesqrt ");
  2721 	asm("movs r1, r1, lsl #12 ");		// if exp=7FF, check mantissa
  2722 	asm("cmpeq r3, #0 ");
  2723 	asm("moveq r1, #-9 ");				// if exp=7FF, mant=0, return KErrOverflow
  2724 	asm("mvnne r2, #0x80000000 ");		// else set NaN
  2725 	asm("mvnne r3, #0 ");
  2726 	asm("movne r1, #-6 ");				// and return KErrArgument
  2727 	asm("donesqrt: ");
  2728 #ifdef __DOUBLE_WORDS_SWAPPED__
  2729 	asm("stmia r0, {r2,r3} ");			// store the result
  2730 #else
  2731 	asm("str r2, [r0, #4] ");
  2732 	asm("str r3, [r0, #0] ");
  2733 #endif
  2734 	asm("mov r0, r1 ");
  2735 	__JUMP(,lr);
  2736 #else // __USE_VFP_MATH
  2737 	asm("stmfd sp!, {r4-r10,lr} ");
  2738 #ifdef __DOUBLE_WORDS_SWAPPED__
  2739 	asm("ldmia r1, {r3,r4} ");			// low mant into r4, sign:exp:high mant into r3
  2740 #else
  2741 	asm("ldr r3, [r1, #4] ");
  2742 	asm("ldr r4, [r1, #0] ");
  2743 #endif
  2744 	asm("bic r5, r3, #0xFF000000 ");
  2745 	asm("bic r5, r5, #0x00F00000 ");	// high word of mantissa into r5
  2746 	asm("mov r2, r3, lsr #20 ");
  2747 	asm("bics r2, r2, #0x800 ");		// exponent now in r2
  2748 	asm("beq fastsqrt1 ");				// branch if exponent zero (zero or denormal)
  2749 	asm("mov r6, #0xFF ");
  2750 	asm("orr r6, r6, #0x700 ");
  2751 	asm("cmp r2, r6 ");					// check for infinity or NaN
  2752 	asm("beq fastsqrt2 ");				// branch if infinity or NaN
  2753 	asm("movs r3, r3 ");				// test sign
  2754 	asm("bmi fastsqrtn ");				// branch if negative
  2755 	asm("sub r2, r2, #0xFF ");			// unbias the exponent
  2756 	asm("sub r2, r2, #0x300 ");			//
  2757 	asm("fastsqrtd1: ");
  2758 	asm("mov r1, #0x40000000 ");		// value for comparison
  2759 	asm("mov r3, #27 ");				// loop counter (number of bits/2)
  2760 	asm("movs r2, r2, asr #1 ");		// divide exponent by 2, LSB into CF
  2761 	asm("movcs r7, r5, lsl #11 ");		// mantissa into r6,r7 with MSB in MSB of r7
  2762 	asm("orrcs r7, r7, r4, lsr #21 ");
  2763 	asm("movcs r6, r4, lsl #11 ");
  2764 	asm("movcs r4, #0 ");				// r4, r5 will hold result mantissa
  2765 	asm("orrcs r7, r7, #0x80000000 ");	// if exponent odd, restore MSB of mantissa
  2766 	asm("movcc r7, r5, lsl #12 ");		// mantissa into r6,r7 with MSB in MSB of r7
  2767 	asm("orrcc r7, r7, r4, lsr #20 ");	// if exponent even, shift mantissa left an extra
  2768 	asm("movcc r6, r4, lsl #12 ");		// place, lose top bit, and
  2769 	asm("movcc r4, #1 ");				// set MSB of result, and
  2770 	asm("mov r5, #0 ");					// r4, r5 will hold result mantissa
  2771 	asm("mov r8, #0 ");					// r8, r9 will be comparison accumulator
  2772 	asm("mov r9, #0 ");
  2773 	asm("bcc fastsqrt4 ");				// if exponent even, calculate one less bit
  2774 										// as result MSB already known
  2775 
  2776 	// Main mantissa square-root loop
  2777 	asm("fastsqrt3: ");					// START OF MAIN LOOP
  2778 	asm("subs r10, r7, r1 ");			// subtract result:01 from acc:mant
  2779 	asm("sbcs r12, r8, r4 ");			// result into r14:r12:r10
  2780 	asm("sbcs r14, r9, r5 ");
  2781 	asm("movcs r7, r10 ");				// if no borrow replace accumulator with result
  2782 	asm("movcs r8, r12 ");
  2783 	asm("movcs r9, r14 ");
  2784 	asm("adcs r4, r4, r4 ");			// shift result left one, putting in next bit
  2785 	asm("adcs r5, r5, r5 ");
  2786 	asm("mov r9, r9, lsl #2 ");			// shift acc:mant left by 2 bits
  2787 	asm("orr r9, r9, r8, lsr #30 ");
  2788 	asm("mov r8, r8, lsl #2 ");
  2789 	asm("orr r8, r8, r7, lsr #30 ");
  2790 	asm("mov r7, r7, lsl #2 ");
  2791 	asm("orr r7, r7, r6, lsr #30 ");
  2792 	asm("mov r6, r6, lsl #2 ");
  2793 	asm("fastsqrt4: ");					// Come in here if we need to do one less iteration
  2794 	asm("subs r10, r7, r1 ");			// subtract result:01 from acc:mant
  2795 	asm("sbcs r12, r8, r4 ");			// result into r14:r12:r10
  2796 	asm("sbcs r14, r9, r5 ");
  2797 	asm("movcs r7, r10 ");				// if no borrow replace accumulator with result
  2798 	asm("movcs r8, r12 ");
  2799 	asm("movcs r9, r14 ");
  2800 	asm("adcs r4, r4, r4 ");			// shift result left one, putting in next bit
  2801 	asm("adcs r5, r5, r5 ");
  2802 	asm("mov r9, r9, lsl #2 ");			// shift acc:mant left by 2 bits
  2803 	asm("orr r9, r9, r8, lsr #30 ");
  2804 	asm("mov r8, r8, lsl #2 ");
  2805 	asm("orr r8, r8, r7, lsr #30 ");
  2806 	asm("mov r7, r7, lsl #2 ");
  2807 	asm("orr r7, r7, r6, lsr #30 ");
  2808 	asm("mov r6, r6, lsl #2 ");
  2809 	asm("subs r3, r3, #1 ");			// decrement loop counter
  2810 	asm("bne fastsqrt3 ");				// do necessary number of iterations
  2811 
  2812 	asm("movs r4, r4, lsr #1 ");		// shift result mantissa right 1 place
  2813 	asm("orr r4, r4, r5, lsl #31 ");	// LSB (=rounding bit) into carry
  2814 	asm("mov r5, r5, lsr #1 ");
  2815 	asm("adcs r4, r4, #0 ");			// round the mantissa to 53 bits
  2816 	asm("adcs r5, r5, #0 ");
  2817 	asm("cmp r5, #0x00200000 ");		// check for mantissa overflow
  2818 	asm("addeq r2, r2, #1 ");			// if so, increment exponent - can never overflow
  2819 	asm("bic r5, r5, #0x00300000 ");	// remove top bit of mantissa - it is implicit
  2820 	asm("add r2, r2, #0xFF ");			// re-bias the exponent
  2821 	asm("add r3, r2, #0x300 ");			// and move into r3
  2822 	asm("orr r3, r5, r3, lsl #20 ");	// r3 now contains exponent + top of mantissa
  2823 	asm("fastsqrt_ok: ");
  2824 #ifdef __DOUBLE_WORDS_SWAPPED__
  2825 	asm("stmia r0, {r3,r4} ");			// store the result
  2826 #else
  2827 	asm("str r3, [r0, #4] ");
  2828 	asm("str r4, [r0, #0] ");
  2829 #endif
  2830 	asm("mov r0, #0 ");					// error code KErrNone
  2831 	__POPRET("r4-r10,");
  2832 
  2833 	asm("fastsqrt1: ");
  2834 	asm("orrs r6, r5, r4 ");			// exponent zero - test mantissa
  2835 	asm("beq fastsqrt_ok ");			// if zero, return 0
  2836 
  2837 	asm("movs r3, r3 ");				// denormal - test sign
  2838 	asm("bmi fastsqrtn ");				// branch out if negative
  2839 	asm("sub r2, r2, #0xFE ");			// unbias the exponent
  2840 	asm("sub r2, r2, #0x300 ");			//
  2841 	asm("fastsqrtd: ");
  2842 	asm("adds r4, r4, r4 ");			// shift mantissa left
  2843 	asm("adcs r5, r5, r5 ");
  2844 	asm("sub r2, r2, #1 ");				// and decrement exponent
  2845 	asm("tst r5, #0x00100000 ");		// test if normalised
  2846 	asm("beq fastsqrtd ");				// loop until normalised
  2847 	asm("b fastsqrtd1 ");				// now treat as a normalised number
  2848 	asm("fastsqrt2: ");					// get here if infinity or NaN
  2849 	asm("orrs r6, r5, r4 ");			// if mantissa zero, infinity
  2850 	asm("bne fastsqrtnan ");			// branch if not - must be NaN
  2851 	asm("movs r3, r3 ");				// test sign of infinity
  2852 	asm("bmi fastsqrtn ");				// branch if -ve
  2853 #ifdef __DOUBLE_WORDS_SWAPPED__
  2854 	asm("stmia r0, {r3,r4} ");			// store the result
  2855 #else
  2856 	asm("str r3, [r0, #4] ");
  2857 	asm("str r4, [r0, #0] ");
  2858 #endif
  2859 	asm("mov r0, #-9 ");				// return KErrOverflow
  2860 	asm("b fastsqrt_end ");
  2861 
  2862 	asm("fastsqrtn: ");					// get here if negative or QNaN operand
  2863 	asm("mov r3, #0xFF000000 ");		// generate "real indefinite" QNaN
  2864 	asm("orr r3, r3, #0x00F80000 ");	// sign=1, exp=7FF, mantissa = 1000...0
  2865 	asm("mov r4, #0 ");
  2866 	asm("fastsqrtxa: ");
  2867 #ifdef __DOUBLE_WORDS_SWAPPED__
  2868 	asm("stmia r0, {r3,r4} ");			// store the result
  2869 #else
  2870 	asm("str r3, [r0, #4] ");
  2871 	asm("str r4, [r0, #0] ");
  2872 #endif
  2873 	asm("mov r0, #-6 ");				// return KErrArgument
  2874 	asm("fastsqrt_end: ");
  2875 	__POPRET("r4-r10,");
  2876 
  2877 	asm("fastsqrtnan: ");				// operand is a NaN
  2878 	asm("tst r5, #0x00080000 ");		// test MSB of mantissa
  2879 	asm("bne fastsqrtn ");				// if set it is a QNaN - so return "real indefinite"
  2880 	asm("bic r3, r3, #0x00080000 ");	// else convert SNaN to QNaN
  2881 	asm("b fastsqrtxa ");				// and return KErrArgument
  2882 #endif // __USE_VFP_MATH
  2883 	}
  2884 
  2885 
  2886 
  2887 
  2888 __NAKED__ EXPORT_C TReal Math::Poly(TReal /*aX*/,const SPoly* /*aPoly*/) __SOFTFP
  2889 /**
  2890 Evaluates the polynomial:
  2891 {a[n]X^n + a[n-1]X^(n-1) + ... + a[2]X^2 + a[1]X^1 + a[0]}.
  2892 
  2893 
  2894 @param aX    The value of the x-variable 
  2895 @param aPoly A pointer to the structure containing the set of coefficients
  2896              in the order: a[0], a[1], ..., a[n-1], a[n].
  2897 
  2898 @return The result of the evaluation.
  2899 */
  2900 //
  2901 // Evaluate a power series in x for a P_POLY coefficient table.
  2902 // Changed to use TRealX throughout the calculation
  2903 //
  2904 	{
  2905 	// On entry r0,r1=aX, r2=aPoly
  2906 	asm("stmfd sp!, {r4-r11,lr} ");
  2907 	asm("mov r11, r2 ");
  2908 	asm("ldr r10, [r11], #4 ");			// r10=number of coefficients, r11=first coeff addr
  2909 	asm("add r11, r11, r10, lsl #3 ");	// r11=address of last coefficient+8
  2910 	asm("mov r2, r1 ");					// aX into r1,r2
  2911 	asm("mov r1, r0 ");
  2912 	asm("bl ConvertTReal64ToTRealX ");	// convert to TRealX in r1,r2,r3
  2913 	asm("mov r4, r1 ");					// move into r4,r5,r6
  2914 	asm("mov r5, r2 ");
  2915 	asm("mov r6, r3 ");
  2916 	asm("ldmdb r11!, {r1,r2} ");		// last coefficient into r1,r2
  2917 	asm("bl ConvertTReal64ToTRealX ");	// convert to TRealX in r1,r2,r3
  2918 	asm("subs r10, r10, #1 ");
  2919 	asm("beq polynomial0 ");			// if no more coefficients, exit
  2920 
  2921 	asm("polynomial1: ");
  2922 	asm("stmfd sp!, {r4,r5,r6} ");		// save value of aX
  2923 	asm("bl TRealXMultiply ");			// r *= aX
  2924 	asm("mov r4, r1 ");					// move result into r4,r5,r6
  2925 	asm("mov r5, r2 ");
  2926 	asm("mov r6, r3 ");
  2927 	asm("ldmdb r11!, {r1,r2} ");		// next coefficient into r1,r2
  2928 	asm("bl ConvertTReal64ToTRealX ");	// convert to TRealX in r1,r2,r3
  2929 	asm("bl TRealXAdd ");				// r += *--pR
  2930 	asm("ldmfd sp!, {r4,r5,r6} ");		// aX back into r4,r5,r6
  2931 	asm("subs r10, r10, #1 ");			// iterate until all coefficients processed
  2932 	asm("bne polynomial1 ");
  2933 
  2934 	asm("polynomial0: ");				// result now in r1,r2,r3
  2935 	asm("bl ConvertTRealXToTReal64 ");	// convert back to TReal64
  2936 	__POPRET("r4-r11,");
  2937 	}
  2938 
  2939 
  2940 
  2941 
  2942 __NAKED__ EXPORT_C void Math::PolyX(TRealX& /*aY*/,const TRealX& /*aX*/,TInt /*aDeg*/,const TRealX* /*aCoef*/)
  2943 /**
  2944 Evaluates the polynomial:
  2945 {a[n]X^n + a[n-1]X^(n-1) + ... + a[2]X^2 + a[1]X^1 + a[0]}.
  2946 
  2947 @param aY      A reference containing the result. 
  2948 @param aX      The value of the x-variable. 
  2949 @param aDeg    The degree of the polynomial (the highest power of x
  2950                which is present).
  2951 @param aCoef   A pointer to a contiguous set of TRealX values containing
  2952                the coefficients.
  2953                They must be in the order: a[0], a[1], ..., a[n-1], a[n].
  2954 */
  2955 //
  2956 // Evaluate a polynomial with TRealX argument, coefficients and result
  2957 //
  2958 	{
  2959 	// On entry r0=&aY, r1=&aX, r2=aDeg, r3=aCoef
  2960 	asm("stmfd sp!, {r0,r4-r11,lr} ");
  2961 	asm("add r11, r3, r2, lsl #3 ");	// r11=address of last coefficient
  2962 	asm("add r11, r11, r2, lsl #2 ");
  2963 	asm("mov r9, r1 ");					// r9=address of argument
  2964 	asm("movs r10, r2 ");				// r10=number of coefficients-1
  2965 	asm("ldmia r11, {r1,r2,r3} ");		// last coefficient into r1,r2,r3
  2966 	asm("beq polyx0 ");					// if no more coefficients, exit
  2967 
  2968 	asm("polyx1: ");
  2969 	asm("ldmia r9, {r4,r5,r6} ");		// aX into r4,r5,r6
  2970 	asm("bl TRealXMultiply ");			// result *= aX
  2971 	asm("ldmdb r11!, {r4,r5,r6} ");		// next coefficient into r4,r5,r6
  2972 	asm("bl TRealXAdd ");				// result += next coeff
  2973 	asm("subs r10, r10, #1 ");			// iterate until all coefficients processed
  2974 	asm("bne polyx1 ");
  2975 
  2976 	asm("polyx0: ");					// result now in r1,r2,r3
  2977 	asm("ldmfd sp!, {r0,r4-r11,lr} ");	// restore registers, including destination address in r0
  2978 	asm("stmia r0, {r1,r2,r3} ");		// store result
  2979 	__JUMP(,lr);
  2980 	}
  2981 
  2982 
  2983 
  2984 
  2985 #ifndef __USE_VFP_MATH
  2986 __NAKED__ EXPORT_C TInt Math::Int(TReal& /*aTrg*/, const TReal& /*aSrc*/)
  2987 /**
  2988 Calculates the integer part of a number.
  2989 
  2990 The integer part is that before a decimal point.
  2991 Truncation is toward zero, so that
  2992 int(2.4)=2, int(2)=2, int(-1)=-1, int(-1.4)=-1, int(-1.999)=-1.
  2993 
  2994 
  2995 @param aTrg A reference containing the result. 
  2996 @param aSrc The number whose integer part is required. 
  2997 
  2998 @return KErrNone if successful, otherwise another of
  2999         the system-wide error codes. 
  3000 */
  3001 //
  3002 // Write the integer part of aSrc to the TReal at aTrg
  3003 // Negative numbers are rounded towards zero.
  3004 //
  3005 	{
  3006 	// r0=&aTrg, r1=&aSrc, return value in r0
  3007 	asm("stmfd sp!, {lr} ");
  3008 	asm("mov r12, r0 ");				// r12=&aTrg
  3009 #ifdef __DOUBLE_WORDS_SWAPPED__
  3010 	asm("ldmia r1, {r0,r1} ");			// input value into r0,r1
  3011 #else
  3012 	asm("ldr r0, [r1, #4] ");
  3013 	asm("ldr r1, [r1, #0] ");
  3014 #endif
  3015 	asm("bl TReal64Int ");
  3016 #ifdef __DOUBLE_WORDS_SWAPPED__
  3017 	asm("stmia r12, {r0,r1} ");			// store result
  3018 #else
  3019 	asm("str r0, [r12, #4] ");
  3020 	asm("str r1, [r12, #0] ");
  3021 #endif
  3022 	asm("bic r0, r0, #0x80000000 ");	// remove sign bit
  3023 	asm("cmn r0, #0x00100000 ");		// check for NaN or infinity
  3024 	asm("movpl r0, #0 ");				// if neither, return KErrNone
  3025 	asm("bpl math_int_0 ");
  3026 	asm("movs r0, r0, lsl #12 ");		// check for infinity
  3027 	asm("cmpeq r1, #0 ");
  3028 	asm("mvneq r0, #8 ");				// if infinity return KErrOverflow
  3029 	asm("mvnne r0, #5 ");				// else return KErrArgument
  3030 	asm("math_int_0: ");
  3031 	__POPRET("");
  3032 
  3033 	// Take integer part of TReal64 in r0,r1
  3034 	// Infinity and NaNs are unaffected
  3035 	// r0-r3 modified
  3036 	asm("TReal64Int: ");
  3037 	asm("mov r2, r0, lsr #20 ");
  3038 	asm("bic r2, r2, #0x800 ");			// r2=exponent
  3039 	asm("mov r3, #0x300 ");
  3040 	asm("orr r3, r3, #0xFF ");			// r3=0x3FF
  3041 	asm("subs r2, r2, r3 ");			// r2=exponent-3FF=number of integer bits-1
  3042 	asm("ble TReal64Int1 ");			// branch if <=1 integer bits
  3043 	asm("cmp r2, #52 ");
  3044 	__JUMP(ge,lr);
  3045 	asm("cmp r2, #20 ");
  3046 	asm("bgt TReal64Int2 ");			// jump if >21 integer bits (r0 will be unaffected)
  3047 	asm("rsb r2, r2, #20 ");			// r2=number of bits to clear at bottom end of r0
  3048 	asm("mov r0, r0, lsr r2 ");			// clear them
  3049 	asm("mov r0, r0, lsl r2 ");
  3050 	asm("mov r1, #0 ");					// clear r1
  3051 	__JUMP(,lr);
  3052 	asm("TReal64Int2: ");
  3053 	asm("rsb r2, r2, #52 ");			// r2=number of bits to clear at bottom end of r1
  3054 	asm("mov r1, r1, lsr r2 ");			// clear them
  3055 	asm("mov r1, r1, lsl r2 ");
  3056 	__JUMP(,lr);
  3057 	asm("TReal64Int1: ");				// result is either 0 or 1
  3058 	asm("mov r1, #0 ");					// lower mantissa bits of result will be zero
  3059 	asm("moveq r0, r0, lsr #20 ");		// if result is 1, clear mantissa but leave exponent
  3060 	asm("moveq r0, r0, lsl #20 ");
  3061 	asm("andlt r0, r0, #0x80000000 ");	// if result is 0, clear mantissa and exponent
  3062 	__JUMP(,lr);
  3063 	}
  3064 
  3065 
  3066 
  3067 
  3068 __NAKED__ EXPORT_C TInt Math::Int(TInt16& /*aTrg*/, const TReal& /*aSrc*/)
  3069 /**
  3070 Calculates the integer part of a number.
  3071 
  3072 The integer part is that before a decimal point.
  3073 Truncation is toward zero, so that:
  3074 int(2.4)=2, int(2)=2, int(-1)=-1, int(-1.4)=-1, int(-1.999)=-1.
  3075 
  3076 This function is suitable when the result is known to be small enough
  3077 for a 16-bit signed integer.
  3078 
  3079 @param aTrg A reference containing the result. 
  3080 @param aSrc The number whose integer part is required. 
  3081 
  3082 @return KErrNone if successful, otherwise another of
  3083         the system-wide error codes. 
  3084 */
  3085 //
  3086 // If the integer part of aSrc is in the range -32768 to +32767
  3087 // inclusive, write the integer part to the TInt16 at aTrg
  3088 // Negative numbers are rounded towards zero.
  3089 // If an overflow or underflow occurs, aTrg is set to the max/min value
  3090 //
  3091 	{
  3092 	// r0=&aTrg, r1=&aSrc
  3093 	asm("stmfd sp!, {lr} ");
  3094 	asm("mov r3, r0 ");					// r3=&aTrg
  3095 #ifdef __DOUBLE_WORDS_SWAPPED__
  3096 	asm("ldmia r1, {r0,r1} ");			// input value into r0,r1
  3097 #else
  3098 	asm("ldr r0, [r1, #4] ");
  3099 	asm("ldr r1, [r1, #0] ");
  3100 #endif
  3101 	asm("bl TReal64GetTInt ");			// do the conversion
  3102 	asm("cmp r0, #0x8000 ");			// limit answer to TInt16 range
  3103 	asm("movge r0, #0x7F00 ");
  3104 	asm("orrge r0, r0, #0xFF ");
  3105 	asm("mvnge r12, #8 ");				// set error code if limiting occurred
  3106 	asm("cmn r0, #0x8000 ");
  3107 	asm("movlt r0, #0x8000 ");
  3108 	asm("mvnlt r12, #9 ");				// set error code if limiting occurred
  3109 	asm("mov r1, r0, lsr #8 ");			// top byte of answer into r1
  3110 	asm("strb r0, [r3] ");				// store result in aTrg
  3111 	asm("strb r1, [r3, #1] ");
  3112 	asm("mov r0, r12 ");				// return error code in r0
  3113 	__POPRET("");
  3114 	} 
  3115 
  3116 
  3117 
  3118 __NAKED__ EXPORT_C TInt Math::Int(TInt32& /*aTrg*/, const TReal& /*aSrc*/)
  3119 /**
  3120 Calculates the integer part of a number.
  3121 
  3122 The integer part is that before a decimal point.
  3123 Truncation is toward zero, so that
  3124 int(2.4)=2, int(2)=2, int(-1)=-1, int(-1.4)=-1, int(-1.999)=-1.
  3125 
  3126 This function is suitable when the result is known to be small enough
  3127 for a 32-bit signed integer.
  3128 
  3129 @param aTrg A reference containing the result. 
  3130 @param aSrc The number whose integer part is required.
  3131 
  3132 @return KErrNone if successful, otherwise another of
  3133         the system-wide error codes.
  3134 */
  3135 //													 
  3136 // If the integer part of the float is in the range -2147483648 to +2147483647
  3137 // inclusive, write the integer part to the TInt32 at aTrg
  3138 // Negative numbers are rounded towards zero.
  3139 // If an overflow or underflow occurs, aTrg is set to the max/min value
  3140 //
  3141 	{
  3142 	// r0=&aTrg, r1=&aSrc
  3143 	asm("stmfd sp!, {lr} ");
  3144 	asm("mov r3, r0 ");					// r3=&aTrg
  3145 #ifdef __DOUBLE_WORDS_SWAPPED__
  3146 	asm("ldmia r1, {r0,r1} ");			// input value into r0,r1
  3147 #else
  3148 	asm("ldr r0, [r1, #4] ");
  3149 	asm("ldr r1, [r1, #0] ");
  3150 #endif
  3151 	asm("bl TReal64GetTInt ");			// do the conversion
  3152 	asm("str r0, [r3] ");				// store result in aTrg
  3153 	asm("mov r0, r12 ");				// return error code in r0
  3154 	__POPRET("");
  3155 
  3156 	//  Convert double in r0,r1 to int in r0
  3157 	//	Return error code in r12
  3158 	//	Registers r0,r1,r2,r12 modified
  3159 	asm("TReal64GetTInt: ");
  3160 	asm("mov r2, r0, lsr #20 ");
  3161 	asm("bic r2, r2, #0x800 ");			// r1=exponent
  3162 	asm("add r12, r2, #1 ");
  3163 	asm("cmp r12, #0x800 ");			// check for NaN
  3164 	asm("bne TReal64GetTInt1 ");
  3165 	asm("movs r12, r0, lsl #12 ");		// exponent=FF, check mantissa
  3166 	asm("cmpeq r1, #0 ");
  3167 	asm("movne r0, #0 ");				// if non-zero, input is a NaN so return 0
  3168 	asm("mvnne r12, #5 ");				// and return KErrArgument
  3169 	__JUMP(ne,lr);
  3170 	asm("TReal64GetTInt1: ");
  3171 	asm("mov r12, #0x400 ");
  3172 	asm("orr r12, r12, #0x1E ");		// r12=0x41E (exponent of 2^31)
  3173 	asm("subs r2, r12, r2 ");			// r2=number of shifts to produce integer
  3174 	asm("mov r12, #0 ");				// set return code to KErrNone
  3175 	asm("ble TReal64GetTInt2 ");		// if <=0, saturate result
  3176 	asm("cmp r2, #31 ");				// check if more than 31 shifts needed
  3177 	asm("movhi r0, #0 ");				// if so, underflow result to 0
  3178 	__JUMP(hi,lr);
  3179 	asm("cmp r0, #0 ");					// check sign bit
  3180 	asm("orr r0, r0, #0x00100000 ");	// set implicit integer bit
  3181 	asm("mov r0, r0, lsl #11 ");		// shift mantissa up so MSB is in MSB of r0
  3182 	asm("orr r0, r0, r1, lsr #21 ");	// put in bits from r1
  3183 	asm("mov r0, r0, lsr r2 ");			// r0=absolute integer
  3184 	asm("rsbmi r0, r0, #0 ");			// if negative, negate
  3185 	__JUMP(,lr);
  3186 	asm("TReal64GetTInt2: ");
  3187 	asm("blt TReal64GetTInt3 ");		// if exponent>0x41E, definitely an overflow
  3188 	asm("cmp r0, #0 ");					// check sign bit
  3189 	asm("bpl TReal64GetTInt3 ");		// if positive, definitely an overflow
  3190 	asm("orr r0, r0, #0x00100000 ");	// set implicit integer bit
  3191 	asm("mov r0, r0, lsl #11 ");		// shift mantissa up so MSB is in MSB of r0
  3192 	asm("orr r0, r0, r1, lsr #21 ");	// put in bits from r1
  3193 	asm("cmp r0, #0x80000000 ");		// check if value is = -2^31
  3194 	__JUMP(eq,lr);
  3195 	asm("TReal64GetTInt3: ");
  3196 	asm("cmp r0, #0 ");					// check sign
  3197 	asm("mov r0, #0x80000000 ");
  3198 	asm("subpl r0, r0, #1 ");			// if -ve return 80000000, if +ve return 7FFFFFFF
  3199 	asm("mvnpl r12, #8 ");				// if +ve return KErrOverflow
  3200 	asm("mvnmi r12, #9 ");				// if -ve return KErrUnderflow
  3201 	__JUMP(,lr);
  3202 	}
  3203 #endif // __USE_VFP_MATH
  3204 
  3205 
  3206 
  3207 
  3208 __NAKED__ EXPORT_C TBool Math::IsZero(const TReal& /*aVal*/)
  3209 /**
  3210 Determines whether a value is zero.
  3211 
  3212 @param aVal A reference to the value to be checked. 
  3213 
  3214 @return True, if aVal is zero; false, otherwise.
  3215 */
  3216 	{
  3217 #ifdef __DOUBLE_WORDS_SWAPPED__
  3218 	asm("ldmia r0, {r1,r2} ");			// input value into r0,r1
  3219 #else
  3220 	asm("ldr r2, [r0, #0] ");
  3221 	asm("ldr r1, [r0, #4] ");
  3222 #endif
  3223 	asm("TReal64IsZero: ");
  3224 	asm("mov r0, #0 ");					// default return value is 0
  3225 	asm("bics r1, r1, #0x80000000 ");	// remove sign bit
  3226 	asm("cmpeq r2, #0 ");				// and check both exponent and mantissa are zero
  3227 	asm("moveq r0, #1 ");				// return 1 if zero
  3228 	__JUMP(,lr);
  3229 	}
  3230 
  3231 
  3232 
  3233 
  3234 __NAKED__ EXPORT_C TBool Math::IsNaN(const TReal& /*aVal*/)
  3235 /**
  3236 Determines whether a value is not a number.
  3237 
  3238 @param aVal A reference to the value to be checked. 
  3239 
  3240 @return True, if aVal is not a number; false, otherwise.
  3241 */
  3242 	{
  3243 #ifdef __DOUBLE_WORDS_SWAPPED__
  3244 	asm("ldmia r0, {r1,r2} ");			// input value into r0,r1
  3245 #else
  3246 	asm("ldr r2, [r0, #0] ");
  3247 	asm("ldr r1, [r0, #4] ");
  3248 #endif
  3249 	asm("TReal64IsNaN: ");
  3250 	asm("mov r0, #0 ");					// default return value is 0
  3251 	asm("bic r1, r1, #0x80000000 ");	// remove sign bit
  3252 	asm("cmn r1, #0x00100000 ");		// check if exponent=7FF
  3253 	__JUMP(pl,lr);
  3254 	asm("movs r1, r1, lsl #12 ");		// exponent=7FF, check mantissa
  3255 	asm("cmpeq r2, #0 ");
  3256 	asm("movne r0, #1 ");				// if mantissa nonzero, return 1
  3257 	__JUMP(,lr);
  3258 	}
  3259 
  3260 
  3261 
  3262 
  3263 __NAKED__ EXPORT_C TBool Math::IsInfinite(const TReal& /*aVal*/)
  3264 /**
  3265 Determines whether a value is infinite.
  3266 
  3267 @param aVal A reference to the value to be checked.
  3268 
  3269 @return True, if aVal is infinite; false, otherwise.
  3270 */
  3271 	{
  3272 #ifdef __DOUBLE_WORDS_SWAPPED__
  3273 	asm("ldmia r0, {r1,r2} ");			// input value into r0,r1
  3274 #else
  3275 	asm("ldr r2, [r0, #0] ");
  3276 	asm("ldr r1, [r0, #4] ");
  3277 #endif
  3278 	asm("TReal64IsInfinite: ");
  3279 	asm("mov r0, #0 ");					// default return value is 0
  3280 	asm("mov r3, #0x00200000 ");		// r3 == - (0x7ff00000 << 1)
  3281 	asm("cmp r2, #0 ");
  3282 	asm("cmneq r3, r1, lsl #1 ");		// check exp=7FF && mant=0
  3283 	asm("moveq r0, #1 ");				// if so, return 1
  3284 	__JUMP(,lr);
  3285 	}
  3286 
  3287 
  3288 
  3289 
  3290 __NAKED__ EXPORT_C TBool Math::IsFinite(const TReal& /*aVal*/)
  3291 /**
  3292 Determines whether a value is finite.
  3293 
  3294 In this context, a value is finite if it is a valid number and
  3295 is not infinite.
  3296 
  3297 @param aVal A reference to the value to be checked.
  3298 
  3299 @return True, if aVal is finite; false, otherwise.
  3300 */
  3301 	{
  3302 #ifdef __DOUBLE_WORDS_SWAPPED__
  3303 	asm("ldr r1, [r0, #0] ");			// only need exponent - get it into r0
  3304 #else
  3305 	asm("ldr r1, [r0, #4] ");			// only need exponent - get it into r0
  3306 #endif
  3307 	asm("TReal64IsFinite: ");
  3308 	asm("mov r0, #0 ");					// default return value is 0
  3309 	asm("bic r1, r1, #0x80000000 ");	// remove sign bit
  3310 	asm("cmn r1, #0x00100000 ");		// check if exponent=7FF
  3311 	asm("movpl r0, #1 ");				// else return 1
  3312 	__JUMP(,lr);
  3313 	}
  3314 
  3315 
  3316 
  3317 
  3318 __NAKED__ EXPORT_C void Math::SetZero(TReal& /*aVal*/, TInt /*aSign*/)
  3319 //
  3320 // Constructs zeros, assuming default sign is positive
  3321 //
  3322 	{
  3323 	asm("cmp r1, #0 ");					// test aSign
  3324 	asm("movne r1, #0x80000000 ");		// if nonzero, set sign bit
  3325 	asm("mov r2, #0 ");					// mantissa=0
  3326 #ifdef __DOUBLE_WORDS_SWAPPED__
  3327 	asm("stmia r0, {r1,r2} ");
  3328 #else
  3329 	asm("str r2, [r0, #0] ");
  3330 	asm("str r1, [r0, #4] ");
  3331 #endif
  3332 	__JUMP(,lr);
  3333 	}
  3334 
  3335 
  3336 
  3337 
  3338 __NAKED__ EXPORT_C void Math::SetNaN(TReal& /*aVal*/)
  3339 //
  3340 // Constructs NaN (+ve sign for Java)
  3341 //
  3342 	{
  3343 #ifdef __DOUBLE_WORDS_SWAPPED__
  3344 	asm("mvn r1, #0x80000000 ");		// r1=7FFFFFFF
  3345 	asm("mvn r2, #0 ");					// r2=FFFFFFFF
  3346 #else
  3347 	asm("mvn r2, #0x80000000 ");		// r2=7FFFFFFF
  3348 	asm("mvn r1, #0 ");					// r1=FFFFFFFF
  3349 #endif
  3350 	asm("stmia r0, {r1,r2} ");
  3351 	__JUMP(,lr);
  3352 	}
  3353 
  3354 
  3355 
  3356 
  3357 __NAKED__ EXPORT_C void Math::SetInfinite(TReal& /*aVal*/, TInt /*aSign*/)
  3358 //
  3359 // Constructs infinities
  3360 //
  3361 	{
  3362 	asm("cmp r1, #0 ");					// test aSign
  3363 	asm("movne r1, #0x80000000 ");		// if nonzero, set sign bit
  3364 	asm("orr r1, r1, #0x70000000 ");	// set exponent to 7FF
  3365 	asm("orr r1, r1, #0x0FF00000 ");
  3366 	asm("mov r2, #0 ");					// mantissa=0
  3367 #ifdef __DOUBLE_WORDS_SWAPPED__
  3368 	asm("stmia r0, {r1,r2} ");
  3369 #else
  3370 	asm("str r2, [r0, #0] ");
  3371 	asm("str r1, [r0, #4] ");
  3372 #endif
  3373 	__JUMP(,lr);
  3374 	}
  3375 
  3376 
  3377 
  3378 #ifndef __USE_VFP_MATH
  3379 __NAKED__ EXPORT_C TInt Math::Frac(TReal& /*aTrg*/, const TReal& /*aSrc*/)
  3380 /**
  3381 Calculates the fractional part of a number.
  3382 
  3383 The fractional part is that after a decimal point.
  3384 Truncation is toward zero, so that
  3385 Frac(2.4)=0.4, Frac(2)=0, Frac(-1)=0, Frac(-1.4)=0.4.
  3386 
  3387 @param aTrg A reference containing the result.
  3388 @param aSrc The number whose fractional part is required. 
  3389 
  3390 @return KErrNone if successful, otherwise another of
  3391         the system-wide error codes.
  3392 */
  3393 	{
  3394 	// on entry r0=aTrg, r1=&Src
  3395 	// on exit r0=return code
  3396 #ifdef __DOUBLE_WORDS_SWAPPED__
  3397 	asm("ldmia r1, {r1,r2} ");		// r1,r2=aSrc
  3398 #else
  3399 	asm("ldr r2, [r1, #0] ");
  3400 	asm("ldr r1, [r1, #4] ");
  3401 #endif
  3402 	asm("and r3, r1, #0x80000000 ");
  3403 	asm("str r3, [sp, #-4]! ");		// save sign
  3404 	asm("mov r3, r1, lsr #20 ");
  3405 	asm("bic r3, r3, #0x800 ");		// r3=exponent of aSrc
  3406 	asm("mov r12, #0x300 ");
  3407 	asm("orr r12, r12, #0xFE ");	// r12=0x3FE
  3408 	asm("subs r3, r3, r12 ");		// r3=exponent of aSrc-0x3FE=number of integer bits
  3409 	asm("ble MathFrac0 ");			// if <=0, return aSrc unaltered
  3410 	asm("cmp r3, #53 ");
  3411 	asm("bge MathFrac1 ");			// if >=53 integer bits, there is no fractional part
  3412 	asm("mov r1, r1, lsl #11 ");	// left-justify mantissa in r1,r2
  3413 	asm("orr r1, r1, r2, lsr #21 ");
  3414 	asm("mov r2, r2, lsl #11 ");
  3415 	asm("cmp r3, #32 ");			// check for >=32 integer bits
  3416 	asm("bge MathFrac2 ");
  3417 	asm("rsb r12, r3, #32 ");
  3418 	asm("mov r1, r1, lsl r3 ");		// shift mantissa left by number of integer bits
  3419 	asm("orrs r1, r1, r2, lsr r12 ");
  3420 	asm("mov r2, r2, lsl r3 ");
  3421 	asm("mov r3, #0x300 ");			// r3 holds exponent = 0x3FE initially
  3422 	asm("orr r3, r3, #0xFE ");
  3423 	asm("beq MathFrac3 ");			// branch if >=32 shifts to normalise
  3424 #ifdef __CPU_ARM_HAS_CLZ
  3425 	CLZ(12,1);
  3426 	asm("mov r1, r1, lsl r12 ");
  3427 	asm("rsb r12, r12, #32 ");
  3428 	asm("orr r1, r1, r2, lsr r12 ");
  3429 	asm("rsb r12, r12, #32 ");
  3430 #else
  3431 	asm("mov r12, #32 ");			// else r12=32-number of shifts needed
  3432 	asm("cmp r1, #0x10000 ");		// calculate shift count
  3433 	asm("movcc r1, r1, lsl #16 ");
  3434 	asm("subcc r12, r12, #16 ");
  3435 	asm("cmp r1, #0x1000000 ");
  3436 	asm("movcc r1, r1, lsl #8 ");
  3437 	asm("subcc r12, r12, #8 ");
  3438 	asm("cmp r1, #0x10000000 ");
  3439 	asm("movcc r1, r1, lsl #4 ");
  3440 	asm("subcc r12, r12, #4 ");
  3441 	asm("cmp r1, #0x40000000 ");
  3442 	asm("movcc r1, r1, lsl #2 ");
  3443 	asm("subcc r12, r12, #2 ");
  3444 	asm("cmp r1, #0x80000000 ");
  3445 	asm("movcc r1, r1, lsl #1 ");
  3446 	asm("subcc r12, r12, #1 ");
  3447 	asm("orr r1, r1, r2, lsr r12 ");	// normalise
  3448 	asm("rsb r12, r12, #32 ");			// r12=shift count
  3449 #endif
  3450 	asm("mov r2, r2, lsl r12 ");
  3451 	asm("sub r3, r3, r12 ");			// exponent-=shift count
  3452 	asm("b MathFrac4 ");				// branch to assemble and store result
  3453 
  3454 	// come here if >=32 shifts to normalise
  3455 	asm("MathFrac3: ");
  3456 	asm("sub r3, r3, #32 ");		// decrement exponent by 32
  3457 	asm("movs r1, r2 ");			// shift left by 32, set Z if result zero
  3458 	asm("mov r2, #0 ");
  3459 	asm("bne MathFrac6 ");			// if result nonzero, normalise
  3460 	asm("beq MathFrac5 ");			// branch if result zero
  3461 
  3462 	// come here if >=32 integer bits
  3463 	asm("MathFrac2: ");
  3464 	asm("sub r3, r3, #32 ");
  3465 	asm("movs r1, r2, lsl r3 ");	// shift left by number of integer bits, set Z if result zero
  3466 	asm("mov r2, #0 ");
  3467 	asm("mov r3, #0x300 ");			// r3 holds exponent = 0x3FE initially
  3468 	asm("orr r3, r3, #0xFE ");
  3469 	asm("beq MathFrac5 ");			// branch if result zero
  3470 	asm("MathFrac6: ");
  3471 	asm("cmp r1, #0x10000 ");		// else normalise
  3472 	asm("movcc r1, r1, lsl #16 ");
  3473 	asm("subcc r3, r3, #16 ");
  3474 	asm("cmp r1, #0x1000000 ");
  3475 	asm("movcc r1, r1, lsl #8 ");
  3476 	asm("subcc r3, r3, #8 ");
  3477 	asm("cmp r1, #0x10000000 ");
  3478 	asm("movcc r1, r1, lsl #4 ");
  3479 	asm("subcc r3, r3, #4 ");
  3480 	asm("cmp r1, #0x40000000 ");
  3481 	asm("movcc r1, r1, lsl #2 ");
  3482 	asm("subcc r3, r3, #2 ");
  3483 	asm("cmp r1, #0x80000000 ");
  3484 	asm("movcc r1, r1, lsl #1 ");
  3485 	asm("subcc r3, r3, #1 ");
  3486 
  3487 	// come here to assemble and store result
  3488 	asm("MathFrac4: ");
  3489 	asm("bic r1, r1, #0x80000000 ");	// remove integer bit
  3490 	asm("mov r2, r2, lsr #11 ");		// shift mantissa right by 11
  3491 	asm("orr r2, r2, r1, lsl #21 ");
  3492 	asm("mov r1, r1, lsr #11 ");
  3493 	asm("ldr r12, [sp] ");
  3494 	asm("orr r1, r1, r3, lsl #20 ");	// exponent into r1 bits 20-30
  3495 	asm("orr r1, r1, r12 ");			// sign bit into r1 bit 31
  3496 
  3497 	// come here to return source unaltered
  3498 	asm("MathFrac0: ");
  3499 	asm("add sp, sp, #4 ");
  3500 	asm("MathFrac_ok: ");
  3501 #ifdef __DOUBLE_WORDS_SWAPPED__
  3502 	asm("stmia r0, {r1,r2} ");			// store result
  3503 #else
  3504 	asm("str r2, [r0, #0] ");
  3505 	asm("str r1, [r0, #4] ");
  3506 #endif
  3507 	asm("mov r0, #0 ");					// return KErrNone
  3508 	__JUMP(,lr);
  3509 
  3510 	// come here if infinity, NaN or >=53 integer bits
  3511 	asm("MathFrac1: ");
  3512 	asm("cmp r3, #0x400 ");				// check for infinity/NaN
  3513 	asm("bhi MathFrac7 ");				// branch if so
  3514 
  3515 	// come here to return zero
  3516 	asm("MathFrac5: ");
  3517 	asm("ldr r1, [sp], #4 ");			// r1 bit 31=sign, rest zero
  3518 	asm("mov r2, #0 ");
  3519 	asm("b MathFrac_ok ");
  3520 
  3521 	// come here if infinity/NaN
  3522 	asm("MathFrac7: ");
  3523 	asm("movs r12, r1, lsl #12 ");		// check for infinity
  3524 	asm("cmpeq r2, #0 ");
  3525 	asm("bne MathFrac8 ");				// branch if NaN
  3526 	asm("ldr r1, [sp], #4 ");			// r1 bit 31=sign, rest zero
  3527 	asm("mov r2, #0 ");
  3528 #ifdef __DOUBLE_WORDS_SWAPPED__
  3529 	asm("stmia r0, {r1,r2} ");			// store zero result
  3530 #else
  3531 	asm("str r2, [r0, #0] ");
  3532 	asm("str r1, [r0, #4] ");
  3533 #endif
  3534 	asm("mvn r0, #8 ");					// return KErrOverflow
  3535 	__JUMP(,lr);
  3536 	asm("MathFrac8: ");					// NaN
  3537 	asm("add sp, sp, #4 ");
  3538 #ifdef __DOUBLE_WORDS_SWAPPED__
  3539 	asm("stmia r0, {r1,r2} ");			// store NaN unchanged
  3540 #else
  3541 	asm("str r2, [r0, #0] ");
  3542 	asm("str r1, [r0, #4] ");
  3543 #endif
  3544 	asm("mvn r0, #5 ");					// return KErrArgument
  3545 	__JUMP(,lr);
  3546 	}
  3547 #endif // __USE_VFP_MATH
  3548 #endif
  3549 
  3550 #ifdef __REALS_MACHINE_CODED__
  3551 #ifndef __ARMCC__
  3552 extern "C" {
  3553 
  3554 extern "C" void __math_exception(TInt aErrType);
  3555 __NAKED__ EXPORT_C TReal32 __addsf3(TReal32 /*a1*/, TReal32 /*a2*/)
  3556 //
  3557 // Add two floats
  3558 //
  3559     {
  3560 	// a1 is in r0, a2 in r1 on entry; return with answer in r0
  3561 	asm("stmfd sp!, {r4-r8,lr} ");
  3562 	asm("bl ConvertTReal32ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
  3563 	asm("mov r4, r1 ");					// move into r4,r5,r6
  3564 	asm("mov r5, r2 ");
  3565 	asm("mov r6, r3 ");
  3566 	asm("mov r1, r0 ");					// a1 into r1
  3567 	asm("bl ConvertTReal32ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
  3568 	asm("bl TRealXAdd ");				// add a1+a2, result in r1,r2,r3
  3569 	asm("bl TRealXGetTReal32 ");		// convert result to TReal32 in r0, error code in r12
  3570 	asm("cmp r12, #0 ");				// check error code
  3571 	__CPOPRET(eq,"r4-r8,");
  3572 	asm("stmfd sp!, {r0} ");			// save result
  3573 	asm("mov r0, r12 ");				// error code into r0
  3574 	asm("bl __math_exception ");		// raise exception
  3575 	__POPRET("r0,r4-r8,");
  3576     }
  3577 
  3578 __NAKED__ EXPORT_C TReal64 __adddf3(TReal64 /*a1*/, TReal64 /*a2*/)
  3579 //
  3580 // Add two doubles
  3581 //
  3582     {
  3583 	// a1 is in r0,r1 a2 in r2,r3 on entry; return with answer in r0,r1
  3584 	asm("stmfd sp!, {r4-r8,lr} ");
  3585 	asm("mov r7, r2 ");					// save a2
  3586 	asm("mov r8, r3 ");
  3587 	asm("mov r2, r1 ");					// a1 into r1,r2
  3588 	asm("mov r1, r0 ");
  3589 	asm("bl ConvertTReal64ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
  3590 	asm("mov r4, r1 ");					// move into r4,r5,r6
  3591 	asm("mov r5, r2 ");
  3592 	asm("mov r6, r3 ");
  3593 	asm("mov r1, r7 ");					// a2 into r1,r2
  3594 	asm("mov r2, r8 ");
  3595 	asm("bl ConvertTReal64ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
  3596 	asm("bl TRealXAdd ");				// add a1+a2, result in r1,r2,r3
  3597 	asm("bl TRealXGetTReal64 ");		// convert result to TReal64 in r0,r1 error code in r12
  3598 	asm("cmp r12, #0 ");				// check error code
  3599 	__CPOPRET(eq,"r4-r8,");
  3600 	asm("stmfd sp!, {r0,r1} ");			// save result
  3601 	asm("mov r0, r12 ");				// error code into r0
  3602 	asm("bl __math_exception ");		// raise exception
  3603 	__POPRET("r0,r1,r4-r8,");
  3604     }
  3605 
  3606 __NAKED__ EXPORT_C TReal32 __subsf3(TReal32 /*a1*/, TReal32 /*a2*/)
  3607 //
  3608 // Subtract two floats
  3609 //
  3610     {
  3611 	// a1 is in r0, a2 in r1 on entry; return with answer in r0
  3612 	asm("stmfd sp!, {r4-r8,lr} ");
  3613 	asm("bl ConvertTReal32ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
  3614 	asm("mov r4, r1 ");					// move into r4,r5,r6
  3615 	asm("mov r5, r2 ");
  3616 	asm("mov r6, r3 ");
  3617 	asm("mov r1, r0 ");					// a1 into r1
  3618 	asm("bl ConvertTReal32ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
  3619 	asm("bl TRealXSubtract ");			// subtract a1-a2, result in r1,r2,r3
  3620 	asm("bl TRealXGetTReal32 ");		// convert result to TReal32 in r0, error code in r12
  3621 	asm("cmp r12, #0 ");				// check error code
  3622 	__CPOPRET(eq,"r4-r8,");
  3623 	asm("stmfd sp!, {r0} ");			// save result
  3624 	asm("mov r0, r12 ");				// error code into r0
  3625 	asm("bl __math_exception ");		// raise exception
  3626 	__POPRET("r0,r4-r8,");
  3627 	}
  3628 
  3629 __NAKED__ EXPORT_C TReal64 __subdf3(TReal64 /*a1*/, TReal64 /*a2*/)
  3630 //
  3631 // Subtract two doubles
  3632 //
  3633     {
  3634 	// a1 is in r0,r1 a2 in r2,r3 on entry; return with answer in r0,r1
  3635 	asm("stmfd sp!, {r4-r8,lr} ");
  3636 	asm("mov r7, r0 ");					// save a1
  3637 	asm("mov r8, r1 ");
  3638 	asm("mov r1, r2 ");					// a2 into r1,r2
  3639 	asm("mov r2, r3 ");
  3640 	asm("bl ConvertTReal64ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
  3641 	asm("mov r4, r1 ");					// move into r4,r5,r6
  3642 	asm("mov r5, r2 ");
  3643 	asm("mov r6, r3 ");
  3644 	asm("mov r1, r7 ");					// a1 into r1,r2
  3645 	asm("mov r2, r8 ");
  3646 	asm("bl ConvertTReal64ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
  3647 	asm("bl TRealXSubtract ");			// subtract a1-a2, result in r1,r2,r3
  3648 	asm("bl TRealXGetTReal64 ");		// convert result to TReal64 in r0,r1 error code in r12
  3649 	asm("cmp r12, #0 ");				// check error code
  3650 	__CPOPRET(eq,"r4-r8,");
  3651 	asm("stmfd sp!, {r0,r1} ");			// save result
  3652 	asm("mov r0, r12 ");				// error code into r0
  3653 	asm("bl __math_exception ");		// raise exception
  3654 	__POPRET("r0,r1,r4-r8,");
  3655     }
  3656 
  3657 __NAKED__ EXPORT_C TInt __cmpsf3(TReal32 /*a1*/, TReal32 /*a2*/)
  3658 //
  3659 // Compare two floats
  3660 //
  3661     {
  3662 	// a1 in r0, a2 in r1 on entry
  3663 	asm("stmfd sp!, {lr} ");
  3664 	asm("bl CompareTReal32 ");			// compare the two numbers
  3665 	asm("mov r0, r0, lsl #28 ");
  3666 	asm("msr cpsr_flg, r0 ");			// N=unordered, Z=(a1>a2), C=(a1=a2), V=(a1<a2)
  3667 	asm("mov r0, #0 ");
  3668 	asm("mvnvs r0, #0 ");				// if a1<a2 r0=-1
  3669 	asm("moveq r0, #1 ");				// if a1>a2 r0=+1
  3670 	__POPRET("");
  3671 
  3672 	// Compare two TReal32s in r0, r1.
  3673 	// Return 1 if r0<r1, 2 if r0=r1, 4 if r0>r1, 8 if unordered
  3674 	// Registers r0,r1,r12 modified
  3675 	asm("CompareTReal32: ");
  3676 	asm("mov r12, r0, lsr #23 ");
  3677 	asm("and r12, r12, #0xFF ");		// r12=r0 exponent
  3678 	asm("cmp r12, #0xFF ");				// check if r0 is a NaN
  3679 	asm("bne CompareTReal32a ");
  3680 	asm("movs r12, r0, lsl #9 ");		// exponent=FF, check mantissa
  3681 	asm("movne r0, #8 ");				// if not zero, r0 is a NaN so result is unordered
  3682 	__JUMP(ne,lr);
  3683 	asm("CompareTReal32a: ");
  3684 	asm("mov r12, r1, lsr #23 ");
  3685 	asm("and r12, r12, #0xFF ");		// r12=r1 exponent
  3686 	asm("cmp r12, #0xFF ");				// check if r1 is a NaN
  3687 	asm("bne CompareTReal32b ");
  3688 	asm("movs r12, r1, lsl #9 ");		// exponent=FF, check mantissa
  3689 	asm("movne r0, #8 ");				// if not zero, r1 is a NaN so result is unordered
  3690 	__JUMP(ne,lr);
  3691 	asm("CompareTReal32b: ");
  3692 	asm("bics r12, r0, #0x80000000 ");	// check if r0=0 (can be +0 or -0)
  3693 	asm("moveq r0, #0 ");				// if it is, make it +0
  3694 	asm("bics r12, r1, #0x80000000 ");	// check if r1=0 (can be +0 or -0)
  3695 	asm("moveq r1, #0 ");				// if it is, make it +0
  3696 	asm("teq r0, r1 ");					// test if signs different
  3697 	asm("bmi CompareTReal32c ");		// branch if different
  3698 	asm("cmp r0, r1 ");					// if same, check exponents + mantissas
  3699 	asm("moveq r0, #2 ");				// if equal, return 2
  3700 	__JUMP(eq,lr);
  3701 	asm("movhi r0, #4 ");				// if r0>r1, r0=4
  3702 	asm("movcc r0, #1 ");				// if r0<r1, r0=1
  3703 	asm("cmp r1, #0 ");					// check signs
  3704 	asm("eormi r0, r0, #5 ");			// if negative, switch 1 and 4
  3705 	__JUMP(,lr);
  3706 	asm("CompareTReal32c: ");			// come here if signs different
  3707 	asm("cmp r0, #0 ");					// check sign of r0
  3708 	asm("movpl r0, #4 ");				// if r0 nonnegative, then r0 is greater so return 4
  3709 	asm("movmi r0, #1 ");				// if r0 negative, return 1
  3710 	__JUMP(,lr);
  3711     }
  3712 
  3713 __NAKED__ EXPORT_C TInt __cmpdf3(TReal64 /*a1*/,TReal64 /*a2*/)
  3714 //
  3715 // Compare two doubles
  3716 //
  3717     {
  3718 	// a1 in r0,r1, a2 in r2,r3 on entry
  3719 	asm("stmfd sp!, {lr} ");
  3720 	asm("bl CompareTReal64 ");			// compare the two numbers
  3721 	asm("mov r0, r0, lsl #28 ");
  3722 	asm("msr cpsr_flg, r0 ");			// N=unordered, Z=(a1>a2), C=(a1=a2), V=(a1<a2)
  3723 	asm("mov r0, #0 ");
  3724 	asm("mvnvs r0, #0 ");				// if a1<a2 r0=-1
  3725 	asm("moveq r0, #1 ");				// if a1>a2 r0=+1
  3726 	__POPRET("");
  3727 
  3728 	// Compare two TReal64s in r0,r1 and r2,r3.
  3729 	// Return 1 if r0,r1<r2,r3
  3730 	// Return 2 if r0,r1=r2,r3
  3731 	// Return 4 if r0,r1>r2,r3
  3732 	// Return 8 if unordered
  3733 	// Registers r0,r1,r12 modified
  3734 	asm("CompareTReal64: ");
  3735 #ifndef __DOUBLE_WORDS_SWAPPED__
  3736 	asm("mov r12, r0 ");
  3737 	asm("mov r0, r1 ");
  3738 	asm("mov r1, r12 ");
  3739 	asm("mov r12, r2 ");
  3740 	asm("mov r2, r3 ");
  3741 	asm("mov r3, r12 ");
  3742 #endif
  3743 	asm("mov r12, r0, lsr #20 ");
  3744 	asm("bic r12, r12, #0x800 ");		// r12=first operand exponent
  3745 	asm("add r12, r12, #1 ");			// add 1 to get usable compare value
  3746 	asm("cmp r12, #0x800 ");			// check if first operand is a NaN
  3747 	asm("bne CompareTReal64a ");
  3748 	asm("movs r12, r0, lsl #12 ");		// exponent=7FF, check mantissa
  3749 	asm("cmpeq r1, #0 ");
  3750 	asm("movne r0, #8 ");				// if not zero, 1st op is a NaN so result is unordered
  3751 	__JUMP(ne,lr);
  3752 	asm("CompareTReal64a: ");
  3753 	asm("mov r12, r2, lsr #20 ");
  3754 	asm("bic r12, r12, #0x800 ");		// r12=second operand exponent
  3755 	asm("add r12, r12, #1 ");			// add 1 to get usable compare value
  3756 	asm("cmp r12, #0x800 ");			// check if second operand is a NaN
  3757 	asm("bne CompareTReal64b ");
  3758 	asm("movs r12, r2, lsl #12 ");		// exponent=7FF, check mantissa
  3759 	asm("cmpeq r3, #0 ");
  3760 	asm("movne r0, #8 ");				// if not zero, 2nd op is a NaN so result is unordered
  3761 	__JUMP(ne,lr);
  3762 	asm("CompareTReal64b: ");
  3763 	asm("bics r12, r0, #0x80000000 ");	// check if first operand is zero (can be +0 or -0)
  3764 	asm("cmpeq r1, #0 ");
  3765 	asm("moveq r0, #0 ");				// if it is, make it +0
  3766 	asm("bics r12, r2, #0x80000000 ");	// check if second operand is zero (can be +0 or -0)
  3767 	asm("cmpeq r3, #0 ");
  3768 	asm("moveq r2, #0 ");				// if it is, make it +0
  3769 	asm("teq r0, r2 ");					// test if signs different
  3770 	asm("bmi CompareTReal64c ");		// branch if different
  3771 	asm("cmp r0, r2 ");					// if same, check exponents + mantissas
  3772 	asm("cmpeq r1, r3 ");
  3773 	asm("moveq r0, #2 ");				// if equal, return 2
  3774 	__JUMP(eq,lr);
  3775 	asm("movhi r0, #4 ");				// if 1st operand > 2nd operand, r0=4
  3776 	asm("movcc r0, #1 ");				// if 1st operand < 2nd operand, r0=1
  3777 	asm("cmp r2, #0 ");					// check signs
  3778 	asm("eormi r0, r0, #5 ");			// if negative, switch 1 and 4
  3779 	__JUMP(,lr);
  3780 	asm("CompareTReal64c: ");			// come here if signs different
  3781 	asm("cmp r0, #0 ");					// check sign of r0
  3782 	asm("movpl r0, #4 ");				// if first operand nonnegative, return 4
  3783 	asm("movmi r0, #1 ");				// if first operand negative, return 1
  3784 	__JUMP(,lr);
  3785     }
  3786 
  3787 __NAKED__ EXPORT_C TInt __eqsf2(TReal32 /*a1*/, TReal32 /*a2*/)
  3788 //
  3789 // Compare if two floats are equal
  3790 //
  3791     {
  3792 	// a1 in r0, a2 in r1 on entry
  3793 	asm("stmfd sp!, {lr} ");
  3794 	asm("bl CompareTReal32 ");			// compare the two numbers
  3795 	asm("tst r0, #2 ");
  3796 	asm("movne r0, #0 ");				// if ordered and equal return 0
  3797 	asm("moveq r0, #1 ");				// else return 1
  3798 	__POPRET("");
  3799     }
  3800 
  3801 __NAKED__ EXPORT_C TInt __eqdf2(TReal64 /*a1*/, TReal64 /*a2*/)
  3802 //
  3803 // Compare if two doubles are equal
  3804 //
  3805     {
  3806 	// a1 in r0,r1, a2 in r2,r3 on entry
  3807 	asm("stmfd sp!, {lr} ");
  3808 	asm("bl CompareTReal64 ");			// compare the two numbers
  3809 	asm("tst r0, #2 ");
  3810 	asm("movne r0, #0 ");				// if ordered and equal return 0
  3811 	asm("moveq r0, #1 ");				// else return 1
  3812 	__POPRET("");
  3813     }
  3814 
  3815 __NAKED__ EXPORT_C TInt __nesf2(TReal32 /*a1*/, TReal32 /*a2*/)
  3816 //
  3817 // Compare if two floats are not equal
  3818 //
  3819     {
  3820 	// a1 in r0, a2 in r1 on entry
  3821 	asm("stmfd sp!, {lr} ");
  3822 	asm("bl CompareTReal32 ");			// compare the two numbers
  3823 	asm("tst r0, #5 ");					// test if ordered and unequal
  3824 	asm("moveq r0, #0 ");				// if equal or unordered return 0
  3825 	asm("movne r0, #1 ");				// if ordered and unequal return 1
  3826 	__POPRET("");
  3827     }
  3828 
  3829 __NAKED__ EXPORT_C TInt __nedf2(TReal64 /*a1*/, TReal64 /*a2*/)
  3830 //
  3831 // Compare if two doubles are not equal
  3832 //
  3833     {
  3834 	// a1 in r0,r1, a2 in r2,r3 on entry
  3835 	asm("stmfd sp!, {lr} ");
  3836 	asm("bl CompareTReal64 ");			// compare the two numbers
  3837 	asm("tst r0, #5 ");					// test if ordered and unequal
  3838 	asm("moveq r0, #0 ");				// if equal or unordered return 0
  3839 	asm("movne r0, #1 ");				// if ordered and unequal return 1
  3840 	__POPRET("");
  3841     }
  3842 
  3843 __NAKED__ EXPORT_C TInt __gtsf2(TReal32 /*a1*/, TReal32 /*a2*/)
  3844 //
  3845 // Compare if one float is greater than another
  3846 //
  3847     {
  3848 	// a1 in r0, a2 in r1 on entry
  3849 	asm("stmfd sp!, {lr} ");
  3850 	asm("bl CompareTReal32 ");			// compare the two numbers
  3851 	asm("tst r0, #4 ");					// test if ordered and a1>a2
  3852 	asm("movne r0, #1 ");				// if ordered and a1>a2 return +1
  3853 	asm("mvneq r0, #0 ");				// else return -1
  3854 	__POPRET("");
  3855     }
  3856 
  3857 __NAKED__ EXPORT_C TInt __gtdf2(TReal64 /*a1*/, TReal64 /*a2*/)
  3858 //
  3859 // Compare if one double is greater than another
  3860 //
  3861     {
  3862 	// a1 in r0,r1, a2 in r2,r3 on entry
  3863 	asm("stmfd sp!, {lr} ");
  3864 	asm("bl CompareTReal64 ");			// compare the two numbers
  3865 	asm("tst r0, #4 ");					// test if ordered and a1>a2
  3866 	asm("movne r0, #1 ");				// if ordered and a1>a2 return +1
  3867 	asm("mvneq r0, #0 ");				// else return -1
  3868 	__POPRET("");
  3869     }
  3870 
  3871 __NAKED__ EXPORT_C TInt __gesf2(TReal32 /*a1*/, TReal32 /*a2*/)
  3872 //
  3873 // Compare if one float is greater than or equal to another
  3874 //
  3875     {
  3876 	// a1 in r0, a2 in r1 on entry
  3877 	asm("stmfd sp!, {lr} ");
  3878 	asm("bl CompareTReal32 ");			// compare the two numbers
  3879 	asm("tst r0, #6 ");					// test if ordered and a1>=a2
  3880 	asm("movne r0, #1 ");				// if ordered and a1>=a2 return +1
  3881 	asm("mvneq r0, #0 ");				// else return -1
  3882 	__POPRET("");
  3883     }
  3884 
  3885 __NAKED__ EXPORT_C TInt __gedf2(TReal64 /*a1*/, TReal64 /*a2*/)
  3886 //
  3887 // Compare if one double is greater than or equal to another
  3888 //
  3889     {
  3890 	// a1 in r0,r1, a2 in r2,r3 on entry
  3891 	asm("stmfd sp!, {lr} ");
  3892 	asm("bl CompareTReal64 ");			// compare the two numbers
  3893 	asm("tst r0, #6 ");					// test if ordered and a1>=a2
  3894 	asm("movne r0, #1 ");				// if ordered and a1>=a2 return +1
  3895 	asm("mvneq r0, #0 ");				// else return -1
  3896 	__POPRET("");
  3897     }
  3898 
  3899 __NAKED__ EXPORT_C TInt __ltsf2(TReal32 /*a1*/, TReal32 /*a2*/)
  3900 //
  3901 // Compare if one float is less than another
  3902 //
  3903     {
  3904 	// a1 in r0, a2 in r1 on entry
  3905 	asm("stmfd sp!, {lr} ");
  3906 	asm("bl CompareTReal32 ");			// compare the two numbers
  3907 	asm("tst r0, #1 ");					// test if ordered and a1<a2
  3908 	asm("mvnne r0, #0 ");				// if ordered and a1<a2 return -1
  3909 	asm("moveq r0, #1 ");				// else return +1
  3910 	__POPRET("");
  3911     }
  3912 
  3913 __NAKED__ EXPORT_C TInt __ltdf2(TReal64 /*a1*/, TReal64 /*a2*/)
  3914 //
  3915 // Compare if one double is less than another
  3916 //
  3917     {
  3918 	// a1 in r0,r1, a2 in r2,r3 on entry
  3919 	asm("stmfd sp!, {lr} ");
  3920 	asm("bl CompareTReal64 ");			// compare the two numbers
  3921 	asm("tst r0, #1 ");					// test if ordered and a1<a2
  3922 	asm("mvnne r0, #0 ");				// if ordered and a1<a2 return -1
  3923 	asm("moveq r0, #1 ");				// else return +1
  3924 	__POPRET("");
  3925     }
  3926 
  3927 __NAKED__ EXPORT_C TInt __lesf2(TReal32 /*a1*/, TReal32 /*a2*/)
  3928 //
  3929 // Compare if one float is less than or equal to another
  3930 //
  3931     {
  3932 	// a1 in r0, a2 in r1 on entry
  3933 	asm("stmfd sp!, {lr} ");
  3934 	asm("bl CompareTReal32 ");			// compare the two numbers
  3935 	asm("tst r0, #3 ");					// test if ordered and a1<=a2
  3936 	asm("mvnne r0, #0 ");				// if ordered and a1<=a2 return -1
  3937 	asm("moveq r0, #1 ");				// else return +1
  3938 	__POPRET("");
  3939     }
  3940 
  3941 __NAKED__ EXPORT_C TInt __ledf2(TReal64 /*a1*/, TReal64 /*a2*/)
  3942 //
  3943 // Compare if one double is less than or equal to another
  3944 //
  3945     {
  3946 	// a1 in r0,r1, a2 in r2,r3 on entry
  3947 	asm("stmfd sp!, {lr} ");
  3948 	asm("bl CompareTReal64 ");			// compare the two numbers
  3949 	asm("tst r0, #3 ");					// test if ordered and a1<=a2
  3950 	asm("mvnne r0, #0 ");				// if ordered and a1<=a2 return -1
  3951 	asm("moveq r0, #1 ");				// else return +1
  3952 	__POPRET("");
  3953     }
  3954 
  3955 __NAKED__ EXPORT_C TReal32 __mulsf3(TReal32 /*a1*/,TReal32 /*a2*/)
  3956 //
  3957 // Multiply two floats
  3958 //
  3959     {
  3960 	// a1 is in r0, a2 in r1 on entry; return with answer in r0
  3961 	asm("stmfd sp!, {r4-r7,lr} ");
  3962 	asm("bl ConvertTReal32ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
  3963 	asm("mov r4, r1 ");					// move into r4,r5,r6
  3964 	asm("mov r5, r2 ");
  3965 	asm("mov r6, r3 ");
  3966 	asm("mov r1, r0 ");					// a1 into r1
  3967 	asm("bl ConvertTReal32ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
  3968 	asm("bl TRealXMultiply ");			// multiply a1*a2, result in r1,r2,r3
  3969 	asm("bl TRealXGetTReal32 ");		// convert result to TReal32 in r0, error code in r12
  3970 	asm("cmp r12, #0 ");				// check error code
  3971 	__CPOPRET(eq,"r4-r7,");
  3972 	asm("stmfd sp!, {r0} ");			// save result
  3973 	asm("mov r0, r12 ");				// error code into r0
  3974 	asm("bl __math_exception ");		// raise exception
  3975 	__POPRET("r0,r4-r7,");
  3976     }
  3977 
  3978 __NAKED__ EXPORT_C TReal64 __muldf3(TReal64 /*a1*/, TReal64 /*a2*/)
  3979 //
  3980 // Multiply two doubles
  3981 //
  3982     {
  3983 	// a1 is in r0,r1 a2 in r2,r3 on entry; return with answer in r0,r1
  3984 	asm("stmfd sp!, {r4-r8,lr} ");
  3985 	asm("mov r7, r2 ");					// save a2
  3986 	asm("mov r8, r3 ");
  3987 	asm("mov r2, r1 ");					// a1 into r1,r2
  3988 	asm("mov r1, r0 ");
  3989 	asm("bl ConvertTReal64ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
  3990 	asm("mov r4, r1 ");					// move into r4,r5,r6
  3991 	asm("mov r5, r2 ");
  3992 	asm("mov r6, r3 ");
  3993 	asm("mov r1, r7 ");					// a2 into r1,r2
  3994 	asm("mov r2, r8 ");
  3995 	asm("bl ConvertTReal64ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
  3996 	asm("bl TRealXMultiply ");			// multiply a1*a2, result in r1,r2,r3
  3997 	asm("bl TRealXGetTReal64 ");		// convert result to TReal64 in r0,r1 error code in r12
  3998 	asm("cmp r12, #0 ");				// check error code
  3999 	__CPOPRET(eq,"r4-r8,");
  4000 	asm("stmfd sp!, {r0,r1} ");			// save result
  4001 	asm("mov r0, r12 ");				// error code into r0
  4002 	asm("bl __math_exception ");		// raise exception
  4003 	__POPRET("r0,r1,r4-r8,");
  4004     }
  4005 
  4006 __NAKED__ EXPORT_C TReal32 __divsf3(TReal32 /*a1*/, TReal32 /*a2*/)
  4007 //
  4008 // Divide two floats
  4009 //
  4010     {
  4011 	// a1 is in r0, a2 in r1 on entry; return with answer in r0
  4012 	asm("stmfd sp!, {r4-r9,lr} ");
  4013 	asm("bl ConvertTReal32ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
  4014 	asm("mov r4, r1 ");					// move into r4,r5,r6
  4015 	asm("mov r5, r2 ");
  4016 	asm("mov r6, r3 ");
  4017 	asm("mov r1, r0 ");					// a1 into r1
  4018 	asm("bl ConvertTReal32ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
  4019 	asm("bl TRealXDivide ");			// divide a1/a2, result in r1,r2,r3 error code in r12
  4020 	asm("mov r9, r12 ");				// save error code in case it's division by zero
  4021 	asm("bl TRealXGetTReal32 ");		// convert result to TReal32 in r0, error code in r12
  4022 	asm("cmn r9, #41 ");				// check for KErrDivideByZero
  4023 	asm("moveq r12, r9 ");
  4024 	asm("cmp r12, #0 ");				// check error code
  4025 	__CPOPRET(eq,"r4-r9,");
  4026 	asm("stmfd sp!, {r0} ");			// save result
  4027 	asm("mov r0, r12 ");				// error code into r0
  4028 	asm("bl __math_exception ");		// raise exception
  4029 	__POPRET("r0,r4-r9,");
  4030     }
  4031 
  4032 __NAKED__ EXPORT_C TReal64 __divdf3(TReal64 /*a1*/, TReal64 /*a2*/)
  4033 	//
  4034 	// Divide two doubles
  4035 	//
  4036 	{
  4037 	// a1 is in r0,r1 a2 in r2,r3 on entry; return with answer in r0,r1
  4038 	asm("stmfd sp!, {r4-r9,lr} ");
  4039 	asm("mov r7, r0 ");					// save a1
  4040 	asm("mov r8, r1 ");
  4041 	asm("mov r1, r2 ");					// a2 into r1,r2
  4042 	asm("mov r2, r3 ");
  4043 	asm("bl ConvertTReal64ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
  4044 	asm("mov r4, r1 ");					// move into r4,r5,r6
  4045 	asm("mov r5, r2 ");
  4046 	asm("mov r6, r3 ");
  4047 	asm("mov r1, r7 ");					// a1 into r1,r2
  4048 	asm("mov r2, r8 ");
  4049 	asm("bl ConvertTReal64ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
  4050 	asm("bl TRealXDivide ");			// divide a1/a2, result in r1,r2,r3
  4051 	asm("mov r9, r12 ");				// save error code in case it's division by zero
  4052 	asm("bl TRealXGetTReal64 ");		// convert result to TReal64 in r0,r1 error code in r12
  4053 	asm("cmn r9, #41 ");				// check for KErrDivideByZero
  4054 	asm("moveq r12, r9 ");
  4055 	asm("cmp r12, #0 ");				// check error code
  4056 	__CPOPRET(eq,"r4-r9,");
  4057 	asm("stmfd sp!, {r0,r1} ");			// save result
  4058 	asm("mov r0, r12 ");				// error code into r0
  4059 	asm("bl __math_exception ");		// raise exception
  4060 	__POPRET("r0,r1,r4-r9,");
  4061 	}
  4062 
  4063 __NAKED__ EXPORT_C TReal32 __negsf2(TReal32 /*a1*/)
  4064 //
  4065 // Negate a float
  4066 //
  4067     {
  4068 	// a1 in r0 on entry, return value in r0
  4069 	asm("eor r0, r0, #0x80000000 ");	// change sign bit
  4070 	__JUMP(,lr);
  4071     }
  4072 
  4073 __NAKED__ EXPORT_C TReal64 __negdf2(TReal64 /*a1*/)
  4074 //
  4075 // Negate a double
  4076 //
  4077     {
  4078 	// a1 in r0,r1 on entry, return value in r0,r1
  4079 	asm("eor r0, r0, #0x80000000 ");	// change sign bit
  4080 	__JUMP(,lr);
  4081     }
  4082 
  4083 __NAKED__ EXPORT_C TReal32 __floatsisf(TInt /*a1*/)
  4084 //
  4085 // Convert int to float
  4086 //
  4087     {
  4088 	// a1 in r0 on entry, return value in r0
  4089 	asm("cmp r0, #0 ");					// test for zero or negative
  4090 	__JUMP(eq,lr);
  4091 	asm("and ip, r0, #0x80000000 ");	// ip=bit 31 of r0 (sign bit)
  4092 	asm("rsbmi r0, r0, #0 ");			// if negative, negate it
  4093 	asm("mov r2, #0x9E ");				// r2=0x9E=exponent of 2^31
  4094 	asm("cmp r0, #0x00010000 ");		// normalise integer, adjusting exponent
  4095 	asm("movcc r0, r0, lsl #16 ");
  4096 	asm("subcc r2, r2, #16 ");
  4097 	asm("cmp r0, #0x01000000 ");
  4098 	asm("movcc r0, r0, lsl #8 ");
  4099 	asm("subcc r2, r2, #8 ");
  4100 	asm("cmp r0, #0x10000000 ");
  4101 	asm("movcc r0, r0, lsl #4 ");
  4102 	asm("subcc r2, r2, #4 ");
  4103 	asm("cmp r0, #0x40000000 ");
  4104 	asm("movcc r0, r0, lsl #2 ");
  4105 	asm("subcc r2, r2, #2 ");
  4106 	asm("cmp r0, #0x80000000 ");
  4107 	asm("movcc r0, r0, lsl #1 ");
  4108 	asm("subcc r2, r2, #1 ");
  4109 	asm("and r1, r0, #0xFF ");			// r1=bottom 8 bits=rounding bits
  4110 	asm("cmp r1, #0x80 ");				// check if we need to round up (carry=1 if we do)
  4111 	asm("moveqs r1, r0, lsr #9 ");		// if bottom 8 bits=0x80, set carry=LSB of mantissa
  4112 	asm("addcss r0, r0, #0x100 ");		// round up if necessary
  4113 	asm("addcs r2, r2, #1 ");			// if carry, increment exponent
  4114 	asm("bic r0, r0, #0x80000000 ");	// remove top bit (integer bit of mantissa implicit)
  4115 	asm("mov r0, r0, lsr #8 ");			// mantissa into r0 bits 0-22
  4116 	asm("orr r0, r0, r2, lsl #23 ");	// exponent into r0 bits 23-30
  4117 	asm("orr r0, r0, ip ");				// sign bit into r0 bit 31
  4118 	__JUMP(,lr);
  4119     }
  4120 
  4121 __NAKED__ EXPORT_C TReal64 __floatsidf(TInt /*a1*/)
  4122 //
  4123 // Convert int to double
  4124 //
  4125     {
  4126 	// a1 in r0 on entry, return value in r0,r1
  4127 	asm("cmp r0, #0 ");					// test for zero or negative
  4128 	asm("moveq r1, #0 ");				// if zero, return 0
  4129 	__JUMP(eq,lr);
  4130 	asm("and ip, r0, #0x80000000 ");	// ip=bit 31 of r0 (sign bit)
  4131 	asm("rsbmi r0, r0, #0 ");			// if negative, negate it
  4132 	asm("mov r2, #0x400 ");				// r2=0x41E=exponent of 2^31
  4133 	asm("orr r2, r2, #0x1E ");
  4134 	asm("cmp r0, #0x00010000 ");		// normalise integer, adjusting exponent
  4135 	asm("movcc r0, r0, lsl #16 ");
  4136 	asm("subcc r2, r2, #16 ");
  4137 	asm("cmp r0, #0x01000000 ");
  4138 	asm("movcc r0, r0, lsl #8 ");
  4139 	asm("subcc r2, r2, #8 ");
  4140 	asm("cmp r0, #0x10000000 ");
  4141 	asm("movcc r0, r0, lsl #4 ");
  4142 	asm("subcc r2, r2, #4 ");
  4143 	asm("cmp r0, #0x40000000 ");
  4144 	asm("movcc r0, r0, lsl #2 ");
  4145 	asm("subcc r2, r2, #2 ");
  4146 	asm("cmp r0, #0x80000000 ");
  4147 	asm("movcc r0, r0, lsl #1 ");
  4148 	asm("subcc r2, r2, #1 ");
  4149 	asm("bic r0, r0, #0x80000000 ");	// remove top bit (integer bit of mantissa implicit)
  4150 	asm("mov r1, r0, lsl #21 ");		// low 11 bits of mantissa into r1
  4151 	asm("mov r0, r0, lsr #11 ");		// high 20 bits of mantissa into r0 bits 0-19
  4152 	asm("orr r0, r0, r2, lsl #20 ");	// exponent into r0 bits 20-30
  4153 	asm("orr r0, r0, ip ");				// sign bit into r0 bit 31
  4154 #ifndef __DOUBLE_WORDS_SWAPPED__
  4155 	asm("mov ip, r0 ");
  4156 	asm("mov r0, r1 ");
  4157 	asm("mov r1, ip ");
  4158 #endif
  4159 	__JUMP(,lr);
  4160     }
  4161 
  4162 __NAKED__ EXPORT_C TInt __fixsfsi(TReal32 /*a1*/)
  4163 //
  4164 // Convert float to int
  4165 //
  4166     {
  4167 	// a1 in r0 on entry, return value in r0
  4168 	asm("mov r1, r0, lsr #23 ");
  4169 	asm("and r1, r1, #0xFF ");			// r1=exponent of a1
  4170 	asm("cmp r1, #0xFF ");				// check for NaN
  4171 	asm("bne fixsfsi1 ");
  4172 	asm("movs r2, r0, lsl #9 ");		// exponent=FF, check mantissa
  4173 	asm("movne r0, #0 ");				// if non-zero, a1 is a NaN so return 0
  4174 	__JUMP(ne,lr);
  4175 	asm("fixsfsi1: ");
  4176 	asm("rsbs r1, r1, #0x9E ");			// r1=number of shifts to produce integer
  4177 	asm("ble fixsfsi2 ");				// if <=0, saturate result
  4178 	asm("cmp r0, #0 ");					// check sign bit
  4179 	asm("orr r0, r0, #0x00800000 ");	// set implicit integer bit
  4180 	asm("mov r0, r0, lsl #8 ");			// shift mantissa up so MSB is in MSB of r0
  4181 	asm("mov r0, r0, lsr r1 ");			// r0=absolute integer
  4182 	asm("rsbmi r0, r0, #0 ");			// if negative, negate
  4183 	__JUMP(,lr);
  4184 	asm("fixsfsi2: ");
  4185 	asm("cmp r0, #0 ");					// check sign
  4186 	asm("mov r0, #0x80000000 ");
  4187 	asm("subpl r0, r0, #1 ");			// if -ve return 80000000, if +ve return 7FFFFFFF
  4188 	__JUMP(,lr);
  4189     }
  4190 
  4191 __NAKED__ EXPORT_C TInt __fixdfsi(TReal64 /*a1*/)
  4192 //
  4193 // Convert double to int
  4194 //
  4195     {
  4196 	// a1 in r0,r1 on entry, return value in r0
  4197 #ifndef __DOUBLE_WORDS_SWAPPED__
  4198 	asm("mov r2, r0 ");
  4199 	asm("mov r0, r1 ");
  4200 	asm("mov r1, r2 ");
  4201 #endif
  4202 	asm("mov r2, r0, lsr #20 ");
  4203 	asm("bic r2, r2, #0x800 ");			// r1=exponent of a1
  4204 	asm("add r3, r2, #1 ");
  4205 	asm("cmp r3, #0x800 ");				// check for NaN
  4206 	asm("bne fixdfsi1 ");
  4207 	asm("movs r3, r0, lsl #12 ");		// exponent=FF, check mantissa
  4208 	asm("cmpeq r1, #0 ");
  4209 	asm("movne r0, #0 ");				// if non-zero, a1 is a NaN so return 0
  4210 	__JUMP(ne,lr);
  4211 	asm("fixdfsi1: ");
  4212 	asm("mov r3, #0x400 ");
  4213 	asm("orr r3, r3, #0x1E ");			// r3=0x41E (exponent of 2^31)
  4214 	asm("subs r2, r3, r2 ");			// r2=number of shifts to produce integer
  4215 	asm("ble fixdfsi2 ");				// if <=0, saturate result
  4216 	asm("cmp r2, #31 ");				// check if more than 31 shifts needed
  4217 	asm("movhi r0, #0 ");				// if so, underflow result to 0
  4218 	__JUMP(hi,lr);
  4219 	asm("cmp r0, #0 ");					// check sign bit
  4220 	asm("orr r0, r0, #0x00100000 ");	// set implicit integer bit
  4221 	asm("mov r0, r0, lsl #11 ");		// shift mantissa up so MSB is in MSB of r0
  4222 	asm("orr r0, r0, r1, lsr #21 ");	// put in bits from r1
  4223 	asm("mov r0, r0, lsr r2 ");			// r0=absolute integer
  4224 	asm("rsbmi r0, r0, #0 ");			// if negative, negate
  4225 	__JUMP(,lr);
  4226 	asm("fixdfsi2: ");
  4227 	asm("cmp r0, #0 ");					// check sign
  4228 	asm("mov r0, #0x80000000 ");
  4229 	asm("subpl r0, r0, #1 ");			// if -ve return 80000000, if +ve return 7FFFFFFF
  4230 	__JUMP(,lr);
  4231     }
  4232 
  4233 __NAKED__ EXPORT_C TReal64 __extendsfdf2(TReal32 /*a1*/)
  4234 //
  4235 // Convert a float to a double
  4236 //
  4237     {
  4238 	// a1 in r0, return in r0,r1
  4239 	asm("mov r3, r0, lsr #3 ");
  4240 	asm("ands r3, r3, #0x0FF00000 ");	// r3 bits 20-27 hold exponent, Z=1 if zero/denormal
  4241 	asm("mov r1, r0, lsl #9 ");			// r1 = TReal32 mantissa << 9
  4242 	asm("and r0, r0, #0x80000000 ");	// leave only sign bit in r0
  4243 	asm("beq extendsfdf2a ");			// branch if zero/denormal
  4244 	asm("cmp r3, #0x0FF00000 ");		// check for infinity or NaN
  4245 	asm("orrcs r3, r3, #0x70000000 ");	// if infinity or NaN, exponent = 7FF
  4246 	asm("addcc r3, r3, #0x38000000 ");	// else exponent = TReal32 exponent + 380
  4247 	asm("orr r0, r0, r1, lsr #12 ");	// top 20 mantissa bits into r0 bits 0-19
  4248 	asm("mov r1, r1, lsl #20 ");		// remaining mantissa bits in r1 bits 29-31
  4249 	asm("orr r0, r0, r3 ");				// exponent into r0 bits 20-30
  4250 	asm("b 0f ");
  4251 	asm("extendsfdf2a: ");				// come here if zero or denormal
  4252 	asm("cmp r1, #0 ");					// check for zero
  4253 	asm("beq 0f ");
  4254 	asm("mov r3, #0x38000000 ");		// else exponent = 380 (highest denormal exponent)
  4255 	asm("cmp r1, #0x10000 ");			// normalise mantissa, decrementing exponent as needed
  4256 	asm("movcc r1, r1, lsl #16 ");
  4257 	asm("subcc r3, r3, #0x01000000 ");
  4258 	asm("cmp r1, #0x1000000 ");
  4259 	asm("movcc r1, r1, lsl #8 ");
  4260 	asm("subcc r3, r3, #0x00800000 ");
  4261 	asm("cmp r1, #0x10000000 ");
  4262 	asm("movcc r1, r1, lsl #4 ");
  4263 	asm("subcc r3, r3, #0x00400000 ");
  4264 	asm("cmp r1, #0x40000000 ");
  4265 	asm("movcc r1, r1, lsl #2 ");
  4266 	asm("subcc r3, r3, #0x00200000 ");
  4267 	asm("cmp r1, #0x80000000 ");
  4268 	asm("movcc r1, r1, lsl #1 ");
  4269 	asm("subcc r3, r3, #0x00100000 ");
  4270 	asm("add r1, r1, r1 ");				// shift mantissa left one more to remove integer bit
  4271 	asm("orr r0, r0, r1, lsr #12 ");	// top 20 mantissa bits into r0 bits 0-19
  4272 	asm("mov r1, r1, lsl #20 ");		// remaining mantissa bits in r1 bits 29-31
  4273 	asm("orr r0, r0, r3 ");				// exponent into r0 bits 20-30
  4274 	asm("0: ");
  4275 #ifndef __DOUBLE_WORDS_SWAPPED__
  4276 	asm("mov r3, r0 ");
  4277 	asm("mov r0, r1 ");
  4278 	asm("mov r1, r3 ");
  4279 #endif
  4280 	__JUMP(,lr);
  4281     }
  4282 
  4283 __NAKED__ EXPORT_C TReal32 __truncdfsf2(TReal64 /*a1*/)
  4284 //
  4285 // Convert a double to a float
  4286 // Raises an exception if conversion results in an error
  4287 //
  4288     {
  4289 	asm("stmfd sp!, {lr} ");
  4290 	asm("bl TReal64GetTReal32 ");			// do the conversion
  4291 	asm("cmp r12, #0 ");					// check error code
  4292 	__CPOPRET(eq,"");
  4293 	asm("stmfd sp!, {r0} ");				// else save result
  4294 	asm("mov r0, r12 ");					// error code into r0
  4295 	asm("bl __math_exception ");			// raise exception
  4296 	__POPRET("r0,");
  4297 
  4298 	// Convert TReal64 in r0,r1 to TReal32 in r0
  4299 	// Return error code in r12
  4300 	// r0-r3, r12 modified
  4301 	// NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE.
  4302 	asm("TReal64GetTReal32: ");
  4303 #ifndef __DOUBLE_WORDS_SWAPPED__
  4304 	asm("mov r2, r0 ");
  4305 	asm("mov r0, r1 ");
  4306 	asm("mov r1, r2 ");
  4307 #endif
  4308 	asm("mov r12, r0, lsr #20 ");
  4309 	asm("bic r12, r12, #0x800 ");			// r12=a1 exponent
  4310 	asm("sub r12, r12, #0x380 ");			// r12=exp in - 380 = result exponent if in range
  4311 	asm("cmp r12, #0xFF ");					// check if input exponent too big for TReal32
  4312 	asm("bge TReal64GetTReal32a ");			// branch if it is
  4313 	asm("mov r2, r0, lsl #11 ");			// left justify mantissa in r2:r1
  4314 	asm("orr r2, r2, r1, lsr #21 ");
  4315 	asm("mov r1, r1, lsl #11 ");
  4316 	asm("orr r2, r2, #0x80000000 ");		// set implied integer bit in mantissa
  4317 	asm("cmp r12, #0 ");
  4318 	asm("bgt TReal64GetTReal32b ");			// branch if normalised result
  4319 	asm("cmn r12, #23 ");					// check for total underflow or zero
  4320 	asm("bge TReal64GetTReal32e ");			// skip if not
  4321 	asm("bics r2, r0, #0x80000000 ");		// check if input value zero
  4322 	asm("cmpeq r1, #0 ");
  4323 	asm("moveq r12, #0 ");					// if zero return KErrNone
  4324 	asm("mvnne r12, #9 ");					// else return KErrUnderflow
  4325 	asm("and r0, r0, #0x80000000 ");		// return zero of appropriate sign
  4326 	asm("mov r1, #0 ");
  4327 	__JUMP(,lr);
  4328 	asm("TReal64GetTReal32e: ");			// result will be a denormal
  4329 	asm("add r12, r12, #31 ");				// r12=32-mantissa shift required = 32-(1-r12)
  4330 	asm("movs r3, r1, lsl r12 ");			// r3=lost bits when r2:r1 is shifted
  4331 	asm("orrne lr, lr, #1 ");				// if these are not zero, set rounded down flag
  4332 	asm("rsb r3, r12, #32 ");
  4333 	asm("mov r1, r1, lsr r3 ");
  4334 	asm("orr r1, r1, r2, lsl r12 ");
  4335 	asm("mov r2, r2, lsr r3 ");				// r2 top 24 bits now give unrounded result mantissa
  4336 	asm("mov r12, #0 ");					// result exponent will be zero
  4337 	asm("TReal64GetTReal32b: ");
  4338 	asm("movs r3, r2, lsl #24 ");			// top 8 truncated bits into top byte of r3
  4339 	asm("bpl TReal64GetTReal32c ");			// if top bit clear, truncate
  4340 	asm("cmp r3, #0x80000000 ");
  4341 	asm("cmpeq r1, #0 ");					// compare rounding bits to 1000...
  4342 	asm("bhi TReal64GetTReal32d ");			// if >, round up
  4343 	asm("tst lr, #1 ");						// check rounded-down flag
  4344 	asm("bne TReal64GetTReal32d ");			// if rounded down, round up
  4345 	asm("tst r2, #0x100 ");					// else round to even - test LSB of result mantissa
  4346 	asm("beq TReal64GetTReal32c ");			// if zero, truncate, else round up
  4347 	asm("TReal64GetTReal32d: ");			// come here to round up
  4348 	asm("adds r2, r2, #0x100 ");			// increment the mantissa
  4349 	asm("movcs r2, #0x80000000 ");			// if carry, mantissa=800000
  4350 	asm("addcs r12, r12, #1 ");				// and increment exponent
  4351 	asm("cmpmi r12, #1 ");					// if mantissa normalised, check exponent>0
  4352 	asm("movmi r12, #1 ");					// if normalised and exponent=0, set exponent to 1
  4353 	asm("TReal64GetTReal32c: ");			// come here to truncate
  4354 	asm("and r0, r0, #0x80000000 ");		// leave only sign bit in r0
  4355 	asm("orr r0, r0, r12, lsl #23 ");		// exponent into r0 bits 23-30
  4356 	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
  4357 	asm("orr r0, r0, r2, lsr #8 ");			// non-integer mantissa bits into r0 bits 0-22
  4358 	asm("cmp r12, #0xFF ");					// check for overflow
  4359 	asm("mvneq r12, #8 ");					// if overflow, return KErrOverflow
  4360 	asm("biceq pc, lr, #3 ");
  4361 	asm("bics r1, r0, #0x80000000 ");		// check for underflow
  4362 	asm("mvneq r12, #9 ");					// if underflow return KErrUnderflow
  4363 	asm("movne r12, #0 ");					// else return KErrNone
  4364 	asm("bic pc, lr, #3 ");
  4365 	asm("TReal64GetTReal32a: ");			// come here if overflow, infinity or NaN
  4366 	asm("add r3, r12, #1 ");
  4367 	asm("cmp r3, #0x480 ");					// check for infinity or NaN
  4368 	asm("movne r1, #0 ");					// if not, set mantissa to 0 for infinity result
  4369 	asm("movne r0, r0, lsr #20 ");
  4370 	asm("movne r0, r0, lsl #20 ");
  4371 	asm("mov r1, r1, lsr #29 ");			// assemble 23 bit mantissa in r1
  4372 	asm("orr r1, r1, r0, lsl #3 ");
  4373 	asm("bic r1, r1, #0xFF000000 ");
  4374 	asm("and r0, r0, #0x80000000 ");		// leave only sign in r0
  4375 	asm("orr r0, r0, #0x7F000000 ");		// r0 bits 23-30 = FF = exponent
  4376 	asm("orr r0, r0, #0x00800000 ");
  4377 	asm("orr r0, r0, r1 ");					// r0 bits 0-22 = result mantissa
  4378 	asm("movs r12, r0, lsl #9 ");			// check if result is infinity or NaN
  4379 	asm("mvneq r12, #8 ");					// if infinity return KErrOverflow
  4380 	asm("mvnne r12, #5 ");					// else return KErrArgument
  4381 	asm("bic pc, lr, #3 ");
  4382     }
  4383 }	// end of extern "C" declaration
  4384 #endif
  4385 #endif
  4386