kernel/eka/euser/epoc/arm/uc_realx.cia
changeset 0 a41df078684a
child 165 0d8cadb1e860
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\euser\epoc\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