kernel/eka/euser/epoc/arm/uc_realx.cia
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// e32\euser\epoc\arm\uc_realx.cia
// 
//

#include <e32cia.h>
#include <u32std.h>
#include <e32math.h>
#ifdef __USE_VFP_MATH
#include <arm_vfp.h>
#endif

#if defined(__USE_VFP_MATH) && !defined(__CPU_HAS_VFP)
#error	__USE_VFP_MATH was defined but not __CPU_HAS_VFP - impossible combination, check variant.mmh 
#endif	

#ifndef __EABI_CTORS__
__NAKED__ EXPORT_C TRealX::TRealX()
/**
Constructs a default extended precision object.

This sets the value to zero.
*/
	{
	asm("mov r1, #0 ");
	asm("str r1, [r0] ");
	asm("str r1, [r0, #4] ");
	asm("str r1, [r0, #8] ");
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TRealX::TRealX(TUint /*anExp*/, TUint /*aMantHi*/, TUint /*aMantLo*/)
/**
Constructs an extended precision object from an explicit exponent and
a 64 bit mantissa.

@param anExp   The exponent 
@param aMantHi The high order 32 bits of the 64 bit mantissa 
@param aMantLo The low order 32 bits of the 64 bit mantissa 
*/
	{
	asm("str r1, [r0, #8] ");
	asm("str r2, [r0, #4] ");
	asm("str r3, [r0, #0] ");
	__JUMP(,lr);
	}
#endif





__NAKED__ EXPORT_C TInt TRealX::Set(TInt /*anInt*/)
/**
Gives this extended precision object a new value taken
from a signed integer.

@param anInt The signed integer value.

@return KErrNone, always.
*/
	{
	asm("stmfd sp!, {lr} ");
	asm("mov r2, r1 ");
	asm("bl ConvertIntToTRealX ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("mov r0, #0 ");				// return KErrNone
	__POPRET("");
	}




#ifndef __EABI_CTORS__
__NAKED__ EXPORT_C TRealX::TRealX(TInt /*anInt*/)
/**
Constructs an extended precision object from a signed integer value.

@param anInt The signed integer value.
*/
	{
	// fall through
	}
#endif




__NAKED__ EXPORT_C TRealX& TRealX::operator=(TInt /*anInt*/)
/**
Assigns the specified signed integer value to this extended precision object.

@param anInt The signed integer value.

@return A reference to this extended precision object.
*/
	{
	asm("stmfd sp!, {lr} ");
	asm("mov r2, r1 ");
	asm("bl ConvertIntToTRealX ");
	asm("stmia r0, {r1,r2,r3} ");
	__POPRET("");

	asm("ConvertIntToTRealX: ");
	asm("cmp r2, #0 ");
	asm("movpl r3, #0 ");				// if int>0, r3=0
	asm("beq ConvertIntToTRealX0 ");	// if int=0, return 0
	asm("movmi r3, #1 ");				// if int<0, r3=1
	asm("rsbmi r2, r2, #0 ");			// if int -ve, negate it
	asm("orr r3, r3, #0x001E0000 ");
	asm("orr r3, r3, #0x80000000 ");	// r3=exponent 801E + sign bit
#ifdef __CPU_ARM_HAS_CLZ
	CLZ(12,2);
	asm("mov r2, r2, lsl r12 ");
	asm("sub r3, r3, r12, lsl #16 ");
#else
	asm("cmp r2, #0x10000 ");			// normalise mantissa, decrementing exponent as needed
	asm("movcc r2, r2, lsl #16 ");
	asm("subcc r3, r3, #0x100000 ");
	asm("cmp r2, #0x1000000 ");
	asm("movcc r2, r2, lsl #8 ");
	asm("subcc r3, r3, #0x080000 ");
	asm("cmp r2, #0x10000000 ");
	asm("movcc r2, r2, lsl #4 ");
	asm("subcc r3, r3, #0x040000 ");
	asm("cmp r2, #0x40000000 ");
	asm("movcc r2, r2, lsl #2 ");
	asm("subcc r3, r3, #0x020000 ");
	asm("cmp r2, #0x80000000 ");
	asm("movcc r2, r2, lsl #1 ");
	asm("subcc r3, r3, #0x010000 ");
#endif
	asm("ConvertIntToTRealX0: ");
	asm("mov r1, #0 ");					// low order word of mantissa = 0
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TInt TRealX::Set(const TInt64& /*anInt*/)
/**
Gives this extended precision object a new value taken from
a 64 bit integer.

@param anInt The 64 bit integer value.

@return KErrNone, always.
*/
	{
	asm("stmfd sp!, {lr} ");
	asm("ldmia r1, {r1,r2} ");
	asm("bl ConvertInt64ToTRealX ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("mov r0, #0 ");					// return KErrNone
	__POPRET("");
	}




#ifndef __EABI_CTORS__
__NAKED__ EXPORT_C TRealX::TRealX(const TInt64& /*anInt*/)
/**
Constructs an extended precision object from a 64 bit integer.

@param anInt A reference to a 64 bit integer. 
*/
	{
	// fall through
	}
#endif




__NAKED__ EXPORT_C TRealX& TRealX::operator=(const TInt64& /*anInt*/)
/**
Assigns the specified 64 bit integer value to this extended precision object.

@param anInt A reference to a 64 bit integer. 

@return A reference to this extended precision object.
*/
	{
	asm("stmfd sp!, {lr} ");
	asm("ldmia r1, {r1,r2} ");
	asm("bl ConvertInt64ToTRealX ");
	asm("stmia r0, {r1,r2,r3} ");
	__POPRET("");

	asm("ConvertInt64ToTRealX: ");
	asm("movs r3, r2, lsr #31 ");		// sign bit into r3 bit 0
	asm("beq ConvertInt64ToTRealX1 ");	// skip if plus
	asm("rsbs r1, r1, #0 ");			// take absolute value
	asm("rsc r2, r2, #0 ");
	asm("ConvertInt64ToTRealX1: ");
	asm("cmp r2, #0 ");					// does it fit into 32 bits?
	asm("moveq r2, r1 ");				// if it does, do 32 bit conversion
	asm("beq ConvertUintToTRealX1 ");
#ifdef __CPU_ARM_HAS_CLZ
	CLZ(12,2);
	asm("mov r2, r2, lsl r12 ");
	asm("rsb r12, r12, #32 ");
	asm("orr r2, r2, r1, lsr r12 ");
	asm("rsb r12, r12, #32 ");
#else
	asm("mov r12, #32 ");				// 32-number of left-shifts needed to normalise
	asm("cmp r2, #0x10000 ");			// calculate number required
	asm("movcc r2, r2, lsl #16 ");
	asm("subcc r12, r12, #16 ");
	asm("cmp r2, #0x1000000 ");
	asm("movcc r2, r2, lsl #8 ");
	asm("subcc r12, r12, #8 ");
	asm("cmp r2, #0x10000000 ");
	asm("movcc r2, r2, lsl #4 ");
	asm("subcc r12, r12, #4 ");
	asm("cmp r2, #0x40000000 ");
	asm("movcc r2, r2, lsl #2 ");
	asm("subcc r12, r12, #2 ");
	asm("cmp r2, #0x80000000 ");
	asm("movcc r2, r2, lsl #1 ");
	asm("subcc r12, r12, #1 ");			// r2 is now normalised
	asm("orr r2, r2, r1, lsr r12 ");	// shift r1 left into r2
	asm("rsb r12, r12, #32 ");
#endif
	asm("mov r1, r1, lsl r12 ");
	asm("add r3, r3, #0x80000000 ");	// exponent = 803E-r12
	asm("add r3, r3, #0x003E0000 ");
	asm("sub r3, r3, r12, lsl #16 ");
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TInt TRealX::Set(TUint /*anInt*/)
/**
Gives this extended precision object a new value taken from
an unsigned integer.

@param The unsigned integer value.

@return KErrNone, always.
*/
	{
	asm("stmfd sp!, {lr} ");
	asm("mov r2, r1 ");
	asm("bl ConvertUintToTRealX ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("mov r0, #0 ");				// return KErrNone
	__POPRET("");
	}




#ifndef __EABI_CTORS__
__NAKED__ EXPORT_C TRealX::TRealX(TUint /*anInt*/)
/**
Constructs an extended precision object from an unsigned integer value.

@param anInt The unsigned integer value.
*/
	{
	// fall through
	}
#endif




__NAKED__ EXPORT_C TRealX& TRealX::operator=(TUint /*anInt*/)
/**
Assigns the specified unsigned integer value to this extended precision object.

@param anInt The unsigned integer value.

@return A reference to this extended precision object.
*/
	{
	asm("stmfd sp!, {lr} ");
	asm("mov r2, r1 ");
	asm("bl ConvertUintToTRealX ");
	asm("stmia r0, {r1,r2,r3} ");
	__POPRET("");

	asm("ConvertUintToTRealX: ");
	asm("mov r3, #0 ");
	asm("ConvertUintToTRealX1: ");
	asm("cmp r2, #0 ");					// check for zero
	asm("beq ConvertUintToTRealX0 ");
	asm("orr r3, r3, #0x001E0000 ");
	asm("orr r3, r3, #0x80000000 ");	// r3=exponent 801E
#ifdef __CPU_ARM_HAS_CLZ
	CLZ(12,2);
	asm("mov r2, r2, lsl r12 ");
	asm("sub r3, r3, r12, lsl #16 ");
#else
	asm("cmp r2, #0x10000 ");			// normalise mantissa, decrementing exponent as needed
	asm("movcc r2, r2, lsl #16 ");
	asm("subcc r3, r3, #0x100000 ");
	asm("cmp r2, #0x1000000 ");
	asm("movcc r2, r2, lsl #8 ");
	asm("subcc r3, r3, #0x080000 ");
	asm("cmp r2, #0x10000000 ");
	asm("movcc r2, r2, lsl #4 ");
	asm("subcc r3, r3, #0x040000 ");
	asm("cmp r2, #0x40000000 ");
	asm("movcc r2, r2, lsl #2 ");
	asm("subcc r3, r3, #0x020000 ");
	asm("cmp r2, #0x80000000 ");
	asm("movcc r2, r2, lsl #1 ");
	asm("subcc r3, r3, #0x010000 ");
#endif
	asm("ConvertUintToTRealX0: ");
	asm("mov r1, #0 ");					// low order word of mantissa = 0
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C void TRealX::SetZero(TBool /*aNegative*/)
/**
Sets the value of this extended precision object to zero.

@param aNegative ETrue, the value is a negative zero;
                 EFalse, the value is a positive zero, this is the default.
*/
	{
	asm("mov r3, #0 ");
	asm("cmp r1, #0 ");
	asm("movne r3, #1 ");
	asm("mov r2, #0 ");
	asm("mov r1, #0 ");
	asm("stmia r0, {r1,r2,r3} ");
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C void TRealX::SetNaN()
/**
Sets the value of this extended precision object to 'not a number'.
*/
	{
	asm("ldr r3, [pc, #__RealIndefiniteExponent-.-8] ");
	asm("mov r2, #0xC0000000 ");
	asm("mov r1, #0 ");
	asm("stmia r0, {r1,r2,r3} ");
	__JUMP(,lr);
	asm("__RealIndefiniteExponent: ");
	asm(".word 0xFFFF0001 ");
	}





__NAKED__ EXPORT_C void TRealX::SetInfinite(TBool /*aNegative*/)
/**
Sets the value of this extended precision object to infinity.

@param aNegative ETrue, the value is a negative zero;
                 EFalse, the value is a positive zero.
*/
	{
	asm("ldr r3, [pc, #__InfiniteExponent-.-8] ");
	asm("cmp r1, #0 ");
	asm("orrne r3, r3, #1 ");
	asm("mov r2, #0x80000000 ");
	asm("mov r1, #0 ");
	asm("stmia r0, {r1,r2,r3} ");
	__JUMP(,lr);
	asm("__InfiniteExponent: ");
	asm(".word 0xFFFF0000 ");
	}




__NAKED__ EXPORT_C TBool TRealX::IsZero() const
/**
Determines whether the extended precision value is zero.

@return True, if the extended precision value is zero, false, otherwise.
*/
	{
	asm("ldr r1, [r0, #8] ");	// get exponent word
	asm("mov r0, #0 ");			// default return value is 0
	asm("cmp r1, #0x10000 ");	// is exponent=0 ?
	asm("movcc r0, #1 ");		// if so return 1
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TBool TRealX::IsNaN() const
/**
Determines whether the extended precision value is 'not a number'.

@return True, if the extended precision value is 'not a number',
        false, otherwise.
*/
	{
	asm("ldmia r0, {r1,r2,r3} ");
	asm("mov r0, #0 ");					// default return value is 0
	asm("cmn r3, #0x10000 ");			// check for exponent 65535
	asm("bcc 1f ");						// branch if not
	asm("cmp r2, #0x80000000 ");		// check if infinity
	asm("cmpeq r1, #0 ");
	asm("movne r0, #1 ");				// if not, return 1
	asm("1: ");
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TBool TRealX::IsInfinite() const
/**
Determines whether the extended precision value has a finite value.

@return True, if the extended precision value is finite,
        false, if the value is 'not a number' or is infinite,
*/
	{
	asm("ldmia r0, {r1,r2,r3} ");
	asm("mov r0, #0 ");						// default return value is 0
	asm("cmn r3, #0x10000 ");				// check for exponent 65535
	asm("bcc 1f ");							// branch if not
	asm("cmp r2, #0x80000000 ");			// check if infinity
	asm("cmpeq r1, #0 ");
	asm("moveq r0, #1 ");					// if it is, return 1
	asm("1: ");
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TBool TRealX::IsFinite() const
/**
Determines whether the extended precision value has a finite value.

@return True, if the extended precision value is finite,
        false, if the value is 'not a number' or is infinite,
*/
	{
	asm("ldr r1, [r0, #8] ");	// get exponent word
	asm("mov r0, #0 ");			// default return value is 0
	asm("cmn r1, #0x10000 ");	// is exponent=65535 (infinity or NaN) ?
	asm("movcc r0, #1 ");		// if not return 1
	__JUMP(,lr);
	}




#ifndef __EABI_CTORS__
__NAKED__ EXPORT_C TRealX::TRealX(TReal32 /*aReal*/) __SOFTFP
/**
Constructs an extended precision object from
a single precision floating point number.

@param aReal The single precision floating point value.
*/
	{
	// fall through
	}
#endif




__NAKED__ EXPORT_C TRealX& TRealX::operator=(TReal32 /*aReal*/) __SOFTFP
/**
Assigns the specified single precision floating point number to
this extended precision object.

@param aReal The single precision floating point value.

@return A reference to this extended precision object.
*/
	{
	asm("stmfd sp!, {lr} ");
	asm("bl ConvertTReal32ToTRealX ");
	asm("stmia r0, {r1,r2,r3} ");
	__POPRET("");
	}




__NAKED__ EXPORT_C TInt TRealX::Set(TReal32 /*aReal*/) __SOFTFP
/**
Gives this extended precision object a new value taken from
a single precision floating point number.

@param aReal The single precision floating point value. 

@return KErrNone, if a valid number;
        KErrOverflow, if the number is infinite;
        KErrArgument, if not a number.
*/
	{
	// aReal is in r1 on entry
	// sign in bit 31, exponent in 30-23, mantissa (non-integer bits) in 22-0
	asm("stmfd sp!, {lr} ");
	asm("bl ConvertTReal32ToTRealX ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("cmn r3, #0x10000 ");			// check for infinity or NaN
	asm("movcc r0, #0 ");				// if neither, return KErrNone
	asm("bcc trealx_set_treal32_0 ");
	asm("cmp r2, #0x80000000 ");		// check for infinity
	asm("mvneq r0, #8 ");				// if so, return KErrOverflow
	asm("mvnne r0, #5 ");				// else return KErrArgument
	asm("trealx_set_treal32_0: ");
	__POPRET("");

	// Convert 32-bit real in r1 to TRealX in r1,r2,r3
	// r0 unmodified, r1,r2,r3,r12 modified
	asm("ConvertTReal32ToTRealX: ");
	asm("mov r3, r1, lsr #7 ");			// r3 bits 16-31 = TReal32 exponent
	asm("ands r3, r3, #0x00FF0000 ");
	asm("mov r2, r1, lsl #8 ");			// r2 = TReal32 mantissa << 8, bit 31 not yet in
	asm("orrne r2, r2, #0x80000000 ");	// if not zero/denormal, put in implied integer bit
	asm("orr r3, r3, r1, lsr #31 ");	// r3 bit 0 = sign bit
	asm("mov r1, #0 ");					// low word of mantissa = 0
	asm("beq ConvertTReal32ToTRealX0 ");	// branch if zero/denormal
	asm("cmp r3, #0x00FF0000 ");		// check for infinity or NaN
	asm("orrcs r3, r3, #0xFF000000 ");	// if infinity or NaN, exponent = FFFF
	asm("addcc r3, r3, #0x7F000000 ");	// else exponent = TReal32 exponent + 7F80
	asm("addcc r3, r3, #0x00800000 ");
	__JUMP(,lr);
	asm("ConvertTReal32ToTRealX0: ");	// come here if zero or denormal
	asm("adds r2, r2, r2 ");			// shift mantissa left one more and check if zero
	__JUMP(eq,lr);
	asm("add r3, r3, #0x7F000000 ");	// else exponent = 7F80 (highest denormal exponent)
	asm("add r3, r3, #0x00800000 ");
#ifdef __CPU_ARM_HAS_CLZ
	CLZ(12,2);
	asm("mov r2, r2, lsl r12 ");
	asm("sub r3, r3, r12, lsl #16 ");
#else
	asm("cmp r2, #0x10000 ");			// normalise mantissa, decrementing exponent as needed
	asm("movcc r2, r2, lsl #16 ");
	asm("subcc r3, r3, #0x100000 ");
	asm("cmp r2, #0x1000000 ");
	asm("movcc r2, r2, lsl #8 ");
	asm("subcc r3, r3, #0x080000 ");
	asm("cmp r2, #0x10000000 ");
	asm("movcc r2, r2, lsl #4 ");
	asm("subcc r3, r3, #0x040000 ");
	asm("cmp r2, #0x40000000 ");
	asm("movcc r2, r2, lsl #2 ");
	asm("subcc r3, r3, #0x020000 ");
	asm("cmp r2, #0x80000000 ");
	asm("movcc r2, r2, lsl #1 ");
	asm("subcc r3, r3, #0x010000 ");
#endif
	__JUMP(,lr);
	}




#ifndef __EABI_CTORS__
__NAKED__ EXPORT_C TRealX::TRealX(TReal64 /*aReal*/) __SOFTFP
/**
Constructs an extended precision object from
a double precision floating point number.

@param aReal The double precision floating point value.
*/
	{
	// fall through
	}
#endif




__NAKED__ EXPORT_C TRealX& TRealX::operator=(TReal64 /*aReal*/) __SOFTFP
/**
Assigns the specified double precision floating point number to
this extended precision object.

@param aReal The double precision floating point value.

@return A reference to this extended precision object.
*/
	{
	asm("stmfd sp!, {lr} ");
	asm("bl ConvertTReal64ToTRealX ");
	asm("stmia r0, {r1,r2,r3} ");
	__POPRET("");
	}




__NAKED__ EXPORT_C TInt TRealX::Set(TReal64 /*aReal*/) __SOFTFP
/**
Gives this extended precision object a new value taken from
a double precision floating point number.

@param aReal The double precision floating point value. 

@return KErrNone, if a valid number;
        KErrOverflow, if the number is infinite;
        KErrArgument, if not a number.
*/
	{
	// aReal is in r1,r2 on entry
	// sign in bit 31 of r1, exponent in 30-20 of r1
	// mantissa (non-integer bits) in 19-0 of r1 (high) and r2 (low)
	asm("stmfd sp!, {lr} ");
	asm("bl ConvertTReal64ToTRealX ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("cmn r3, #0x10000 ");			// check for infinity or NaN
	asm("movcc r0, #0 ");				// if neither, return KErrNone
	asm("bcc trealx_set_treal64_0 ");
	asm("cmp r2, #0x80000000 ");		// check for infinity
	asm("cmpeq r1, #0 ");
	asm("mvneq r0, #8 ");				// if so, return KErrOverflow
	asm("mvnne r0, #5 ");				// else return KErrArgument
	asm("trealx_set_treal64_0: ");
	__POPRET("");

	// convert TReal64 in r1,r2 in GCC and r2 and r3 in RVCT
	// if __DOUBLE_WORDS_SWAPPED__ r1=sign,exp,high mant, r2=low mant
	// else r1 unused , r2=low mant, r3=sign,exp,high mant (as a result of EABI alignment reqs)
	// into TRealX in r1,r2,r3 (r2,r1=mant high,low r3=exp,flag,sign)
	// r0 unmodified, r1,r2,r3,r12 modified
	asm("ConvertTReal64ToTRealX: ");
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("mov r12, r2 ");				// ls word of mantissa into r12
#else
	asm("mov r12, r2 ");				// ls word of mantissa into r12
	asm("mov r1, r3 ");
#endif
	asm("mov r3, r1, lsr #20 ");		// sign and exp into bottom 12 bits of r3
	asm("mov r2, r1, lsl #11 ");		// left justify mantissa in r2,r1
	asm("mov r3, r3, lsl #16 ");		// and into bits 16-27
	asm("bics r3, r3, #0x08000000 ");	// remove sign, leaving exponent in bits 16-26
	asm("orr r2, r2, r12, lsr #21 ");
	asm("orrne r2, r2, #0x80000000 ");	// if not zero/denormal, put in implied integer bit
	asm("orr r3, r3, r1, lsr #31 ");	// sign bit into bit 0 of r3
	asm("mov r1, r12, lsl #11 ");
	asm("beq ConvertTReal64ToTRealX0 ");	// branch if zero or denormal
	asm("mov r12, r3, lsl #5 ");		// exponent into bits 21-31 of r12
	asm("cmn r12, #0x00200000 ");		// check if exponent=7FF (infinity or NaN)
	asm("addcs r3, r3, #0xF8000000 ");	// if so, result exponent=FFFF
	asm("addcc r3, r3, #0x7C000000 ");	// else result exponent = TReal64 exponent + 7C00
	__JUMP(,lr);
	asm("ConvertTReal64ToTRealX0: ");	// come here if zero or denormal
	asm("adds r1, r1, r1 ");			// shift mantissa left one more bit
	asm("adcs r2, r2, r2 ");
	asm("cmpeq r1, #0 ");				// and test for zero
	__JUMP(eq,lr);
	asm("add r3, r3, #0x7C000000 ");	// else exponent=7C00 (highest denormal exponent)
	asm("cmp r2, #0 ");					// normalise - first check if r2=0
	asm("moveq r2, r1 ");				// if so, shift up by 32
	asm("moveq r1, #0 ");
	asm("subeq r3, r3, #0x200000 ");	// and subtract 32 from exponent
#ifdef __CPU_ARM_HAS_CLZ
	CLZ(12,2);
	asm("mov r2, r2, lsl r12 ");
	asm("rsb r12, r12, #32 ");
	asm("orr r2, r2, r1, lsr r12 ");
	asm("rsb r12, r12, #32 ");
#else
	asm("mov r12, #32 ");				// 32-number of left-shifts needed to normalise
	asm("cmp r2, #0x10000 ");			// calculate number required
	asm("movcc r2, r2, lsl #16 ");
	asm("subcc r12, r12, #16 ");
	asm("cmp r2, #0x1000000 ");
	asm("movcc r2, r2, lsl #8 ");
	asm("subcc r12, r12, #8 ");
	asm("cmp r2, #0x10000000 ");
	asm("movcc r2, r2, lsl #4 ");
	asm("subcc r12, r12, #4 ");
	asm("cmp r2, #0x40000000 ");
	asm("movcc r2, r2, lsl #2 ");
	asm("subcc r12, r12, #2 ");
	asm("cmp r2, #0x80000000 ");
	asm("movcc r2, r2, lsl #1 ");
	asm("subcc r12, r12, #1 ");			// r2 is now normalised
	asm("orr r2, r2, r1, lsr r12 ");	// shift r1 left into r2
	asm("rsb r12, r12, #32 ");
#endif
	asm("mov r1, r1, lsl r12 ");
	asm("sub r3, r3, r12, lsl #16 ");	// exponent -= number of left shifts
	__JUMP(,lr);
	}





__NAKED__ EXPORT_C TRealX::operator TInt() const
/**
Gets the extended precision value as a signed integer value.

The operator returns:

1. zero , if the extended precision value is not a number

2. 0x7FFFFFFF, if the value is positive and too big to fit into a TInt.

3. 0x80000000, if the value is negative and too big to fit into a TInt.
*/
	{
	asm("ldmia r0, {r1,r2,r3} ");		// get value into r1,r2,r3

	asm("ConvertTRealXToInt: ");
	asm("mov r12, #0x8000 ");			// r12=0x801E
	asm("orr r12, r12, #0x001E ");
	asm("subs r12, r12, r3, lsr #16 ");	// r12=801E-exponent
	asm("bls ConvertTRealXToInt1 ");	// branch if exponent>=801E
	asm("cmp r12, #31 ");				// test if exponent<7FFF
	asm("movhi r0, #0 ");				// if so, underflow result to zero
	__JUMP(hi,lr);
	asm("mov r0, r2, lsr r12 ");		// shift mantissa right to form integer
	asm("tst r3, #1 ");					// check sign bit
	asm("rsbne r0, r0, #0 ");			// if negative, r0=-r0
	__JUMP(,lr);
	asm("ConvertTRealXToInt1: ");
	asm("cmn r3, #0x10000 ");			// check for infinity or NaN
	asm("bcc ConvertTRealXToInt2 ");	// branch if neither
	asm("cmp r2, #0x80000000 ");		// check for infinity
	asm("cmpeq r1, #0 ");
	asm("movne r0, #0 ");				// if NaN, return 0
	__JUMP(ne,lr);
	asm("ConvertTRealXToInt2: ");
	asm("mov r0, #0x80000000 ");		// return 0x80000000 if -ve overflow, 0x7FFFFFFF if +ve
	asm("movs r3, r3, lsr #1 ");
	asm("sbc r0, r0, #0 ");
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TRealX::operator TUint() const
/**
Returns the extended precision value as an unsigned signed integer value.

The operator returns:

1. zero, if the extended precision value is not a number

2. 0xFFFFFFFF, if the value is positive and too big to fit into a TUint.

3. zero, if the value is negative and too big to fit into a TUint.
*/
	{
	asm("ldmia r0, {r1,r2,r3} ");		// get value into r1,r2,r3

	asm("ConvertTRealXToUint: ");
	asm("mov r12, #0x8000 ");			// r12=0x801E
	asm("orr r12, r12, #0x001E ");
	asm("subs r12, r12, r3, lsr #16 ");	// r12=801E-exponent
	asm("bcc ConvertTRealXToUint1 ");	// branch if exponent>801E
	asm("cmp r12, #31 ");				// test if exponent<7FFF
	asm("movhi r0, #0 ");				// if so, underflow result to zero
	__JUMP(hi,lr);
	asm("tst r3, #1 ");					// check sign bit
	asm("moveq r0, r2, lsr r12 ");		// if +ve, shift mantissa right to form integer
	asm("movne r0, #0 ");				// if negative, r0=0
	__JUMP(,lr);
	asm("ConvertTRealXToUint1: ");
	asm("mov r0, #0 ");					// r0=0 initially
	asm("cmn r3, #0x10000 ");			// check for infinity or NaN
	asm("bcc ConvertTRealXToUint2 ");	// branch if neither
	asm("cmp r2, #0x80000000 ");		// check for infinity
	asm("cmpeq r1, #0 ");
	__JUMP(ne,lr);
	asm("ConvertTRealXToUint2: ");
	asm("movs r3, r3, lsr #1 ");		// sign bit into carry
	asm("sbc r0, r0, #0 ");				// r0=0 if -ve, 0xFFFFFFFF if +ve
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TRealX::operator TInt64() const
/**
Returns the extended precision value as a 64 bit integer value.

The operator returns:

1. zero, if the extended precision value is not a number

2. 0x7FFFFFFF FFFFFFFF, if the value is positive and too big to fit
   into a TInt64

3. 0x80000000 00000000, if the value is negative and too big to fit
   into a TInt.
*/
	{
	// r0 = this, result in r1:r0
	asm("ldmia r0, {r0,r1,r2} ");		// get value into r0,r1,r2
	asm("ConvertTRealXToInt64: ");
	asm("mov r3, #0x8000 ");			// r3=0x803E
	asm("orr r3, r3, #0x003E ");
	asm("subs r3, r3, r2, lsr #16 ");	// r3=803E-exponent
	asm("bls ConvertTRealXToInt64a ");	// branch if exponent>=803E
	asm("cmp r3, #63 ");				// test if exponent<7FFF
	asm("movhi r1, #0 ");				// if so, underflow result to zero
	asm("movhi r0, #0 ");
	__JUMP(hi,lr);
	asm("cmp r3, #32 ");				// >=32 shifts required?
	asm("subcs r3, r3, #32 ");			// if so, r3-=32
	asm("movcs r0, r1, lsr r3 ");		// r1:r0 >>= (r3+32)
	asm("movcs r1, #0 ");
	asm("movcc r0, r0, lsr r3 ");		// else r1:r0>>=r3
	asm("rsbcc r3, r3, #32 ");
	asm("orrcc r0, r0, r1, lsl r3 ");
	asm("rsbcc r3, r3, #32 ");
	asm("movcc r1, r1, lsr r3 ");		// r1:r0 = absolute integer
	asm("tst r2, #1 ");					// check sign bit
	__JUMP(eq,lr);
	asm("rsbs r0, r0, #0 ");			// else negate answer
	asm("rsc r1, r1, #0 ");
	__JUMP(,lr);
	asm("ConvertTRealXToInt64a: ");
	asm("cmn r2, #0x10000 ");			// check for infinity or NaN
	asm("bcc ConvertTRealXToInt64b ");	// branch if neither
	asm("cmp r1, #0x80000000 ");		// check for infinity
	asm("cmpeq r0, #0 ");
	asm("movne r1, #0 ");				// if NaN, return 0
	asm("movne r0, #0 ");
	__JUMP(ne,lr);
	asm("ConvertTRealXToInt64b: ");
	asm("mov r1, #0x80000000 ");		// return KMaxTInt64/KMinTInt64 depending on sign
	asm("mov r0, #0 ");
	asm("movs r2, r2, lsr #1 ");
	asm("sbcs r0, r0, #0 ");
	asm("sbc r1, r1, #0 ");
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TRealX::operator TReal32() const __SOFTFP
/**
Returns the extended precision value as
a single precision floating point value.
*/
	{
	asm("ldmia r0, {r1,r2,r3} ");			// r1,r2,r3=input value

	// Convert TRealX in r1,r2,r3 to TReal32 in r0
	asm("ConvertTRealXToTReal32: ");
	asm("mov r12, #0x8000 ");
	asm("orr r12, r12, #0x007F ");			// r12=0x807F
	asm("cmp r3, r12, lsl #16 ");			// check if exponent>=807F
	asm("bcs ConvertTRealXToTReal32a ");	// branch if it is
	asm("sub r12, r12, #0x00FF ");			// r12=0x7F80
	asm("rsbs r12, r12, r3, lsr #16 ");		// r12=exp in - 7F80 = result exponent if in range
	asm("bgt ConvertTRealXToTReal32b ");	// branch if normalised result
	asm("cmn r12, #23 ");					// check for total underflow or zero
	asm("movlt r0, r3, lsl #31 ");			// in this case, return zero with appropriate sign
	__JUMP(lt,lr);
	asm("add r12, r12, #31 ");				// r12=32-mantissa shift required = 32-(1-r12)
	asm("movs r0, r1, lsl r12 ");			// r0=lost bits when r2:r1 is shifted
	asm("bicne r3, r3, #0x300 ");			// if these are not zero, set rounded down flag
	asm("orrne r3, r3, #0x100 ");
	asm("rsb r0, r12, #32 ");
	asm("mov r1, r1, lsr r0 ");
	asm("orr r1, r1, r2, lsl r12 ");
	asm("mov r2, r2, lsr r0 ");				// r2 top 24 bits now give unrounded result mantissa
	asm("mov r12, #0 ");					// result exponent will be zero
	asm("ConvertTRealXToTReal32b: ");
	asm("movs r0, r2, lsl #24 ");			// top 8 truncated bits into top byte of r0
	asm("bpl ConvertTRealXToTReal32c ");	// if top bit clear, truncate
	asm("cmp r0, #0x80000000 ");
	asm("cmpeq r1, #0 ");					// compare rounding bits to 1000...
	asm("bhi ConvertTRealXToTReal32d ");	// if >, round up
	asm("movs r0, r3, lsl #23 ");			// round up flag into C, round down flag into N
	asm("bcs ConvertTRealXToTReal32c ");	// if rounded up, truncate
	asm("bmi ConvertTRealXToTReal32d ");	// if rounded down, round up
	asm("tst r2, #0x100 ");					// else round to even - test LSB of result mantissa
	asm("beq ConvertTRealXToTReal32c ");	// if zero, truncate, else round up
	asm("ConvertTRealXToTReal32d: ");		// come here to round up
	asm("adds r2, r2, #0x100 ");			// increment the mantissa
	asm("movcs r2, #0x80000000 ");			// if carry, mantissa=800000
	asm("addcs r12, r12, #1 ");				// and increment exponent
	asm("cmpmi r12, #1 ");					// if mantissa normalised, check exponent>0
	asm("movmi r12, #1 ");					// if normalised and exponent=0, set exponent to 1
	asm("ConvertTRealXToTReal32c: ");		// come here to truncate
	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
	asm("orr r0, r0, r12, lsl #23 ");		// exponent into r0 bits 23-30
	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
	asm("orr r0, r0, r2, lsr #8 ");			// non-integer mantissa bits into r0 bits 0-22
	__JUMP(,lr);
	asm("ConvertTRealXToTReal32a: ");		// come here if overflow, infinity or NaN
	asm("cmn r3, #0x10000 ");				// check for infinity or NaN
	asm("movcc r2, #0 ");					// if not, set mantissa to 0 for infinity result
	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
	asm("orr r0, r0, #0x7F000000 ");		// r0 bits 23-30 = FF = exponent
	asm("orr r0, r0, #0x00800000 ");
	asm("orr r0, r0, r2, lsr #8 ");			// r0 bits 0-22 = result mantissa
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TRealX::operator TReal64() const __SOFTFP
/**
Returns the extended precision value as
a double precision floating point value.
*/
	{
	asm("ldmia r0, {r1,r2,r3} ");			// r1,r2,r3=input value

	// Convert TRealX in r1,r2,r3 to TReal64 in r0,r1
	// if __DOUBLE_WORDS_SWAPPED__ r0=sign,exp,high mant, r1=low mant
	// else r0, r1 reversed
	asm("ConvertTRealXToTReal64: ");
	asm("mov r12, #0x8300 ");
	asm("orr r12, r12, #0x00FF ");			// r12=0x83FF
	asm("cmp r3, r12, lsl #16 ");			// check if exponent>=83FF
	asm("bcs ConvertTRealXToTReal64a ");	// branch if it is
	asm("mov r12, #0x7C00 ");
	asm("rsbs r12, r12, r3, lsr #16 ");		// r12=exp in - 7C00 = result exponent if in range
	asm("bgt ConvertTRealXToTReal64b ");	// branch if normalised result
	asm("cmn r12, #52 ");					// check for total underflow or zero
	asm("movlt r0, r3, lsl #31 ");			// in this case, return zero with appropriate sign
	asm("movlt r1, #0 ");
	asm("blt ConvertTRealXToTReal64_end ");

	asm("adds r12, r12, #31 ");				// check if >=32 shifts needed, r12=32-shift count
	asm("ble ConvertTRealXToTReal64e ");	// branch if >=32 shifts needed
	asm("movs r0, r1, lsl r12 ");			// r0=lost bits when r2:r1 is shifted
	asm("bicne r3, r3, #0x300 ");			// if these are not zero, set rounded down flag
	asm("orrne r3, r3, #0x100 ");
	asm("rsb r0, r12, #32 ");				// r0=shift count
	asm("mov r1, r1, lsr r0 ");
	asm("orr r1, r1, r2, lsl r12 ");
	asm("mov r2, r2, lsr r0 ");				// r2:r1 top 53 bits = unrounded result mantissa
	asm("b ConvertTRealXToTReal64f ");
	asm("ConvertTRealXToTReal64e: ");
	asm("add r12, r12, #32 ");				// r12=64-shift count
	asm("cmp r1, #0 ");						// r1 bits are all lost - test them
	asm("moveqs r0, r2, lsl r12 ");			// if zero, test lost bits from r2
	asm("bicne r3, r3, #0x300 ");			// if lost bits not all zero, set rounded down flag
	asm("orrne r3, r3, #0x100 ");
	asm("rsb r0, r12, #32 ");				// r0=shift count-32
	asm("mov r1, r2, lsr r0 ");				// shift r2:r1 right
	asm("mov r2, #0 ");
	asm("ConvertTRealXToTReal64f: ");
	asm("mov r12, #0 ");					// result exponent will be zero for denormals
	asm("ConvertTRealXToTReal64b: ");
	asm("movs r0, r1, lsl #21 ");			// 11 rounding bits to top of r0
	asm("bpl ConvertTRealXToTReal64c ");	// if top bit clear, truncate
	asm("cmp r0, #0x80000000 ");			// compare rounding bits to 10000000000
	asm("bhi ConvertTRealXToTReal64d ");	// if >, round up
	asm("movs r0, r3, lsl #23 ");			// round up flag into C, round down flag into N
	asm("bcs ConvertTRealXToTReal64c ");	// if rounded up, truncate
	asm("bmi ConvertTRealXToTReal64d ");	// if rounded down, round up
	asm("tst r1, #0x800 ");					// else round to even - test LSB of result mantissa
	asm("beq ConvertTRealXToTReal64c ");	// if zero, truncate, else round up
	asm("ConvertTRealXToTReal64d: ");		// come here to round up
	asm("adds r1, r1, #0x800 ");			// increment the mantissa
	asm("adcs r2, r2, #0 ");
	asm("movcs r2, #0x80000000 ");			// if carry, mantissa=10000...0
	asm("addcs r12, r12, #1 ");				// and increment exponent
	asm("cmpmi r12, #1 ");					// if mantissa normalised, check exponent>0
	asm("movmi r12, #1 ");					// if normalised and exponent=0, set exponent to 1
	asm("ConvertTRealXToTReal64c: ");		// come here to truncate
	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
	asm("orr r0, r0, r12, lsl #20 ");		// exponent into r0 bits 20-30
	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
	asm("orr r0, r0, r2, lsr #11 ");		// non-integer mantissa bits into r0 bits 0-19
	asm("mov r1, r1, lsr #11 ");			// and r1
	asm("orr r1, r1, r2, lsl #21 ");
	asm("b ConvertTRealXToTReal64_end ");

	asm("ConvertTRealXToTReal64a: ");		// come here if overflow, infinity or NaN
	asm("cmn r3, #0x10000 ");				// check for infinity or NaN
	asm("movcc r2, #0 ");					// if not, set mantissa to 0 for infinity result
	asm("movcc r1, #0 ");
	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
	asm("orr r0, r0, #0x7F000000 ");		// r0 bits 20-30 = 7FF = exponent
	asm("orr r0, r0, #0x00F00000 ");
	asm("orr r0, r0, r2, lsr #11 ");		// r0 bits 0-19 = result mantissa high bits
	asm("mov r1, r1, lsr #11 ");			// and r1=result mantissa low bits
	asm("orr r1, r1, r2, lsl #21 ");
	asm("ConvertTRealXToTReal64_end: ");
#ifndef __DOUBLE_WORDS_SWAPPED__
	asm("mov r2, r0 ");
	asm("mov r0, r1 ");
	asm("mov r1, r2 ");
#endif
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TInt TRealX::GetTReal(TReal32& /*aVal*/) const
/**
Extracts the extended precision value as
a single precision floating point value.

@param aVal A reference to a single precision object which contains
            the result of the operation.

@return KErrNone, if the operation is successful;
        KErrOverflow, if the operation results in overflow;
        KErrUnderflow, if the operation results in underflow.
*/
	{
	asm("stmfd sp!, {r4,lr} ");
	asm("mov r4, r1 ");
	asm("ldmia r0, {r1,r2,r3} ");			// r1,r2,r3=input value
	asm("bl TRealXGetTReal32 ");
	asm("str r0, [r4] ");					// store converted TReal32
	asm("mov r0, r12 ");					// return value into r0
	__POPRET("r4,");

	// Convert TRealX in r1,r2,r3 to TReal32 in r0
	// Return error code in r12
	// r0-r3, r12 modified
	asm("TRealXGetTReal32: ");
	asm("mov r12, #0x8000 ");
	asm("orr r12, r12, #0x007F ");			// r12=0x807F
	asm("cmp r3, r12, lsl #16 ");			// check if exponent>=807F
	asm("bcs TRealXGetTReal32a ");			// branch if it is
	asm("sub r12, r12, #0x00FF ");			// r12=0x7F80
	asm("rsbs r12, r12, r3, lsr #16 ");		// r12=exp in - 7F80 = result exponent if in range
	asm("bgt TRealXGetTReal32b ");			// branch if normalised result
	asm("cmn r12, #23 ");					// check for total underflow or zero
	asm("bge TRealXGetTReal32e ");			// skip if not
	asm("mov r0, r3, lsl #31 ");			// else return zero with appropriate sign
	asm("mov r1, #0 ");
	asm("cmp r3, #0x10000 ");				// check for zero
	asm("movcc r12, #0 ");					// if zero return KErrNone
	asm("mvncs r12, #9 ");					// else return KErrUnderflow
	__JUMP(,lr);
	asm("TRealXGetTReal32e: ");
	asm("add r12, r12, #31 ");				// r12=32-mantissa shift required = 32-(1-r12)
	asm("movs r0, r1, lsl r12 ");			// r0=lost bits when r2:r1 is shifted
	asm("bicne r3, r3, #0x300 ");			// if these are not zero, set rounded down flag
	asm("orrne r3, r3, #0x100 ");
	asm("rsb r0, r12, #32 ");
	asm("mov r1, r1, lsr r0 ");
	asm("orr r1, r1, r2, lsl r12 ");
	asm("mov r2, r2, lsr r0 ");				// r2 top 24 bits now give unrounded result mantissa
	asm("mov r12, #0 ");					// result exponent will be zero
	asm("TRealXGetTReal32b: ");
	asm("movs r0, r2, lsl #24 ");			// top 8 truncated bits into top byte of r0
	asm("bpl TRealXGetTReal32c ");			// if top bit clear, truncate
	asm("cmp r0, #0x80000000 ");
	asm("cmpeq r1, #0 ");					// compare rounding bits to 1000...
	asm("bhi TRealXGetTReal32d ");			// if >, round up
	asm("movs r0, r3, lsl #23 ");			// round up flag into C, round down flag into N
	asm("bcs TRealXGetTReal32c ");			// if rounded up, truncate
	asm("bmi TRealXGetTReal32d ");			// if rounded down, round up
	asm("tst r2, #0x100 ");					// else round to even - test LSB of result mantissa
	asm("beq TRealXGetTReal32c ");			// if zero, truncate, else round up
	asm("TRealXGetTReal32d: ");				// come here to round up
	asm("adds r2, r2, #0x100 ");			// increment the mantissa
	asm("movcs r2, #0x80000000 ");			// if carry, mantissa=800000
	asm("addcs r12, r12, #1 ");				// and increment exponent
	asm("cmpmi r12, #1 ");					// if mantissa normalised, check exponent>0
	asm("movmi r12, #1 ");					// if normalised and exponent=0, set exponent to 1
	asm("TRealXGetTReal32c: ");				// come here to truncate
	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
	asm("orr r0, r0, r12, lsl #23 ");		// exponent into r0 bits 23-30
	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
	asm("orr r0, r0, r2, lsr #8 ");			// non-integer mantissa bits into r0 bits 0-22
	asm("cmp r12, #0xFF ");					// check for overflow
	asm("mvneq r12, #8 ");					// if overflow, return KErrOverflow
	__JUMP(eq,lr);
	asm("bics r1, r0, #0x80000000 ");		// check for underflow
	asm("mvneq r12, #9 ");					// if underflow return KErrUnderflow
	asm("movne r12, #0 ");					// else return KErrNone
	__JUMP(,lr);
	asm("TRealXGetTReal32a: ");				// come here if overflow, infinity or NaN
	asm("cmn r3, #0x10000 ");				// check for infinity or NaN
	asm("movcc r2, #0 ");					// if not, set mantissa to 0 for infinity result
	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
	asm("orr r0, r0, #0x7F000000 ");		// r0 bits 23-30 = FF = exponent
	asm("orr r0, r0, #0x00800000 ");
	asm("orr r0, r0, r2, lsr #8 ");			// r0 bits 0-22 = result mantissa
	asm("movs r12, r0, lsl #9 ");			// check if result is infinity or NaN
	asm("mvneq r12, #8 ");					// if infinity return KErrOverflow
	asm("mvnne r12, #5 ");					// else return KErrArgument
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TInt TRealX::GetTReal(TReal64& /*aVal*/) const
/**
Extracts the extended precision value as
a double precision floating point value.

@param aVal A reference to a double precision object which
            contains the result of the operation.

@return KErrNone, if the operation is successful;
        KErrOverflow, if the operation results in overflow;
        KErrUnderflow, if the operation results in underflow.
*/
	{
	asm("stmfd sp!, {r4,lr} ");
	asm("mov r4, r1 ");
	asm("ldmia r0, {r1,r2,r3} ");			// r1,r2,r3=input value
	asm("bl TRealXGetTReal64 ");
	asm("stmia r4, {r0,r1} ");				// store converted TReal64
	asm("mov r0, r12 ");					// return value into r0
	__POPRET("r4,");

	// Convert TRealX in r1,r2,r3 to TReal64 in r0,r1
	// Return error code in r12
	// r0-r3, r12 modified
	asm("TRealXGetTReal64: ");
	asm("mov r12, #0x8300 ");
	asm("orr r12, r12, #0x00FF ");			// r12=0x83FF
	asm("cmp r3, r12, lsl #16 ");			// check if exponent>=83FF
	asm("bcs TRealXGetTReal64a ");			// branch if it is
	asm("mov r12, #0x7C00 ");
	asm("rsbs r12, r12, r3, lsr #16 ");		// r12=exp in - 7C00 = result exponent if in range
	asm("bgt TRealXGetTReal64b ");			// branch if normalised result
	asm("cmn r12, #52 ");					// check for total underflow or zero
	asm("bge TRealXGetTReal64g ");			// skip if not
	asm("mov r0, r3, lsl #31 ");			// else return zero with appropriate sign
	asm("mov r1, #0 ");
	asm("cmp r3, #0x10000 ");				// check for zero
	asm("movcc r12, #0 ");					// if zero return KErrNone
	asm("mvncs r12, #9 ");					// else return KErrUnderflow
	asm("b TRealXGetTReal64_end ");

	asm("TRealXGetTReal64g: ");
	asm("adds r12, r12, #31 ");				// check if >=32 shifts needed, r12=32-shift count
	asm("ble TRealXGetTReal64e ");			// branch if >=32 shifts needed
	asm("movs r0, r1, lsl r12 ");			// r0=lost bits when r2:r1 is shifted
	asm("bicne r3, r3, #0x300 ");			// if these are not zero, set rounded down flag
	asm("orrne r3, r3, #0x100 ");
	asm("rsb r0, r12, #32 ");				// r0=shift count
	asm("mov r1, r1, lsr r0 ");
	asm("orr r1, r1, r2, lsl r12 ");
	asm("mov r2, r2, lsr r0 ");				// r2:r1 top 53 bits = unrounded result mantissa
	asm("b TRealXGetTReal64f ");
	asm("TRealXGetTReal64e: ");
	asm("add r12, r12, #32 ");				// r12=64-shift count
	asm("cmp r1, #0 ");						// r1 bits are all lost - test them
	asm("moveqs r0, r2, lsl r12 ");			// if zero, test lost bits from r2
	asm("bicne r3, r3, #0x300 ");			// if lost bits not all zero, set rounded down flag
	asm("orrne r3, r3, #0x100 ");
	asm("rsb r0, r12, #32 ");				// r0=shift count-32
	asm("mov r1, r2, lsr r0 ");				// shift r2:r1 right
	asm("mov r2, #0 ");
	asm("TRealXGetTReal64f: ");
	asm("mov r12, #0 ");					// result exponent will be zero for denormals
	asm("TRealXGetTReal64b: ");
	asm("movs r0, r1, lsl #21 ");			// 11 rounding bits to top of r0
	asm("bpl TRealXGetTReal64c ");			// if top bit clear, truncate
	asm("cmp r0, #0x80000000 ");			// compare rounding bits to 10000000000
	asm("bhi TRealXGetTReal64d ");			// if >, round up
	asm("movs r0, r3, lsl #23 ");			// round up flag into C, round down flag into N
	asm("bcs TRealXGetTReal64c ");			// if rounded up, truncate
	asm("bmi TRealXGetTReal64d ");			// if rounded down, round up
	asm("tst r1, #0x800 ");					// else round to even - test LSB of result mantissa
	asm("beq TRealXGetTReal64c ");			// if zero, truncate, else round up
	asm("TRealXGetTReal64d: ");				// come here to round up
	asm("adds r1, r1, #0x800 ");			// increment the mantissa
	asm("adcs r2, r2, #0 ");
	asm("movcs r2, #0x80000000 ");			// if carry, mantissa=10000...0
	asm("addcs r12, r12, #1 ");				// and increment exponent
	asm("cmpmi r12, #1 ");					// if mantissa normalised, check exponent>0
	asm("movmi r12, #1 ");					// if normalised and exponent=0, set exponent to 1
	asm("TRealXGetTReal64c: ");				// come here to truncate
	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
	asm("orr r0, r0, r12, lsl #20 ");		// exponent into r0 bits 20-30
	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
	asm("orr r0, r0, r2, lsr #11 ");		// non-integer mantissa bits into r0 bits 0-19
	asm("mov r1, r1, lsr #11 ");			// and r1
	asm("orr r1, r1, r2, lsl #21 ");
	asm("add r12, r12, #1 ");
	asm("cmp r12, #0x800 ");				// check for overflow
	asm("mvneq r12, #8 ");					// if overflow, return KErrOverflow
	asm("beq TRealXGetTReal64_end ");

	asm("bics r12, r0, #0x80000000 ");		// check for underflow
	asm("cmpeq r1, #0 ");
	asm("mvneq r12, #9 ");					// if underflow return KErrUnderflow
	asm("movne r12, #0 ");					// else return KErrNone
	asm("b TRealXGetTReal64_end ");

	asm("TRealXGetTReal64a: ");				// come here if overflow, infinity or NaN
	asm("cmn r3, #0x10000 ");				// check for infinity or NaN
	asm("movcc r2, #0 ");					// if not, set mantissa to 0 for infinity result
	asm("movcc r1, #0 ");
	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
	asm("mov r0, r3, lsl #31 ");			// r0 bit 31 = sign bit
	asm("orr r0, r0, #0x7F000000 ");		// r0 bits 20-30 = 7FF = exponent
	asm("orr r0, r0, #0x00F00000 ");
	asm("orr r0, r0, r2, lsr #11 ");		// r0 bits 0-19 = result mantissa high bits
	asm("mov r1, r1, lsr #11 ");			// and r1=result mantissa low bits
	asm("orr r1, r1, r2, lsl #21 ");
	asm("movs r12, r0, lsl #12 ");			// check if result is infinity or NaN
	asm("cmpeq r1, #0 ");
	asm("mvneq r12, #8 ");					// if infinity return KErrOverflow
	asm("mvnne r12, #5 ");					// else return KErrArgument
	asm("TRealXGetTReal64_end: ");
#ifndef __DOUBLE_WORDS_SWAPPED__
	asm("mov r2, r0 ");
	asm("mov r0, r1 ");
	asm("mov r1, r2 ");
#endif
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TRealX TRealX::operator+() const
/**
Returns this extended precision number unchanged.

Note that this may also be referred to as a unary plus operator. 

@return The extended precision number.
*/
	{
	asm("ldmia r1, {r2,r3,r12} ");
	asm("stmia r0, {r2,r3,r12} ");
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TRealX TRealX::operator-() const
/**
Negates this extended precision number.

This may also be referred to as a unary minus operator.

@return The negative of the extended precision number.
*/
	{
	asm("ldmia r1, {r2,r3,r12} ");
	asm("eor r12, r12, #1 ");			// unary - changes sign bit
	asm("stmia r0, {r2,r3,r12} ");
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TRealX::TRealXOrder TRealX::Compare(const TRealX& /*aVal*/) const
/**
*/
	{
	asm("stmfd sp!, {r4,r5,r6,lr} ");
	asm("ldmia r1, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXCompare ");
	__POPRET("r4-r6,");

	// Compare TRealX in r1,r2,r3 to TRealX in r4,r5,r6
	// Return TRealXOrder result in r0
	asm("TRealXCompare: ");
	asm("cmn r3, #0x10000 ");				// check for NaNs/infinity
	asm("bcs TRealXCompare1 ");
	asm("TRealXCompare6: ");				// will come back here if infinity
	asm("cmn r6, #0x10000 ");
	asm("bcs TRealXCompare2 ");
	asm("TRealXCompare7: ");				// will come back here if infinity
	asm("cmp r3, #0x10000 ");				// check for zeros
	asm("bcc TRealXCompare3 ");
	asm("cmp r6, #0x10000 ");
	asm("bcc TRealXCompare4 ");
	asm("mov r12, r6, lsl #31 ");
	asm("cmp r12, r3, lsl #31 ");			// compare signs
	asm("movne r0, #4 ");
	asm("bne TRealXCompare5 ");				// branch if signs different
	asm("mov r12, r3, lsr #16 ");			// r12=first exponent
	asm("cmp r12, r6, lsr #16 ");			// compare exponents
	asm("cmpeq r2, r5 ");					// if equal compare high words of mantissa
	asm("cmpeq r1, r4 ");					// if equal compare low words of mantissa
	asm("moveq r0, #2 ");					// if equal return 2
	__JUMP(eq,lr);
	asm("movhi r0, #4 ");					// r0=4 if first exp bigger
	asm("movcc r0, #1 ");					// else r0=1
	asm("TRealXCompare5: ");
	asm("tst r3, #1 ");						// if signs negative
	asm("eorne r0, r0, #5 ");				// then switch 1 and 4
	__JUMP(,lr);
	asm("TRealXCompare3: ");				// first operand zero
	asm("cmp r6, #0x10000 ");				// check if second also zero
	asm("movcc r0, #2 ");					// if so, return 2
	__JUMP(cc,lr);
	asm("tst r6, #1 ");						// else check sign of operand 2
	asm("moveq r0, #1 ");					// if +, return 1
	asm("movne r0, #4 ");					// else return 4
	__JUMP(,lr);
	asm("TRealXCompare4: ");				// second operand zero, first nonzero
	asm("tst r3, #1 ");						// check sign of operand 1
	asm("moveq r0, #4 ");					// if +, return 4
	asm("movne r0, #1 ");					// else return 1
	__JUMP(,lr);
	asm("TRealXCompare1: ");				// first operand NaN or infinity
	asm("cmp r2, #0x80000000 ");			// check for infinity
	asm("cmpeq r1, #0 ");
	asm("beq TRealXCompare6 ");				// if infinity, can handle normally
	asm("mov r0, #8 ");						// if NaN, return 8 (unordered)
	__JUMP(,lr);
	asm("TRealXCompare2: ");				// second operand NaN or infinity
	asm("cmp r5, #0x80000000 ");			// check for infinity
	asm("cmpeq r4, #0 ");
	asm("beq TRealXCompare7 ");				// if infinity, can handle normally
	asm("mov r0, #8 ");						// if NaN, return 8 (unordered)
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TInt TRealX::SubEq(const TRealX& /*aVal*/)
/**
Subtracts an extended precision value from this extended precision number.

@param aVal The extended precision value to be subtracted.

@return KErrNone, if the operation is successful;
        KErrOverflow, if the operation results in overflow;
        KErrUnderflow, if the operation results in underflow.
*/
	{
	asm("stmfd sp!, {r0,r4-r8,lr} ");
	asm("ldmia r1, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXSubtract ");
	asm("ldmfd sp!, {r0,r4-r8,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("mov r0, r12 ");
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TInt TRealX::AddEq(const TRealX& /*aVal*/)
/**
Adds an extended precision value to this extended precision number.

@param aVal The extended precision value to be added.

@return KErrNone, if the operation is successful;
        KErrOverflow,if the operation results in overflow;
        KErrUnderflow, if the operation results in underflow. 
*/
	{
	asm("stmfd sp!, {r0,r4-r8,lr} ");
	asm("ldmia r1, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXAdd ");
	asm("ldmfd sp!, {r0,r4-r8,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("mov r0, r12 ");
	__JUMP(,lr);

	// TRealX subtraction r1,r2,r3 - r4,r5,r6 result in r1,r2,r3
	// Error code returned in r12
	// Registers r0-r8,r12 modified
	// NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE.
	asm("TRealXSubtract: ");
	asm("eor r6, r6, #1 ");					// negate second operand and add

	// TRealX addition r1,r2,r3 + r4,r5,r6 result in r1,r2,r3
	// Error code returned in r12
	// Registers r0-r8,r12 modified
	// NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE.
	// Note:	+0 + +0 = +0, -0 + -0 = -0, +0 + -0 = -0 + +0 = +0,
	//			+/-0 + X = X + +/-0 = X, X + -X = -X + X = +0
	asm("TRealXAdd: ");
	asm("mov r12, #0 ");					// initialise return value to KErrNone
	asm("bic r3, r3, #0x300 ");				// clear rounding flags
	asm("bic r6, r6, #0x300 ");				// clear rounding flags
	asm("cmn r3, #0x10000 ");				// check if first operand is NaN or infinity
	asm("bcs TRealXAdd1 ");					// branch if it is
	asm("cmn r6, #0x10000 ");				// check if second operand is NaN or infinity
	asm("bcs TRealXAdd2 ");					// branch if it is
	asm("cmp r6, #0x10000 ");				// check if second operand zero
	asm("bcc TRealXAdd3a ");				// branch if it is
	asm("cmp r3, #0x10000 ");				// check if first operand zero
	asm("bcc TRealXAdd3 ");					// branch if it is
	asm("mov r7, #0 ");						// r7 will be rounding word
	asm("mov r0, r3, lsr #16 ");			// r0 = first operand exponent
	asm("subs r0, r0, r6, lsr #16 ");		// r0 = first exponent - second exponent
	asm("beq TRealXAdd8 ");					// if equal, no mantissa shifting needed
	asm("bhi TRealXAdd4 ");					// skip if first exponent bigger
	asm("rsb r0, r0, #0 ");					// need to shift first mantissa right by r0 to align
	asm("mov r8, r1 ");						// swap the numbers to the one to be shifted is 2nd
	asm("mov r1, r4 ");
	asm("mov r4, r8 ");
	asm("mov r8, r2 ");
	asm("mov r2, r5 ");
	asm("mov r5, r8 ");
	asm("mov r8, r3 ");
	asm("mov r3, r6 ");
	asm("mov r6, r8 ");
	asm("TRealXAdd4: ");					// need to shift 2nd mantissa right by r0 to align
	asm("cmp r0, #64 ");					// more than 64 shifts needed?
	asm("bhi TRealXAdd6 ");					// if so, smaller number cannot affect larger
	asm("cmp r0, #32 ");
	asm("bhi TRealXAdd7 ");					// branch if shift count>32
	asm("rsb r8, r0, #32 ");
	asm("mov r7, r4, lsl r8 ");				// shift r5:r4 right into r7
	asm("mov r4, r4, lsr r0 ");
	asm("orr r4, r4, r5, lsl r8 ");
	asm("mov r5, r5, lsr r0 ");
	asm("b TRealXAdd8 ");
	asm("TRealXAdd7: ");					// 64 >= shift count > 32
	asm("sub r0, r0, #32 ");
	asm("rsb r8, r0, #32 ");
	asm("movs r7, r4, lsl r8 ");			// test bits lost in shift
	asm("orrne r6, r6, #0x100 ");			// if not all zero, flag 2nd mantissa rounded down
	asm("mov r7, r4, lsr r0 ");				// shift r5:r4 right into r7 by 32+r0
	asm("orr r7, r7, r5, lsl r8 ");
	asm("mov r4, r5, lsr r0 ");
	asm("mov r5, #0 ");
	asm("TRealXAdd8: ");					// mantissas are now aligned
	asm("mov r8, r3, lsl #31 ");			// r8=sign of first operand
	asm("cmp r8, r6, lsl #31 ");			// compare signs
	asm("bne TRealXSub1 ");					// if different, need to do a subtraction
	asm("adds r1, r1, r4 ");				// signs the same - add mantissas
	asm("adcs r2, r2, r5 ");
	asm("bcc TRealXAdd9 ");					// skip if no carry
	asm(".word 0xE1B02062 ");				// movs r2, r2, rrx shift carry into mantissa
	asm(".word 0xE1B01061 ");				// movs r1, r1, rrx
	asm(".word 0xE1B07067 ");				// movs r7, r7, rrx
	asm("orrcs r6, r6, #0x100 ");			// if 1 shifted out, flag 2nd mantissa rounded down
	asm("add r3, r3, #0x10000 ");			// increment exponent
	asm("TRealXAdd9: ");
	asm("cmp r7, #0x80000000 ");			// check rounding word
	asm("bcc TRealXAdd10 ");				// if <0x80000000 round down
	asm("bhi TRealXAdd11 ");				// if >0x80000000 round up
	asm("tst r6, #0x100 ");					// if =0x80000000 check if 2nd mantissa rounded down
	asm("bne TRealXAdd11 ");				// if so, round up
	asm("tst r6, #0x200 ");					// if =0x80000000 check if 2nd mantissa rounded up
	asm("bne TRealXAdd10 ");				// if so, round down
	asm("tst r1, #1 ");						// else round to even - check LSB
	asm("beq TRealXAdd10 ");				// if zero, round down
	asm("TRealXAdd11: ");					// come here to round up
	asm("adds r1, r1, #1 ");				// increment mantissa
	asm("adcs r2, r2, #0 ");
	asm("movcs r2, #0x80000000 ");			// if carry, mantissa = 80000000 00000000
	asm("addcs r3, r3, #0x10000 ");			// and increment exponent
	asm("cmn r3, #0x10000 ");				// check overflow
	asm("orrcc r3, r3, #0x200 ");			// if no overflow, set rounded-up flag ...
	__JUMP(cc,lr);
	asm("b TRealXAdd12 ");					// if overflow, return infinity
	asm("TRealXAdd10: ");					// come here to round down
	asm("cmn r3, #0x10000 ");				// check overflow
	asm("bcs TRealXAdd12 ");				// if overflow, return infinity
	asm("cmp r7, #0 ");						// if no overflow check if rounding word is zero
	asm("orrne r3, r3, #0x100 ");			// if not, set rounded-down flag ...
	__JUMP(ne,lr);
	asm("and r6, r6, #0x300 ");				// else transfer 2nd mantissa rounding flags
	asm("orr r3, r3, r6 ");					// to result
	__JUMP(,lr);

	asm("TRealXAdd12: ");					// come here if overflow - return infinity
	asm("mov r2, #0x80000000 ");
	asm("mov r1, #0 ");
	asm("mvn r12, #8 ");					// and return KErrOverflow
	__JUMP(,lr);

	asm("TRealXSub1: ");					// come here if operand signs differ
	asm("tst r6, #0x300 ");					// check if 2nd mantissa rounded
	asm("eorne r6, r6, #0x300 ");			// if so, change rounding
	asm("rsbs r7, r7, #0 ");				// subtract mantissas r2:r1:0 -= r5:r4:r7
	asm("sbcs r1, r1, r4 ");
	asm("sbcs r2, r2, r5 ");
	asm("bcs TRealXSub2 ");					// skip if no borrow
	asm("tst r6, #0x300 ");					// check if 2nd mantissa rounded
	asm("eorne r6, r6, #0x300 ");			// if so, change rounding
	asm("rsbs r7, r7, #0 ");				// negate result
	asm("rscs r1, r1, #0 ");
	asm("rscs r2, r2, #0 ");
	asm("eor r3, r3, #1 ");					// and change result sign
	asm("TRealXSub2: ");
	asm("bne TRealXSub3 ");					// skip if mantissa top word is not zero
	asm("movs r2, r1 ");					// else shift up by 32
	asm("mov r1, r7 ");
	asm("mov r7, #0 ");
	asm("bne TRealXSub3a ");				// skip if mantissa top word is not zero now
	asm("movs r2, r1 ");					// else shift up by 32 again
	asm("mov r1, #0 ");
	asm("moveq r3, #0 ");					// if r2 still zero, result is zero - return +0
	__JUMP(eq,lr);
	asm("subs r3, r3, #0x00400000 ");		// else, decrement exponent by 64
	asm("bcs TRealXSub3 ");					// if no borrow, proceed
	asm("b TRealXSub4 ");					// if borrow, underflow
	asm("TRealXSub3a: ");					// needed one 32-bit shift
	asm("subs r3, r3, #0x00200000 ");		// so decrement exponent by 32
	asm("bcc TRealXSub4 ");					// if borrow, underflow
	asm("TRealXSub3: ");					// r2 is now non-zero; still may need up to 31 shifts
#ifdef __CPU_ARM_HAS_CLZ
	CLZ(0,2);
	asm("mov r2, r2, lsl r0 ");
#else
	asm("mov r0, #0 ");						// r0 will be shift count
	asm("cmp r2, #0x00010000 ");
	asm("movcc r2, r2, lsl #16 ");
	asm("addcc r0, r0, #16 ");
	asm("cmp r2, #0x01000000 ");
	asm("movcc r2, r2, lsl #8 ");
	asm("addcc r0, r0, #8 ");
	asm("cmp r2, #0x10000000 ");
	asm("movcc r2, r2, lsl #4 ");
	asm("addcc r0, r0, #4 ");
	asm("cmp r2, #0x40000000 ");
	asm("movcc r2, r2, lsl #2 ");
	asm("addcc r0, r0, #2 ");
	asm("cmp r2, #0x80000000 ");
	asm("movcc r2, r2, lsl #1 ");
	asm("addcc r0, r0, #1 ");
#endif
	asm("rsb r8, r0, #32 ");
	asm("subs r3, r3, r0, lsl #16 ");		// subtract shift count from exponent
	asm("bcc TRealXSub4 ");					// if borrow, underflow
	asm("orr r2, r2, r1, lsr r8 ");			// else shift mantissa up
	asm("mov r1, r1, lsl r0 ");
	asm("orr r1, r1, r7, lsr r8 ");
	asm("mov r7, r7, lsl r0 ");
	asm("cmp r3, #0x10000 ");				// check for underflow
	asm("bcs TRealXAdd9 ");					// if no underflow, branch to round result

	asm("TRealXSub4: ");					// come here if underflow
	asm("and r3, r3, #1 ");					// set exponent to zero, leave sign
	asm("mov r2, #0 ");
	asm("mov r1, #0 ");
	asm("mvn r12, #9 ");					// return KErrUnderflow
	__JUMP(,lr);

	asm("TRealXAdd6: ");					// come here if exponents differ by more than 64
	asm("mov r8, r3, lsl #31 ");			// r8=sign of first operand
	asm("cmp r8, r6, lsl #31 ");			// compare signs
	asm("orreq r3, r3, #0x100 ");			// if same, result has been rounded down
	asm("orrne r3, r3, #0x200 ");			// else result has been rounded up
	__JUMP(,lr);

	asm("TRealXAdd3a: ");					// come here if second operand zero
	asm("cmp r3, #0x10000 ");				// check if first operand also zero
	asm("andcc r3, r3, r6 ");				// if so, result is negative iff both zeros negative
	asm("andcc r3, r3, #1 ");
	__JUMP(,lr);

	asm("TRealXAdd3: ");					// come here if first operand zero, second nonzero
	asm("mov r1, r4 ");						// return second operand unchanged
	asm("mov r2, r5 ");
	asm("mov r3, r6 ");
	__JUMP(,lr);

	asm("TRealXAdd1: ");					// come here if first operand NaN or infinity
	asm("cmp r2, #0x80000000 ");			// check for infinity
	asm("cmpeq r1, #0 ");
	asm("bne TRealXBinOpNan ");				// branch if NaN
	asm("cmn r6, #0x10000 ");				// check 2nd operand for NaN/infinity
	asm("mvncc r12, #8 ");					// if neither, return KErrOverflow
	__JUMP(cc,lr);
	asm("cmp r5, #0x80000000 ");			// check 2nd operand for infinity
	asm("cmpeq r4, #0 ");
	asm("bne TRealXBinOpNan ");				// branch if NaN
	asm("mov r0, r3, lsl #31 ");			// both operands are infinity - check signs
	asm("cmp r0, r6, lsl #31 ");
	asm("mvneq r12, #8 ");					// if same, return KErrOverflow
	__JUMP(eq,lr);

	// Return 'real indefinite'
	asm("TRealXRealIndefinite: ");
	asm("ldr r3, [pc, #__RealIndefiniteExponent-.-8] ");
	asm("mov r2, #0xC0000000 ");
	asm("mov r1, #0 ");
	asm("mvn r12, #5 ");					// return KErrArgument
	__JUMP(,lr);

	asm("TRealXAdd2: ");					// come here if 2nd operand NaN/infinity, first finite
	asm("cmp r5, #0x80000000 ");			// check for infinity
	asm("cmpeq r4, #0 ");
	asm("bne TRealXBinOpNan ");				// branch if NaN
	asm("mov r1, r4 ");						// else return 2nd operand (infinity)
	asm("mov r2, r5 ");
	asm("mov r3, r6 ");
	asm("mvn r12, #8 ");					// return KErrOverflow
	__JUMP(,lr);

	asm("TRealXBinOpNan: ");				// generic routine to process NaNs in binary
											// operations
	asm("cmn r3, #0x10000 ");				// check if first operand is NaN
	asm("movcc r0, r1 ");					// if not, swap the operands
	asm("movcc r1, r4 ");
	asm("movcc r4, r0 ");
	asm("movcc r0, r2 ");
	asm("movcc r2, r5 ");
	asm("movcc r5, r0 ");
	asm("movcc r0, r3 ");
	asm("movcc r3, r6 ");
	asm("movcc r6, r0 ");
	asm("cmn r6, #0x10000 ");				// both operands NaNs?
	asm("bcc TRealXBinOpNan1 ");			// skip if not
	asm("cmp r2, r5 ");						// if so, compare the significands
	asm("cmpeq r1, r4 ");
	asm("movcc r1, r4 ");					// r1,r2,r3 will get NaN with larger significand
	asm("movcc r2, r5 ");
	asm("movcc r3, r6 ");
	asm("TRealXBinOpNan1: ");
	asm("orr r2, r2, #0x40000000 ");		// convert an SNaN to a QNaN
	asm("mvn r12, #5 ");					// return KErrArgument
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TInt TRealX::MultEq(const TRealX& /*aVal*/)
/**
Multiplies this extended precision number by an extended precision value.

@param aVal The extended precision value to be used as the multiplier.

@return KErrNone, if the operation is successful;
        KErrOverflow, if the operation results in overflow;
        KErrUnderflow, if the operation results in underflow
*/
	{
	// Version for ARM 3M or later
	// Uses umull/umlal
	asm("stmfd sp!, {r0,r4-r7,lr} ");
	asm("ldmia r1, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXMultiply ");
	asm("ldmfd sp!, {r0,r4-r7,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("mov r0, r12 ");
	__JUMP(,lr);

	// TRealX multiplication r1,r2,r3 * r4,r5,r6 result in r1,r2,r3
	// Error code returned in r12
	// Registers r0-r7,r12 modified
	// NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE.
	asm("TRealXMultiply: ");
	asm("mov r12, #0 ");					// initialise return value to KErrNone
	asm("bic r3, r3, #0x300 ");				// clear rounding flags
	asm("tst r6, #1 ");
	asm("eorne r3, r3, #1 ");				// Exclusive-OR signs
	asm("cmn r3, #0x10000 ");				// check if first operand is NaN or infinity
	asm("bcs TRealXMultiply1 ");			// branch if it is
	asm("cmn r6, #0x10000 ");				// check if second operand is NaN or infinity
	asm("bcs TRealXMultiply2 ");			// branch if it is
	asm("cmp r3, #0x10000 ");				// check if first operand zero
	__JUMP(cc,lr);							// if so, exit

	// Multiply mantissas in r2:r1 and r5:r4, result in r2:r1:r12:r7
	asm("umull r7, r12, r1, r4 ");			// r7:r12=m1.low*m2.low
	asm("movs r0, r6, lsr #16 ");			// r0=2nd operand exponent
	asm("beq TRealXMultiply3 ");			// if zero, return zero
	asm("mov r6, #0 ");						// clear r6 initially
	asm("umlal r12, r6, r1, r5 ");			// r6:r12:r7=m1.low*m2, r1 no longer needed
	asm("add r0, r0, r3, lsr #16 ");		// r0=sum of exponents
	asm("tst r3, #1 ");
	asm("mov r3, #0 ");						// clear r3 initially
	asm("umlal r6, r3, r2, r5 ");			// r3:r6:r12:r7=m2.low*m1+m2.high*m1.high<<64
											// r1,r5 no longer required
	asm("orrne lr, lr, #1 ");				// save sign in bottom bit of lr
	asm("sub r0, r0, #0x7F00 ");
	asm("sub r0, r0, #0x00FE ");			// r0 now contains result exponent
	asm("umull r1, r5, r2, r4 ");			// r5:r1=m2.high*m1.low
	asm("adds r12, r12, r1 ");				// shift left by 32 and add to give final result
	asm("adcs r1, r6, r5 ");
	asm("adcs r2, r3, #0 ");				// final result now in r2:r1:r12:r7
											// set flags on final value of r2 (ms word of result)

	// normalise the result mantissa
	asm("bmi TRealXMultiply4 ");			// skip if already normalised
	asm("adds r7, r7, r7 ");				// else shift left (will only ever need one shift)
	asm("adcs r12, r12, r12 ");
	asm("adcs r1, r1, r1 ");
	asm("adcs r2, r2, r2 ");
	asm("sub r0, r0, #1 ");					// and decrement exponent by one

	// round the result mantissa
	asm("TRealXMultiply4: ");
	asm("and r3, lr, #1 ");					// result sign bit back into r3
	asm("orrs r4, r7, r12 ");				// check for exact result
	asm("beq TRealXMultiply5 ");			// skip if exact
	asm("cmp r12, #0x80000000 ");			// compare bottom 64 bits to 80000000 00000000
	asm("cmpeq r7, #0 ");
	asm("moveqs r4, r1, lsr #1 ");			// if exactly equal, set carry=lsb of result
											// so we round up if lsb=1
	asm("orrcc r3, r3, #0x100 ");			// if rounding down, set rounded-down flag
	asm("orrcs r3, r3, #0x200 ");			// if rounding up, set rounded-up flag
	asm("adcs r1, r1, #0 ");				// increment mantissa if necessary
	asm("adcs r2, r2, #0 ");
	asm("movcs r2, #0x80000000 ");			// if carry, set mantissa to 80000000 00000000
	asm("addcs r0, r0, #1 ");				// and increment result exponent

	// check for overflow or underflow and assemble final result
	asm("TRealXMultiply5: ");
	asm("add r4, r0, #1 ");					// need to add 1 to get usable threshold
	asm("cmp r4, #0x10000 ");				// check if exponent >= 0xFFFF
	asm("bge TRealXMultiply6 ");			// if so, overflow
	asm("cmp r0, #0 ");						// check for underflow
	asm("orrgt r3, r3, r0, lsl #16 ");		// if no underflow, result exponent into r3, ...
	asm("movgt r12, #0 ");					// ... return KErrNone ...
	asm("bicgt pc, lr, #3 ");

	// underflow
	asm("mvn r12, #9 ");					// return KErrUnderflow
	asm("bic pc, lr, #3 ");

	// overflow
	asm("TRealXMultiply6: ");
	asm("bic r3, r3, #0x0000FF00 ");		// clear rounding flags
	asm("orr r3, r3, #0xFF000000 ");		// make exponent FFFF for infinity
	asm("orr r3, r3, #0x00FF0000 ");
	asm("mov r2, #0x80000000 ");			// mantissa = 80000000 00000000
	asm("mov r1, #0 ");
	asm("mvn r12, #8 ");					// return KErrOverflow
	asm("bic pc, lr, #3 ");

	// come here if second operand zero
	asm("TRealXMultiply3: ");
	asm("mov r1, #0 ");
	asm("mov r2, #0 ");
	asm("and r3, r3, #1 ");					// zero exponent, keep xor sign
	asm("mov r12, #0 ");					// return KErrNone
	asm("bic pc, lr, #3 ");

	// First operand NaN or infinity
	asm("TRealXMultiply1: ");
	asm("cmp r2, #0x80000000 ");			// check for infinity
	asm("cmpeq r1, #0 ");
	asm("bne TRealXBinOpNan ");				// branch if NaN
	asm("cmn r6, #0x10000 ");				// check 2nd operand for NaN/infinity
	asm("bcs TRealXMultiply1a ");			// branch if it is
	asm("cmp r6, #0x10000 ");				// else check if second operand zero
	asm("mvncs r12, #8 ");					// if not, return infinity and KErrOverflow
	asm("biccs pc, lr, #3 ");
	asm("b TRealXRealIndefinite ");			// else return 'real indefinite'

	asm("TRealXMultiply1a: ");
	asm("cmp r5, #0x80000000 ");			// check 2nd operand for infinity
	asm("cmpeq r4, #0 ");
	asm("bne TRealXBinOpNan ");				// branch if NaN
	asm("mvn r12, #8 ");					// else (infinity), return KErrOverflow
	asm("bic pc, lr, #3 ");

	// Second operand NaN or infinity, first operand finite
	asm("TRealXMultiply2: ");
	asm("cmp r5, #0x80000000 ");			// check for infinity
	asm("cmpeq r4, #0 ");
	asm("bne TRealXBinOpNan ");				// branch if NaN
	asm("cmp r3, #0x10000 ");				// if infinity, check if first operand zero
	asm("bcc TRealXRealIndefinite ");		// if it is, return 'real indefinite'
	asm("orr r3, r3, #0xFF000000 ");		// else return infinity with xor sign
	asm("orr r3, r3, #0x00FF0000 ");
	asm("mov r2, #0x80000000 ");
	asm("mov r1, #0 ");
	asm("mvn r12, #8 ");					// return KErrOverflow
	asm("bic pc, lr, #3 ");
	}




__NAKED__ EXPORT_C TInt TRealX::DivEq(const TRealX& /*aVal*/)
/**
Divides this extended precision number by an extended precision value.

@param aVal The extended precision value to be used as the divisor.

@return KErrNone, if the operation is successful;
        KErrOverflow, if the operation results in overflow;
        KErrUnderflow, if the operation results in underflow;
        KErrDivideByZero, if the divisor is zero. 
*/
	{
	asm("stmfd sp!, {r0,r4-r9,lr} ");
	asm("ldmia r1, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXDivide ");
	asm("ldmfd sp!, {r0,r4-r9,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("mov r0, r12 ");
	__JUMP(,lr);

	// TRealX division r1,r2,r3 / r4,r5,r6 result in r1,r2,r3
	// Error code returned in r12
	// Registers r0-r9,r12 modified
	// NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE.
	asm("TRealXDivide: ");
	asm("mov r12, #0 ");					// initialise return value to KErrNone
	asm("bic r3, r3, #0x300 ");				// clear rounding flags
	asm("tst r6, #1 ");
	asm("eorne r3, r3, #1 ");				// Exclusive-OR signs
	asm("cmn r3, #0x10000 ");				// check if dividend is NaN or infinity
	asm("bcs TRealXDivide1 ");				// branch if it is
	asm("cmn r6, #0x10000 ");				// check if divisor is NaN or infinity
	asm("bcs TRealXDivide2 ");				// branch if it is
	asm("cmp r6, #0x10000 ");				// check if divisor zero
	asm("bcc TRealXDivide3 ");				// branch if it is
	asm("cmp r3, #0x10000 ");				// check if dividend zero
	__JUMP(cc,lr);							// if zero, exit
	asm("tst r3, #1 ");
	asm("orrne lr, lr, #1 ");				// save sign in bottom bit of lr

	// calculate result exponent
	asm("mov r0, r3, lsr #16 ");			// r0=dividend exponent
	asm("sub r0, r0, r6, lsr #16 ");		// r0=dividend exponent - divisor exponent
	asm("add r0, r0, #0x7F00 ");
	asm("add r0, r0, #0x00FF ");			// r0 now contains result exponent
	asm("mov r6, r1 ");						// move dividend into r6,r7,r8
	asm("mov r7, r2 ");
	asm("mov r8, #0 ");						// use r8 to hold extra bit shifted up
											// r2:r1 will hold result mantissa
	asm("mov r2, #1 ");						// we will make sure first bit is 1
	asm("cmp r7, r5 ");						// compare dividend mantissa to divisor mantissa
	asm("cmpeq r6, r4 ");
	asm("bcs TRealXDivide4 ");				// branch if dividend >= divisor
	asm("adds r6, r6, r6 ");				// else shift dividend left one
	asm("adcs r7, r7, r7 ");				// ignore carry here
	asm("sub r0, r0, #1 ");					// decrement result exponent by one
	asm("TRealXDivide4: ");
	asm("subs r6, r6, r4 ");				// subtract divisor from dividend
	asm("sbcs r7, r7, r5 ");

	// Main mantissa division code
	// First calculate the top 32 bits of the result
	// Top bit is 1, do 10 lots of 3 bits the one more bit
	asm("mov r12, #10 ");
	asm("TRealXDivide5: ");
	asm("adds r6, r6, r6 ");				// shift accumulator left by one
	asm("adcs r7, r7, r7 ");
	asm("adcs r8, r8, r8 ");
	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
	asm("sbcs r3, r7, r5 ");
	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
	asm("movcs r7, r3 ");
	asm("adcs r2, r2, r2 ");				// shift in new result bit
	asm("adds r6, r6, r6 ");				// shift accumulator left by one
	asm("adcs r7, r7, r7 ");
	asm("adcs r8, r8, r8 ");
	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
	asm("sbcs r3, r7, r5 ");
	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
	asm("movcs r7, r3 ");
	asm("adcs r2, r2, r2 ");				// shift in new result bit
	asm("adds r6, r6, r6 ");				// shift accumulator left by one
	asm("adcs r7, r7, r7 ");
	asm("adcs r8, r8, r8 ");
	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
	asm("sbcs r3, r7, r5 ");
	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
	asm("movcs r7, r3 ");
	asm("adcs r2, r2, r2 ");				// shift in new result bit
	asm("subs r12, r12, #1 ");
	asm("bne TRealXDivide5 ");				// iterate the loop
	asm("adds r6, r6, r6 ");				// shift accumulator left by one
	asm("adcs r7, r7, r7 ");
	asm("adcs r8, r8, r8 ");
	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
	asm("sbcs r3, r7, r5 ");
	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
	asm("movcs r7, r3 ");
	asm("adcs r2, r2, r2 ");				// shift in new result bit - now have 32 bits

	// Now calculate the bottom 32 bits of the result
	// Do 8 lots of 4 bits
	asm("mov r12, #8 ");
	asm("TRealXDivide5a: ");
	asm("adds r6, r6, r6 ");				// shift accumulator left by one
	asm("adcs r7, r7, r7 ");
	asm("adcs r8, r8, r8 ");
	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
	asm("sbcs r3, r7, r5 ");
	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
	asm("movcs r7, r3 ");
	asm("adcs r1, r1, r1 ");				// shift in new result bit
	asm("adds r6, r6, r6 ");				// shift accumulator left by one
	asm("adcs r7, r7, r7 ");
	asm("adcs r8, r8, r8 ");
	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
	asm("sbcs r3, r7, r5 ");
	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
	asm("movcs r7, r3 ");
	asm("adcs r1, r1, r1 ");				// shift in new result bit
	asm("adds r6, r6, r6 ");				// shift accumulator left by one
	asm("adcs r7, r7, r7 ");
	asm("adcs r8, r8, r8 ");
	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
	asm("sbcs r3, r7, r5 ");
	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
	asm("movcs r7, r3 ");
	asm("adcs r1, r1, r1 ");				// shift in new result bit
	asm("adds r6, r6, r6 ");				// shift accumulator left by one
	asm("adcs r7, r7, r7 ");
	asm("adcs r8, r8, r8 ");
	asm("subs r9, r6, r4 ");				// subtract divisor from accumulator, result in r9,r3
	asm("sbcs r3, r7, r5 ");
	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
	asm("movcs r6, r9 ");					// if no borrow, replace accumulator with result
	asm("movcs r7, r3 ");
	asm("adcs r1, r1, r1 ");				// shift in new result bit
	asm("subs r12, r12, #1 ");
	asm("bne TRealXDivide5a ");				// iterate the loop

	// r2:r1 now contains a 64-bit normalised mantissa
	// need to do rounding now
	asm("and r3, lr, #1 ");					// result sign back into r3
	asm("orrs r9, r6, r7 ");				// check if accumulator zero
	asm("beq TRealXDivide6 ");				// if it is, result is exact, else generate next bit
	asm("adds r6, r6, r6 ");				// shift accumulator left by one
	asm("adcs r7, r7, r7 ");
	asm("adcs r8, r8, r8 ");
	asm("subs r6, r6, r4 ");				// subtract divisor from accumulator
	asm("sbcs r7, r7, r5 ");
	asm("movccs r8, r8, lsr #1 ");			// if borrow, check for carry from shift
	asm("orrcc r3, r3, #0x100 ");			// if borrow, round down and set round-down flag
	asm("bcc TRealXDivide6 ");
	asm("orrs r9, r6, r7 ");				// if no borrow, check if exactly half-way
	asm("moveqs r9, r1, lsr #1 ");			// if exactly half-way, round to even
	asm("orrcc r3, r3, #0x100 ");			// if C=0, round result down and set round-down flag
	asm("bcc TRealXDivide6 ");
	asm("orr r3, r3, #0x200 ");				// else set round-up flag
	asm("adds r1, r1, #1 ");				// and round mantissa up
	asm("adcs r2, r2, #0 ");
	asm("movcs r2, #0x80000000 ");			// if carry, mantissa = 80000000 00000000
	asm("addcs r0, r0, #1 ");				// and increment exponent

	// check for overflow or underflow and assemble final result
	asm("TRealXDivide6: ");
	asm("add r4, r0, #1 ");					// need to add 1 to get usable threshold
	asm("cmp r4, #0x10000 ");				// check if exponent >= 0xFFFF
	asm("bge TRealXMultiply6 ");			// if so, overflow
	asm("cmp r0, #0 ");						// check for underflow
	asm("orrgt r3, r3, r0, lsl #16 ");		// if no underflow, result exponent into r3, ...
	asm("movgt r12, #0 ");					// ... return KErrNone ...
	asm("bicgt pc, lr, #3 ");

	// underflow
	asm("and r3, r3, #1 ");					// set exponent=0, keep sign
	asm("mvn r12, #9 ");					// return KErrUnderflow
	asm("bic pc, lr, #3 ");

	// come here if divisor is zero, dividend finite
	asm("TRealXDivide3: ");
	asm("cmp r3, #0x10000 ");				// check if dividend also zero
	asm("bcc TRealXRealIndefinite ");		// if so, return 'real indefinite'
	asm("orr r3, r3, #0xFF000000 ");		// else return infinity with xor sign
	asm("orr r3, r3, #0x00FF0000 ");
	asm("mov r2, #0x80000000 ");
	asm("mov r1, #0 ");
	asm("mvn r12, #40 ");					// return KErrDivideByZero
	asm("bic pc, lr, #3 ");

	// Dividend is NaN or infinity
	asm("TRealXDivide1: ");
	asm("cmp r2, #0x80000000 ");			// check for infinity
	asm("cmpeq r1, #0 ");
	asm("bne TRealXBinOpNan ");				// branch if NaN
	asm("cmn r6, #0x10000 ");				// check 2nd operand for NaN/infinity
	asm("mvncc r12, #8 ");					// if not, return KErrOverflow
	asm("biccc pc, lr, #3 ");

	// Dividend=infinity, divisor=NaN or infinity
	asm("cmp r5, #0x80000000 ");			// check 2nd operand for infinity
	asm("cmpeq r4, #0 ");
	asm("bne TRealXBinOpNan ");				// branch if NaN
	asm("b TRealXRealIndefinite ");			// else return 'real indefinite'

	// Divisor is NaN or infinity, dividend finite
	asm("TRealXDivide2: ");
	asm("cmp r5, #0x80000000 ");			// check for infinity
	asm("cmpeq r4, #0 ");
	asm("bne TRealXBinOpNan ");				// branch if NaN
	asm("and r3, r3, #1 ");					// else return zero with xor sign
	asm("bic pc, lr, #3 ");
	}




__NAKED__ EXPORT_C TInt TRealX::ModEq(const TRealX& /*aVal*/)
/**
Modulo-divides this extended precision number by an extended precision value.

@param aVal The extended precision value to be used as the divisor. 

@return KErrNone, if the operation is successful;
        KErrTotalLossOfPrecision, if precision is lost;
        KErrUnderflow, if the operation results in underflow.
*/
	{
	asm("stmfd sp!, {r0,r4-r7,lr} ");
	asm("ldmia r1, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXModulo ");
	asm("ldmfd sp!, {r0,r4-r7,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("mov r0, r12 ");
	__JUMP(,lr);

	// TRealX remainder r1,r2,r3 % r4,r5,r6 result in r1,r2,r3
	// Error code returned in r12
	// Registers r0-r7,r12 modified
	// NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE.
	asm("TRealXModulo: ");
	asm("mov r12, #0 ");					// initialise return value to KErrNone
	asm("cmn r3, #0x10000 ");				// check if dividend is NaN or infinity
	asm("bcs TRealXModulo1 ");				// branch if it is
	asm("cmn r6, #0x10000 ");				// check if divisor is NaN or infinity
	asm("bcs TRealXModulo2 ");				// branch if it is
	asm("cmp r6, #0x10000 ");				// check if divisor zero
	asm("bcc TRealXRealIndefinite ");		// if it is, return 'real indefinite'
	asm("mov r0, r3, lsr #16 ");			// r0=dividend exponent
	asm("subs r0, r0, r6, lsr #16 ");		// r0=dividend exponent-divisor exponent
	__JUMP(lt,lr);
	asm("cmp r0, #64 ");					// check if difference >= 64 bits
	asm("bcs TRealXModuloLp ");				// if so, underflow
	asm("b TRealXModulo4 ");				// skip left shift on first iteration

	asm("TRealXModulo3: ");
	asm("adds r1, r1, r1 ");				// shift dividend mantissa left one bit
	asm("adcs r2, r2, r2 ");
	asm("bcs TRealXModulo5 ");				// if one shifted out, override comparison
	asm("TRealXModulo4: ");
	asm("cmp r2, r5 ");						// compare dividend to divisor
	asm("cmpeq r1, r4 ");
	asm("bcc TRealXModulo6 ");				// if dividend<divisor, skip
	asm("TRealXModulo5: ");
	asm("subs r1, r1, r4 ");				// if dividend>=divisor, dividend-=divisor
	asm("sbcs r2, r2, r5 ");
	asm("TRealXModulo6: ");
	asm("subs r0, r0, #1 ");				// decrement loop count
	asm("bpl TRealXModulo3 ");				// if more bits to do, loop

	asm("orrs r0, r1, r2 ");				// test for exact zero result
	asm("andeq r3, r3, #1 ");				// if so, return zero with same sign as dividend
	__JUMP(eq,lr);
	asm("and r7, r3, #1 ");					// dividend sign bit into r7
	asm("mov r3, r6, lsr #16 ");			// r3 lower 16 bits=result exponent=divisor exponent
	asm("cmp r2, #0 ");						// test if upper 32 bits zero
	asm("moveq r2, r1 ");					// if so, shift left by 32
	asm("moveq r1, #0 ");
	asm("subeqs r3, r3, #32 ");				// and subtract 32 from exponent
	asm("bls TRealXModuloUnderflow ");		// if borrow from exponent or exponent 0, underflow
	asm("mov r0, #32 ");					// r0 will hold 32-number of shifts to normalise
	asm("cmp r2, #0x00010000 ");			// normalise
	asm("movcc r2, r2, lsl #16 ");
	asm("subcc r0, r0, #16 ");
	asm("cmp r2, #0x01000000 ");
	asm("movcc r2, r2, lsl #8 ");
	asm("subcc r0, r0, #8 ");
	asm("cmp r2, #0x10000000 ");
	asm("movcc r2, r2, lsl #4 ");
	asm("subcc r0, r0, #4 ");
	asm("cmp r2, #0x40000000 ");
	asm("movcc r2, r2, lsl #2 ");
	asm("subcc r0, r0, #2 ");
	asm("cmp r2, #0x80000000 ");
	asm("movcc r2, r2, lsl #1 ");			// top bit of r2 is now set
	asm("subcc r0, r0, #1 ");
	asm("orr r2, r2, r1, lsr r0 ");			// top bits of r1 into bottom bits of r2
	asm("rsb r0, r0, #32 ");				// r0=number of shifts to normalise
	asm("mov r1, r1, lsl r0 ");				// shift r1 left - mantissa now normalised
	asm("subs r3, r3, r0 ");				// subtract r0 from exponent
	asm("bls TRealXModuloUnderflow ");		// if borrow from exponent or exponent 0, underflow
	asm("orr r3, r7, r3, lsl #16 ");		// else r3=result exponent and sign
	__JUMP(,lr);

	// dividend=NaN or infinity
	asm("TRealXModulo1: ");
	asm("cmp r2, #0x80000000 ");			// check for infinity
	asm("cmpeq r1, #0 ");
	asm("bne TRealXBinOpNan ");				// branch if NaN
	asm("cmn r6, #0x10000 ");				// check 2nd operand for NaN/infinity
	asm("bcc TRealXRealIndefinite ");		// infinity%finite - return 'real indefinite'
	asm("cmp r5, #0x80000000 ");			// check if divisor=infinity
	asm("cmpeq r4, #0 ");
	asm("bne TRealXBinOpNan ");				// branch if NaN
	asm("b TRealXRealIndefinite ");			// else infinity%infinity - return 'real indefinite'

	// divisor=NaN or infinity, dividend finite
	asm("TRealXModulo2: ");
	asm("cmp r5, #0x80000000 ");			// check for infinity
	asm("cmpeq r4, #0 ");
	asm("bne TRealXBinOpNan ");				// branch if NaN
	__JUMP(,lr);

	asm("TRealXModuloLp: ");
	asm("mvn r12, #%a0" : : "i" ((TInt)~KErrTotalLossOfPrecision));
	asm("mov r1, #0 ");
	asm("mov r2, #0 ");
	asm("and r3, r3, #1 ");
	__JUMP(,lr);

	asm("TRealXModuloUnderflow: ");
	asm("mvn r12, #%a0" : : "i" ((TInt)~KErrUnderflow));
	asm("mov r1, #0 ");
	asm("mov r2, #0 ");
	asm("and r3, r3, #1 ");
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TInt TRealX::Add(TRealX& /*aResult*/,const TRealX& /*aVal*/) const
/**
Adds an extended precision value to this extended precision number.

@param aResult On return, a reference to an extended precision object
               containing the result of the operation.
@param aVal    The extended precision value to be added. 

@return KErrNone, if the operation is successful;
        KErrOverflow, if the operation results in overflow;
        KErrUnderflow, if the operation results in underflow. 
*/
	{
	// r0=this, r1=&aResult, r2=&aVal
	asm("stmfd sp!, {r1,r4-r8,lr} ");
	asm("ldmia r2, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXAdd ");
	asm("ldmfd sp!, {lr} ");				// lr=&aResult
	asm("stmia lr, {r1,r2,r3} ");
	asm("mov r0, r12 ");					// return value into r0
	__POPRET("r4-r8,");
	}




__NAKED__ EXPORT_C TInt TRealX::Sub(TRealX& /*aResult*/,const TRealX& /*aVal*/) const
/**
Subtracts an extended precision value from this extended precision number.

@param aResult On return, a reference to an extended precision object
               containing the result of the operation.
@param aVal    The extended precision value to be subtracted. 

@return KErrNone, if the operation is successful;
        KErrOverflow, if the operation results in overflow;
        KErrUnderflow, if the operation results in underflow. 
*/
	{
	// r0=this, r1=&aResult, r2=&aVal
	asm("stmfd sp!, {r1,r4-r8,lr} ");
	asm("ldmia r2, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXSubtract ");
	asm("ldmfd sp!, {lr} ");				// lr=&aResult
	asm("stmia lr, {r1,r2,r3} ");
	asm("mov r0, r12 ");					// return value into r0
	__POPRET("r4-r8,");
	}




__NAKED__ EXPORT_C TInt TRealX::Mult(TRealX& /*aResult*/,const TRealX& /*aVal*/) const
/**
Multiplies this extended precision number by an extended precision value.

@param aResult On return, a reference to an extended precision object
               containing the result of the operation.
@param aVal    The extended precision value to be used as the multiplier. 

@return KErrNone, if the operation is successful;
        KErrOverflow, if the operation results in overflow;
        KErrUnderflow, if the operation results in underflow. 
*/
	{
	// r0=this, r1=&aResult, r2=&aVal
	asm("stmfd sp!, {r1,r4-r7,lr} ");
	asm("ldmia r2, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXMultiply ");
	asm("ldmfd sp!, {lr} ");				// lr=&aResult
	asm("stmia lr, {r1,r2,r3} ");
	asm("mov r0, r12 ");					// return value into r0
	__POPRET("r4-r7,");
	}




__NAKED__ EXPORT_C TInt TRealX::Div(TRealX& /*aResult*/,const TRealX& /*aVal*/) const
/**
Divides this extended precision number by an extended precision value.

@param aResult On return, a reference to an extended precision object
               containing the result of the operation.
@param aVal    The extended precision value to be used as the divisor.

@return KErrNone, if the operation is successful;
        KErrOverflow, if the operation results in overflow;
        KErrUnderflow, if the operation results in underflow;
        KErrDivideByZero, if the divisor is zero.
*/
	{
	// r0=this, r1=&aResult, r2=&aVal
	asm("stmfd sp!, {r1,r4-r9,lr} ");
	asm("ldmia r2, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXDivide ");
	asm("ldmfd sp!, {lr} ");				// lr=&aResult
	asm("stmia lr, {r1,r2,r3} ");
	asm("mov r0, r12 ");					// return value into r0
	__POPRET("r4-r9,");
	}




__NAKED__ EXPORT_C TInt TRealX::Mod(TRealX& /*aResult*/,const TRealX& /*aVal*/) const
/**
Modulo-divides this extended precision number by an extended precision value.

@param aResult On return, a reference to an extended precision object
               containing the result of the operation.

@param aVal    The extended precision value to be used as the divisor. 

@return KErrNone, if the operation is successful;
        KErrTotalLossOfPrecision, if precision is lost;
        KErrUnderflow, if the operation results in underflow.
*/
	{
	// r0=this, r1=&aResult, r2=&aVal
	asm("stmfd sp!, {r1,r4-r7,lr} ");
	asm("ldmia r2, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXModulo ");
	asm("ldmfd sp!, {lr} ");				// lr=&aResult
	asm("stmia lr, {r1,r2,r3} ");
	asm("mov r0, r12 ");					// return value into r0
	__POPRET("r4-r7,");
	}

extern void PanicOverUnderflowDividebyZero(const TInt aErr);




__NAKED__ EXPORT_C const TRealX& TRealX::operator+=(const TRealX& /*aVal*/)
/**
Adds an extended precision value to this extended precision number.

@param aVal The extended precision value to be added.

@return A reference to this object.

@panic MATHX KErrOverflow if the operation results in overflow.
@panic MATHX KErrUnderflow if  the operation results in underflow.
*/
	{
	asm("stmfd sp!, {r0,r4-r8,lr} ");
	asm("ldmia r1, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXAdd ");
	asm("ldmfd sp!, {r0,r4-r8,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("cmp r12, #0 ");					// check the error code
	__JUMP(eq,lr);
	asm("mov r0, r12 ");
	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
	}




__NAKED__ EXPORT_C const TRealX& TRealX::operator-=(const TRealX& /*aVal*/)
/**
Subtracts an extended precision value from this extended precision number. 

@param aVal The extended precision value to be subtracted.

@return A reference to this object.

@panic MATHX KErrOverflow if the operation results in overflow.
@panic MATHX KErrUnderflow if  the operation results in underflow.
*/
	{
	asm("stmfd sp!, {r0,r4-r8,lr} ");
	asm("ldmia r1, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXSubtract ");
	asm("ldmfd sp!, {r0,r4-r8,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("cmp r12, #0 ");					// check the error code
	__JUMP(eq,lr);
	asm("mov r0, r12 ");
	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
	}




__NAKED__ EXPORT_C const TRealX& TRealX::operator*=(const TRealX& /*aVal*/)
/**
Multiplies this extended precision number by an extended precision value.

@param aVal The extended precision value to be subtracted.

@return A reference to this object.

@panic MATHX KErrOverflow if the operation results in overflow.
@panic MATHX KErrUnderflow if  the operation results in underflow.
*/
	{
	asm("stmfd sp!, {r0,r4-r7,lr} ");
	asm("ldmia r1, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXMultiply ");
	asm("ldmfd sp!, {r0,r4-r7,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("cmp r12, #0 ");					// check the error code
	__JUMP(eq,lr);
	asm("mov r0, r12 ");
	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
	}




__NAKED__ EXPORT_C const TRealX& TRealX::operator/=(const TRealX& /*aVal*/)
/**
Divides this extended precision number by an extended precision value.

@param aVal The extended precision value to be used as the divisor. 

@return A reference to this object.

@panic MATHX KErrOverflow if the operation results in overflow.
@panic MATHX KErrUnderflow if  the operation results in underflow.
@panic MATHX KErrDivideByZero if the divisor is zero.
*/
	{
	asm("stmfd sp!, {r0,r4-r9,lr} ");
	asm("ldmia r1, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXDivide ");
	asm("ldmfd sp!, {r0,r4-r9,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("cmp r12, #0 ");					// check the error code
	__JUMP(eq,lr);
	asm("mov r0, r12 ");
	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
	}




__NAKED__ EXPORT_C const TRealX& TRealX::operator%=(const TRealX& /*aVal*/)
/**
Modulo-divides this extended precision number by an extended precision value.

@param aVal The extended precision value to be used as the divisor. 

@return A reference to this object.

@panic MATHX KErrTotalLossOfPrecision panic if precision is lost.
@panic MATHX KErrUnderflow if  the operation results in underflow.
*/
	{
	asm("stmfd sp!, {r0,r4-r7,lr} ");
	asm("ldmia r1, {r4,r5,r6} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("bl TRealXModulo ");
	asm("ldmfd sp!, {r0,r4-r7,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("cmp r12, #0 ");					// check the error code
	asm("cmpne r12, #%a0" : : "i" ((TInt)KErrTotalLossOfPrecision));
	__JUMP(eq,lr);
	asm("mov r0, r12 ");
	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
	}




__NAKED__ EXPORT_C TRealX& TRealX::operator++()
/**
Increments this extended precision number by one,
and then returns a reference to it.

This is also referred to as a prefix operator. 

@return A reference to this object.

@panic MATHX KErrOverflow if the operation results in overflow.
@panic MATHX KErrUnderflow if  the operation results in underflow.
*/
	{
	// pre-increment
	asm("stmfd sp!, {r0,r4-r8,lr} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("add r4, pc, #__TRealXOne-.-8 ");
	asm("ldmia r4, {r4,r5,r6} ");			// r4,r5,r6=1.0
	asm("bl TRealXAdd ");
	asm("ldmfd sp!, {r0,r4-r8,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("cmp r12, #0 ");					// check the error code
	__JUMP(eq,lr);
	asm("mov r0, r12 ");
	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic

	asm("__TRealXOne: ");
	asm(".word 0x00000000 ");
	asm(".word 0x80000000 ");
	asm(".word 0x7FFF0000 ");
	}




__NAKED__ EXPORT_C TRealX TRealX::operator++(TInt)
/**
Returns this extended precision number before incrementing it by one.

This is also referred to as a postfix operator. 

@return A reference to this object.

@panic MATHX KErrOverflow if the operation results in overflow.
@panic MATHX KErrUnderflow if  the operation results in underflow.
*/
	{
	// post-increment
	// r0=address of return value, r1=this
	asm("stmfd sp!, {r0,r1,r4-r8,lr} ");
	asm("ldmia r1, {r1,r2,r3} ");
	asm("stmia r0, {r1,r2,r3} ");			// store old value
	asm("add r4, pc, #__TRealXOne-.-8 ");
	asm("ldmia r4, {r4,r5,r6} ");			// r4,r5,r6=1.0
	asm("bl TRealXAdd ");
	asm("ldmfd sp!, {r0,lr} ");				// restore r0, lr=this
	asm("stmia lr, {r1,r2,r3} ");			// store incremented value
	asm("ldmfd sp!, {r4-r8,lr} ");
	asm("cmp r12, #0 ");					// check the error code
	__JUMP(eq,lr);
	asm("mov r0, r12 ");
	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
	}




__NAKED__ EXPORT_C TRealX& TRealX::operator--()
/**
Decrements this extended precision number by one,
and then returns a reference to it.

This is also referred to as a prefix operator. 

@return A reference to this object.

@panic MATHX KErrOverflow if the operation results in overflow.
@panic MATHX KErrUnderflow if  the operation results in underflow.
*/
	{
	// pre-decrement
	asm("stmfd sp!, {r0,r4-r8,lr} ");
	asm("ldmia r0, {r1,r2,r3} ");
	asm("add r4, pc, #__TRealXOne-.-8 ");
	asm("ldmia r4, {r4,r5,r6} ");			// r4,r5,r6=1.0
	asm("bl TRealXSubtract ");
	asm("ldmfd sp!, {r0,r4-r8,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("cmp r12, #0 ");					// check the error code
	__JUMP(eq,lr);
	asm("mov r0, r12 ");
	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
	}




__NAKED__ EXPORT_C TRealX TRealX::operator--(TInt)
/**
Returns this extended precision number before decrementing it by one.

This is also referred to as a postfix operator. 

@return A reference to this object.

@panic MATHX KErrOverflow if the operation results in overflow.
@panic MATHX KErrUnderflow if  the operation results in underflow.
*/
	{
	// post-decrement
	// r0=address of return value, r1=this
	asm("stmfd sp!, {r0,r1,r4-r8,lr} ");
	asm("ldmia r1, {r1,r2,r3} ");
	asm("stmia r0, {r1,r2,r3} ");			// store old value
	asm("add r4, pc, #__TRealXOne-.-8 ");
	asm("ldmia r4, {r4,r5,r6} ");			// r4,r5,r6=1.0
	asm("bl TRealXSubtract ");
	asm("ldmfd sp!, {r0,lr} ");				// restore r0, lr=this
	asm("stmia lr, {r1,r2,r3} ");			// store decremented value
	asm("ldmfd sp!, {r4-r8,lr} ");
	asm("cmp r12, #0 ");					// check the error code
	__JUMP(eq,lr);
	asm("mov r0, r12 ");
	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
	}




__NAKED__ EXPORT_C TRealX TRealX::operator+(const TRealX& /*aVal*/) const
/**
Adds an extended precision value to this extended precision number.

@param aVal The extended precision value to be added. 

@return An extended precision object containing the result.

@panic MATHX KErrOverflow if the operation results in overflow.
@panic MATHX KErrUnderflow if  the operation results in underflow.
*/
	{
	// r0=address of return value, r1=this, r2=&aVal
	asm("stmfd sp!, {r0,r4-r8,lr} ");
	asm("ldmia r2, {r4,r5,r6} ");
	asm("ldmia r1, {r1,r2,r3} ");
	asm("bl TRealXAdd ");
	asm("ldmfd sp!, {r0,r4-r8,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("cmp r12, #0 ");					// check the error code
	__JUMP(eq,lr);
	asm("mov r0, r12 ");
	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
	}




__NAKED__ EXPORT_C TRealX TRealX::operator-(const TRealX& /*aVal*/) const
/**
Subtracts an extended precision value from this extended precision number. 

@param aVal The extended precision value to be subtracted. 

@return An extended precision object containing the result. 

@panic MATHX KErrOverflow if the operation results in overflow.
@panic MATHX KErrUnderflow if  the operation results in underflow.
*/
	{
	// r0=address of return value, r1=this, r2=&aVal
	asm("stmfd sp!, {r0,r4-r8,lr} ");
	asm("ldmia r2, {r4,r5,r6} ");
	asm("ldmia r1, {r1,r2,r3} ");
	asm("bl TRealXSubtract ");
	asm("ldmfd sp!, {r0,r4-r8,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("cmp r12, #0 ");					// check the error code
	__JUMP(eq,lr);
	asm("mov r0, r12 ");
	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
	}




__NAKED__ EXPORT_C TRealX TRealX::operator*(const TRealX& /*aVal*/) const
/**
Multiplies this extended precision number by an extended precision value.

@param aVal The extended precision value to be used as the multiplier. 

@return An extended precision object containing the result. 

@panic MATHX KErrOverflow if the operation results in overflow.
@panic MATHX KErrUnderflow if  the operation results in underflow.
*/
	{
	// r0=address of return value, r1=this, r2=&aVal
	asm("stmfd sp!, {r0,r4-r7,lr} ");
	asm("ldmia r2, {r4,r5,r6} ");
	asm("ldmia r1, {r1,r2,r3} ");
	asm("bl TRealXMultiply ");
	asm("ldmfd sp!, {r0,r4-r7,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("cmp r12, #0 ");					// check the error code
	__JUMP(eq,lr);
	asm("mov r0, r12 ");
	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
	}




__NAKED__ EXPORT_C TRealX TRealX::operator/(const TRealX& /*aVal*/) const
/**
Divides this extended precision number by an extended precision value.

@param aVal The extended precision value to be used as the divisor. 

@return An extended precision object containing the result. 

@panic MATHX KErrOverflow if the operation results in overflow.
@panic MATHX KErrUnderflow if  the operation results in underflow.
@panic MATHX KErrDivideByZero if the divisor is zero.
*/
	{
	// r0=address of return value, r1=this, r2=&aVal
	asm("stmfd sp!, {r0,r4-r9,lr} ");
	asm("ldmia r2, {r4,r5,r6} ");
	asm("ldmia r1, {r1,r2,r3} ");
	asm("bl TRealXDivide ");
	asm("ldmfd sp!, {r0,r4-r9,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("cmp r12, #0 ");					// check the error code
	__JUMP(eq,lr);
	asm("mov r0, r12 ");
	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
	}




__NAKED__ EXPORT_C TRealX TRealX::operator%(const TRealX& /*aVal*/) const
/**
Modulo-divides this extended precision number by an extended precision value.

@param aVal The extended precision value to be used as the divisor. 

@return An extended precision object containing the result. 

@panic MATHX KErrTotalLossOfPrecision if precision is lost.
@panic MATHX KErrUnderflow if the operation results in underflow.
*/
	{
	// r0=address of return value, r1=this, r2=&aVal
	asm("stmfd sp!, {r0,r4-r7,lr} ");
	asm("ldmia r2, {r4,r5,r6} ");
	asm("ldmia r1, {r1,r2,r3} ");
	asm("bl TRealXModulo ");
	asm("ldmfd sp!, {r0,r4-r7,lr} ");
	asm("stmia r0, {r1,r2,r3} ");
	asm("cmp r12, #0 ");					// check the error code
	asm("cmpne r12, #%a0" : : "i" ((TInt)KErrTotalLossOfPrecision));
	__JUMP(eq,lr);
	asm("mov r0, r12 ");
	asm("b  " CSM_Z30PanicOverUnderflowDividebyZeroi);	// else panic
	}




#ifdef __REALS_MACHINE_CODED__
__NAKED__ EXPORT_C TInt Math::Sqrt( TReal &/*aDest*/, const TReal &/*aSrc*/ )
/**
Calculates the square root of a number.

@param aDest A reference containing the result. 
@param aSrc  The number whose square-root is required.

@return KErrNone if successful, otherwise another of
        the system-wide error codes. 
*/
	{
	// r0=address of aDest, r1=address of aSrc


#ifdef __USE_VFP_MATH
	VFP_FLDD(CC_AL,0,1,0);
	VFP_FSQRTD(,0,0);
	VFP_FMRRD(CC_AL,3,2,0);
	asm("bic r1, r2, #0x80000000 ");	// remove sign bit
	asm("cmn r1, #0x00100000 ");		// check if exp=7FF
	asm("movpl r1, #0 ");				// if not return KErrNone
	asm("bpl donesqrt ");
	asm("movs r1, r1, lsl #12 ");		// if exp=7FF, check mantissa
	asm("cmpeq r3, #0 ");
	asm("moveq r1, #-9 ");				// if exp=7FF, mant=0, return KErrOverflow
	asm("mvnne r2, #0x80000000 ");		// else set NaN
	asm("mvnne r3, #0 ");
	asm("movne r1, #-6 ");				// and return KErrArgument
	asm("donesqrt: ");
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("stmia r0, {r2,r3} ");			// store the result
#else
	asm("str r2, [r0, #4] ");
	asm("str r3, [r0, #0] ");
#endif
	asm("mov r0, r1 ");
	__JUMP(,lr);
#else // __USE_VFP_MATH
	asm("stmfd sp!, {r4-r10,lr} ");
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("ldmia r1, {r3,r4} ");			// low mant into r4, sign:exp:high mant into r3
#else
	asm("ldr r3, [r1, #4] ");
	asm("ldr r4, [r1, #0] ");
#endif
	asm("bic r5, r3, #0xFF000000 ");
	asm("bic r5, r5, #0x00F00000 ");	// high word of mantissa into r5
	asm("mov r2, r3, lsr #20 ");
	asm("bics r2, r2, #0x800 ");		// exponent now in r2
	asm("beq fastsqrt1 ");				// branch if exponent zero (zero or denormal)
	asm("mov r6, #0xFF ");
	asm("orr r6, r6, #0x700 ");
	asm("cmp r2, r6 ");					// check for infinity or NaN
	asm("beq fastsqrt2 ");				// branch if infinity or NaN
	asm("movs r3, r3 ");				// test sign
	asm("bmi fastsqrtn ");				// branch if negative
	asm("sub r2, r2, #0xFF ");			// unbias the exponent
	asm("sub r2, r2, #0x300 ");			//
	asm("fastsqrtd1: ");
	asm("mov r1, #0x40000000 ");		// value for comparison
	asm("mov r3, #27 ");				// loop counter (number of bits/2)
	asm("movs r2, r2, asr #1 ");		// divide exponent by 2, LSB into CF
	asm("movcs r7, r5, lsl #11 ");		// mantissa into r6,r7 with MSB in MSB of r7
	asm("orrcs r7, r7, r4, lsr #21 ");
	asm("movcs r6, r4, lsl #11 ");
	asm("movcs r4, #0 ");				// r4, r5 will hold result mantissa
	asm("orrcs r7, r7, #0x80000000 ");	// if exponent odd, restore MSB of mantissa
	asm("movcc r7, r5, lsl #12 ");		// mantissa into r6,r7 with MSB in MSB of r7
	asm("orrcc r7, r7, r4, lsr #20 ");	// if exponent even, shift mantissa left an extra
	asm("movcc r6, r4, lsl #12 ");		// place, lose top bit, and
	asm("movcc r4, #1 ");				// set MSB of result, and
	asm("mov r5, #0 ");					// r4, r5 will hold result mantissa
	asm("mov r8, #0 ");					// r8, r9 will be comparison accumulator
	asm("mov r9, #0 ");
	asm("bcc fastsqrt4 ");				// if exponent even, calculate one less bit
										// as result MSB already known

	// Main mantissa square-root loop
	asm("fastsqrt3: ");					// START OF MAIN LOOP
	asm("subs r10, r7, r1 ");			// subtract result:01 from acc:mant
	asm("sbcs r12, r8, r4 ");			// result into r14:r12:r10
	asm("sbcs r14, r9, r5 ");
	asm("movcs r7, r10 ");				// if no borrow replace accumulator with result
	asm("movcs r8, r12 ");
	asm("movcs r9, r14 ");
	asm("adcs r4, r4, r4 ");			// shift result left one, putting in next bit
	asm("adcs r5, r5, r5 ");
	asm("mov r9, r9, lsl #2 ");			// shift acc:mant left by 2 bits
	asm("orr r9, r9, r8, lsr #30 ");
	asm("mov r8, r8, lsl #2 ");
	asm("orr r8, r8, r7, lsr #30 ");
	asm("mov r7, r7, lsl #2 ");
	asm("orr r7, r7, r6, lsr #30 ");
	asm("mov r6, r6, lsl #2 ");
	asm("fastsqrt4: ");					// Come in here if we need to do one less iteration
	asm("subs r10, r7, r1 ");			// subtract result:01 from acc:mant
	asm("sbcs r12, r8, r4 ");			// result into r14:r12:r10
	asm("sbcs r14, r9, r5 ");
	asm("movcs r7, r10 ");				// if no borrow replace accumulator with result
	asm("movcs r8, r12 ");
	asm("movcs r9, r14 ");
	asm("adcs r4, r4, r4 ");			// shift result left one, putting in next bit
	asm("adcs r5, r5, r5 ");
	asm("mov r9, r9, lsl #2 ");			// shift acc:mant left by 2 bits
	asm("orr r9, r9, r8, lsr #30 ");
	asm("mov r8, r8, lsl #2 ");
	asm("orr r8, r8, r7, lsr #30 ");
	asm("mov r7, r7, lsl #2 ");
	asm("orr r7, r7, r6, lsr #30 ");
	asm("mov r6, r6, lsl #2 ");
	asm("subs r3, r3, #1 ");			// decrement loop counter
	asm("bne fastsqrt3 ");				// do necessary number of iterations

	asm("movs r4, r4, lsr #1 ");		// shift result mantissa right 1 place
	asm("orr r4, r4, r5, lsl #31 ");	// LSB (=rounding bit) into carry
	asm("mov r5, r5, lsr #1 ");
	asm("adcs r4, r4, #0 ");			// round the mantissa to 53 bits
	asm("adcs r5, r5, #0 ");
	asm("cmp r5, #0x00200000 ");		// check for mantissa overflow
	asm("addeq r2, r2, #1 ");			// if so, increment exponent - can never overflow
	asm("bic r5, r5, #0x00300000 ");	// remove top bit of mantissa - it is implicit
	asm("add r2, r2, #0xFF ");			// re-bias the exponent
	asm("add r3, r2, #0x300 ");			// and move into r3
	asm("orr r3, r5, r3, lsl #20 ");	// r3 now contains exponent + top of mantissa
	asm("fastsqrt_ok: ");
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("stmia r0, {r3,r4} ");			// store the result
#else
	asm("str r3, [r0, #4] ");
	asm("str r4, [r0, #0] ");
#endif
	asm("mov r0, #0 ");					// error code KErrNone
	__POPRET("r4-r10,");

	asm("fastsqrt1: ");
	asm("orrs r6, r5, r4 ");			// exponent zero - test mantissa
	asm("beq fastsqrt_ok ");			// if zero, return 0

	asm("movs r3, r3 ");				// denormal - test sign
	asm("bmi fastsqrtn ");				// branch out if negative
	asm("sub r2, r2, #0xFE ");			// unbias the exponent
	asm("sub r2, r2, #0x300 ");			//
	asm("fastsqrtd: ");
	asm("adds r4, r4, r4 ");			// shift mantissa left
	asm("adcs r5, r5, r5 ");
	asm("sub r2, r2, #1 ");				// and decrement exponent
	asm("tst r5, #0x00100000 ");		// test if normalised
	asm("beq fastsqrtd ");				// loop until normalised
	asm("b fastsqrtd1 ");				// now treat as a normalised number
	asm("fastsqrt2: ");					// get here if infinity or NaN
	asm("orrs r6, r5, r4 ");			// if mantissa zero, infinity
	asm("bne fastsqrtnan ");			// branch if not - must be NaN
	asm("movs r3, r3 ");				// test sign of infinity
	asm("bmi fastsqrtn ");				// branch if -ve
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("stmia r0, {r3,r4} ");			// store the result
#else
	asm("str r3, [r0, #4] ");
	asm("str r4, [r0, #0] ");
#endif
	asm("mov r0, #-9 ");				// return KErrOverflow
	asm("b fastsqrt_end ");

	asm("fastsqrtn: ");					// get here if negative or QNaN operand
	asm("mov r3, #0xFF000000 ");		// generate "real indefinite" QNaN
	asm("orr r3, r3, #0x00F80000 ");	// sign=1, exp=7FF, mantissa = 1000...0
	asm("mov r4, #0 ");
	asm("fastsqrtxa: ");
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("stmia r0, {r3,r4} ");			// store the result
#else
	asm("str r3, [r0, #4] ");
	asm("str r4, [r0, #0] ");
#endif
	asm("mov r0, #-6 ");				// return KErrArgument
	asm("fastsqrt_end: ");
	__POPRET("r4-r10,");

	asm("fastsqrtnan: ");				// operand is a NaN
	asm("tst r5, #0x00080000 ");		// test MSB of mantissa
	asm("bne fastsqrtn ");				// if set it is a QNaN - so return "real indefinite"
	asm("bic r3, r3, #0x00080000 ");	// else convert SNaN to QNaN
	asm("b fastsqrtxa ");				// and return KErrArgument
#endif // __USE_VFP_MATH
	}




__NAKED__ EXPORT_C TReal Math::Poly(TReal /*aX*/,const SPoly* /*aPoly*/) __SOFTFP
/**
Evaluates the polynomial:
{a[n]X^n + a[n-1]X^(n-1) + ... + a[2]X^2 + a[1]X^1 + a[0]}.


@param aX    The value of the x-variable 
@param aPoly A pointer to the structure containing the set of coefficients
             in the order: a[0], a[1], ..., a[n-1], a[n].

@return The result of the evaluation.
*/
//
// Evaluate a power series in x for a P_POLY coefficient table.
// Changed to use TRealX throughout the calculation
//
	{
	// On entry r0,r1=aX, r2=aPoly
	asm("stmfd sp!, {r4-r11,lr} ");
	asm("mov r11, r2 ");
	asm("ldr r10, [r11], #4 ");			// r10=number of coefficients, r11=first coeff addr
	asm("add r11, r11, r10, lsl #3 ");	// r11=address of last coefficient+8
	asm("mov r2, r1 ");					// aX into r1,r2
	asm("mov r1, r0 ");
	asm("bl ConvertTReal64ToTRealX ");	// convert to TRealX in r1,r2,r3
	asm("mov r4, r1 ");					// move into r4,r5,r6
	asm("mov r5, r2 ");
	asm("mov r6, r3 ");
	asm("ldmdb r11!, {r1,r2} ");		// last coefficient into r1,r2
	asm("bl ConvertTReal64ToTRealX ");	// convert to TRealX in r1,r2,r3
	asm("subs r10, r10, #1 ");
	asm("beq polynomial0 ");			// if no more coefficients, exit

	asm("polynomial1: ");
	asm("stmfd sp!, {r4,r5,r6} ");		// save value of aX
	asm("bl TRealXMultiply ");			// r *= aX
	asm("mov r4, r1 ");					// move result into r4,r5,r6
	asm("mov r5, r2 ");
	asm("mov r6, r3 ");
	asm("ldmdb r11!, {r1,r2} ");		// next coefficient into r1,r2
	asm("bl ConvertTReal64ToTRealX ");	// convert to TRealX in r1,r2,r3
	asm("bl TRealXAdd ");				// r += *--pR
	asm("ldmfd sp!, {r4,r5,r6} ");		// aX back into r4,r5,r6
	asm("subs r10, r10, #1 ");			// iterate until all coefficients processed
	asm("bne polynomial1 ");

	asm("polynomial0: ");				// result now in r1,r2,r3
	asm("bl ConvertTRealXToTReal64 ");	// convert back to TReal64
	__POPRET("r4-r11,");
	}




__NAKED__ EXPORT_C void Math::PolyX(TRealX& /*aY*/,const TRealX& /*aX*/,TInt /*aDeg*/,const TRealX* /*aCoef*/)
/**
Evaluates the polynomial:
{a[n]X^n + a[n-1]X^(n-1) + ... + a[2]X^2 + a[1]X^1 + a[0]}.

@param aY      A reference containing the result. 
@param aX      The value of the x-variable. 
@param aDeg    The degree of the polynomial (the highest power of x
               which is present).
@param aCoef   A pointer to a contiguous set of TRealX values containing
               the coefficients.
               They must be in the order: a[0], a[1], ..., a[n-1], a[n].
*/
//
// Evaluate a polynomial with TRealX argument, coefficients and result
//
	{
	// On entry r0=&aY, r1=&aX, r2=aDeg, r3=aCoef
	asm("stmfd sp!, {r0,r4-r11,lr} ");
	asm("add r11, r3, r2, lsl #3 ");	// r11=address of last coefficient
	asm("add r11, r11, r2, lsl #2 ");
	asm("mov r9, r1 ");					// r9=address of argument
	asm("movs r10, r2 ");				// r10=number of coefficients-1
	asm("ldmia r11, {r1,r2,r3} ");		// last coefficient into r1,r2,r3
	asm("beq polyx0 ");					// if no more coefficients, exit

	asm("polyx1: ");
	asm("ldmia r9, {r4,r5,r6} ");		// aX into r4,r5,r6
	asm("bl TRealXMultiply ");			// result *= aX
	asm("ldmdb r11!, {r4,r5,r6} ");		// next coefficient into r4,r5,r6
	asm("bl TRealXAdd ");				// result += next coeff
	asm("subs r10, r10, #1 ");			// iterate until all coefficients processed
	asm("bne polyx1 ");

	asm("polyx0: ");					// result now in r1,r2,r3
	asm("ldmfd sp!, {r0,r4-r11,lr} ");	// restore registers, including destination address in r0
	asm("stmia r0, {r1,r2,r3} ");		// store result
	__JUMP(,lr);
	}




#ifndef __USE_VFP_MATH
__NAKED__ EXPORT_C TInt Math::Int(TReal& /*aTrg*/, const TReal& /*aSrc*/)
/**
Calculates the integer part of a number.

The integer part is that before a decimal point.
Truncation is toward zero, so that
int(2.4)=2, int(2)=2, int(-1)=-1, int(-1.4)=-1, int(-1.999)=-1.


@param aTrg A reference containing the result. 
@param aSrc The number whose integer part is required. 

@return KErrNone if successful, otherwise another of
        the system-wide error codes. 
*/
//
// Write the integer part of aSrc to the TReal at aTrg
// Negative numbers are rounded towards zero.
//
	{
	// r0=&aTrg, r1=&aSrc, return value in r0
	asm("stmfd sp!, {lr} ");
	asm("mov r12, r0 ");				// r12=&aTrg
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("ldmia r1, {r0,r1} ");			// input value into r0,r1
#else
	asm("ldr r0, [r1, #4] ");
	asm("ldr r1, [r1, #0] ");
#endif
	asm("bl TReal64Int ");
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("stmia r12, {r0,r1} ");			// store result
#else
	asm("str r0, [r12, #4] ");
	asm("str r1, [r12, #0] ");
#endif
	asm("bic r0, r0, #0x80000000 ");	// remove sign bit
	asm("cmn r0, #0x00100000 ");		// check for NaN or infinity
	asm("movpl r0, #0 ");				// if neither, return KErrNone
	asm("bpl math_int_0 ");
	asm("movs r0, r0, lsl #12 ");		// check for infinity
	asm("cmpeq r1, #0 ");
	asm("mvneq r0, #8 ");				// if infinity return KErrOverflow
	asm("mvnne r0, #5 ");				// else return KErrArgument
	asm("math_int_0: ");
	__POPRET("");

	// Take integer part of TReal64 in r0,r1
	// Infinity and NaNs are unaffected
	// r0-r3 modified
	asm("TReal64Int: ");
	asm("mov r2, r0, lsr #20 ");
	asm("bic r2, r2, #0x800 ");			// r2=exponent
	asm("mov r3, #0x300 ");
	asm("orr r3, r3, #0xFF ");			// r3=0x3FF
	asm("subs r2, r2, r3 ");			// r2=exponent-3FF=number of integer bits-1
	asm("ble TReal64Int1 ");			// branch if <=1 integer bits
	asm("cmp r2, #52 ");
	__JUMP(ge,lr);
	asm("cmp r2, #20 ");
	asm("bgt TReal64Int2 ");			// jump if >21 integer bits (r0 will be unaffected)
	asm("rsb r2, r2, #20 ");			// r2=number of bits to clear at bottom end of r0
	asm("mov r0, r0, lsr r2 ");			// clear them
	asm("mov r0, r0, lsl r2 ");
	asm("mov r1, #0 ");					// clear r1
	__JUMP(,lr);
	asm("TReal64Int2: ");
	asm("rsb r2, r2, #52 ");			// r2=number of bits to clear at bottom end of r1
	asm("mov r1, r1, lsr r2 ");			// clear them
	asm("mov r1, r1, lsl r2 ");
	__JUMP(,lr);
	asm("TReal64Int1: ");				// result is either 0 or 1
	asm("mov r1, #0 ");					// lower mantissa bits of result will be zero
	asm("moveq r0, r0, lsr #20 ");		// if result is 1, clear mantissa but leave exponent
	asm("moveq r0, r0, lsl #20 ");
	asm("andlt r0, r0, #0x80000000 ");	// if result is 0, clear mantissa and exponent
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TInt Math::Int(TInt16& /*aTrg*/, const TReal& /*aSrc*/)
/**
Calculates the integer part of a number.

The integer part is that before a decimal point.
Truncation is toward zero, so that:
int(2.4)=2, int(2)=2, int(-1)=-1, int(-1.4)=-1, int(-1.999)=-1.

This function is suitable when the result is known to be small enough
for a 16-bit signed integer.

@param aTrg A reference containing the result. 
@param aSrc The number whose integer part is required. 

@return KErrNone if successful, otherwise another of
        the system-wide error codes. 
*/
//
// If the integer part of aSrc is in the range -32768 to +32767
// inclusive, write the integer part to the TInt16 at aTrg
// Negative numbers are rounded towards zero.
// If an overflow or underflow occurs, aTrg is set to the max/min value
//
	{
	// r0=&aTrg, r1=&aSrc
	asm("stmfd sp!, {lr} ");
	asm("mov r3, r0 ");					// r3=&aTrg
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("ldmia r1, {r0,r1} ");			// input value into r0,r1
#else
	asm("ldr r0, [r1, #4] ");
	asm("ldr r1, [r1, #0] ");
#endif
	asm("bl TReal64GetTInt ");			// do the conversion
	asm("cmp r0, #0x8000 ");			// limit answer to TInt16 range
	asm("movge r0, #0x7F00 ");
	asm("orrge r0, r0, #0xFF ");
	asm("mvnge r12, #8 ");				// set error code if limiting occurred
	asm("cmn r0, #0x8000 ");
	asm("movlt r0, #0x8000 ");
	asm("mvnlt r12, #9 ");				// set error code if limiting occurred
	asm("mov r1, r0, lsr #8 ");			// top byte of answer into r1
	asm("strb r0, [r3] ");				// store result in aTrg
	asm("strb r1, [r3, #1] ");
	asm("mov r0, r12 ");				// return error code in r0
	__POPRET("");
	} 



__NAKED__ EXPORT_C TInt Math::Int(TInt32& /*aTrg*/, const TReal& /*aSrc*/)
/**
Calculates the integer part of a number.

The integer part is that before a decimal point.
Truncation is toward zero, so that
int(2.4)=2, int(2)=2, int(-1)=-1, int(-1.4)=-1, int(-1.999)=-1.

This function is suitable when the result is known to be small enough
for a 32-bit signed integer.

@param aTrg A reference containing the result. 
@param aSrc The number whose integer part is required.

@return KErrNone if successful, otherwise another of
        the system-wide error codes.
*/
//													 
// If the integer part of the float is in the range -2147483648 to +2147483647
// inclusive, write the integer part to the TInt32 at aTrg
// Negative numbers are rounded towards zero.
// If an overflow or underflow occurs, aTrg is set to the max/min value
//
	{
	// r0=&aTrg, r1=&aSrc
	asm("stmfd sp!, {lr} ");
	asm("mov r3, r0 ");					// r3=&aTrg
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("ldmia r1, {r0,r1} ");			// input value into r0,r1
#else
	asm("ldr r0, [r1, #4] ");
	asm("ldr r1, [r1, #0] ");
#endif
	asm("bl TReal64GetTInt ");			// do the conversion
	asm("str r0, [r3] ");				// store result in aTrg
	asm("mov r0, r12 ");				// return error code in r0
	__POPRET("");

	//  Convert double in r0,r1 to int in r0
	//	Return error code in r12
	//	Registers r0,r1,r2,r12 modified
	asm("TReal64GetTInt: ");
	asm("mov r2, r0, lsr #20 ");
	asm("bic r2, r2, #0x800 ");			// r1=exponent
	asm("add r12, r2, #1 ");
	asm("cmp r12, #0x800 ");			// check for NaN
	asm("bne TReal64GetTInt1 ");
	asm("movs r12, r0, lsl #12 ");		// exponent=FF, check mantissa
	asm("cmpeq r1, #0 ");
	asm("movne r0, #0 ");				// if non-zero, input is a NaN so return 0
	asm("mvnne r12, #5 ");				// and return KErrArgument
	__JUMP(ne,lr);
	asm("TReal64GetTInt1: ");
	asm("mov r12, #0x400 ");
	asm("orr r12, r12, #0x1E ");		// r12=0x41E (exponent of 2^31)
	asm("subs r2, r12, r2 ");			// r2=number of shifts to produce integer
	asm("mov r12, #0 ");				// set return code to KErrNone
	asm("ble TReal64GetTInt2 ");		// if <=0, saturate result
	asm("cmp r2, #31 ");				// check if more than 31 shifts needed
	asm("movhi r0, #0 ");				// if so, underflow result to 0
	__JUMP(hi,lr);
	asm("cmp r0, #0 ");					// check sign bit
	asm("orr r0, r0, #0x00100000 ");	// set implicit integer bit
	asm("mov r0, r0, lsl #11 ");		// shift mantissa up so MSB is in MSB of r0
	asm("orr r0, r0, r1, lsr #21 ");	// put in bits from r1
	asm("mov r0, r0, lsr r2 ");			// r0=absolute integer
	asm("rsbmi r0, r0, #0 ");			// if negative, negate
	__JUMP(,lr);
	asm("TReal64GetTInt2: ");
	asm("blt TReal64GetTInt3 ");		// if exponent>0x41E, definitely an overflow
	asm("cmp r0, #0 ");					// check sign bit
	asm("bpl TReal64GetTInt3 ");		// if positive, definitely an overflow
	asm("orr r0, r0, #0x00100000 ");	// set implicit integer bit
	asm("mov r0, r0, lsl #11 ");		// shift mantissa up so MSB is in MSB of r0
	asm("orr r0, r0, r1, lsr #21 ");	// put in bits from r1
	asm("cmp r0, #0x80000000 ");		// check if value is = -2^31
	__JUMP(eq,lr);
	asm("TReal64GetTInt3: ");
	asm("cmp r0, #0 ");					// check sign
	asm("mov r0, #0x80000000 ");
	asm("subpl r0, r0, #1 ");			// if -ve return 80000000, if +ve return 7FFFFFFF
	asm("mvnpl r12, #8 ");				// if +ve return KErrOverflow
	asm("mvnmi r12, #9 ");				// if -ve return KErrUnderflow
	__JUMP(,lr);
	}
#endif // __USE_VFP_MATH




__NAKED__ EXPORT_C TBool Math::IsZero(const TReal& /*aVal*/)
/**
Determines whether a value is zero.

@param aVal A reference to the value to be checked. 

@return True, if aVal is zero; false, otherwise.
*/
	{
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("ldmia r0, {r1,r2} ");			// input value into r0,r1
#else
	asm("ldr r2, [r0, #0] ");
	asm("ldr r1, [r0, #4] ");
#endif
	asm("TReal64IsZero: ");
	asm("mov r0, #0 ");					// default return value is 0
	asm("bics r1, r1, #0x80000000 ");	// remove sign bit
	asm("cmpeq r2, #0 ");				// and check both exponent and mantissa are zero
	asm("moveq r0, #1 ");				// return 1 if zero
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TBool Math::IsNaN(const TReal& /*aVal*/)
/**
Determines whether a value is not a number.

@param aVal A reference to the value to be checked. 

@return True, if aVal is not a number; false, otherwise.
*/
	{
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("ldmia r0, {r1,r2} ");			// input value into r0,r1
#else
	asm("ldr r2, [r0, #0] ");
	asm("ldr r1, [r0, #4] ");
#endif
	asm("TReal64IsNaN: ");
	asm("mov r0, #0 ");					// default return value is 0
	asm("bic r1, r1, #0x80000000 ");	// remove sign bit
	asm("cmn r1, #0x00100000 ");		// check if exponent=7FF
	__JUMP(pl,lr);
	asm("movs r1, r1, lsl #12 ");		// exponent=7FF, check mantissa
	asm("cmpeq r2, #0 ");
	asm("movne r0, #1 ");				// if mantissa nonzero, return 1
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TBool Math::IsInfinite(const TReal& /*aVal*/)
/**
Determines whether a value is infinite.

@param aVal A reference to the value to be checked.

@return True, if aVal is infinite; false, otherwise.
*/
	{
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("ldmia r0, {r1,r2} ");			// input value into r0,r1
#else
	asm("ldr r2, [r0, #0] ");
	asm("ldr r1, [r0, #4] ");
#endif
	asm("TReal64IsInfinite: ");
	asm("mov r0, #0 ");					// default return value is 0
	asm("mov r3, #0x00200000 ");		// r3 == - (0x7ff00000 << 1)
	asm("cmp r2, #0 ");
	asm("cmneq r3, r1, lsl #1 ");		// check exp=7FF && mant=0
	asm("moveq r0, #1 ");				// if so, return 1
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C TBool Math::IsFinite(const TReal& /*aVal*/)
/**
Determines whether a value is finite.

In this context, a value is finite if it is a valid number and
is not infinite.

@param aVal A reference to the value to be checked.

@return True, if aVal is finite; false, otherwise.
*/
	{
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("ldr r1, [r0, #0] ");			// only need exponent - get it into r0
#else
	asm("ldr r1, [r0, #4] ");			// only need exponent - get it into r0
#endif
	asm("TReal64IsFinite: ");
	asm("mov r0, #0 ");					// default return value is 0
	asm("bic r1, r1, #0x80000000 ");	// remove sign bit
	asm("cmn r1, #0x00100000 ");		// check if exponent=7FF
	asm("movpl r0, #1 ");				// else return 1
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C void Math::SetZero(TReal& /*aVal*/, TInt /*aSign*/)
//
// Constructs zeros, assuming default sign is positive
//
	{
	asm("cmp r1, #0 ");					// test aSign
	asm("movne r1, #0x80000000 ");		// if nonzero, set sign bit
	asm("mov r2, #0 ");					// mantissa=0
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("stmia r0, {r1,r2} ");
#else
	asm("str r2, [r0, #0] ");
	asm("str r1, [r0, #4] ");
#endif
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C void Math::SetNaN(TReal& /*aVal*/)
//
// Constructs NaN (+ve sign for Java)
//
	{
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("mvn r1, #0x80000000 ");		// r1=7FFFFFFF
	asm("mvn r2, #0 ");					// r2=FFFFFFFF
#else
	asm("mvn r2, #0x80000000 ");		// r2=7FFFFFFF
	asm("mvn r1, #0 ");					// r1=FFFFFFFF
#endif
	asm("stmia r0, {r1,r2} ");
	__JUMP(,lr);
	}




__NAKED__ EXPORT_C void Math::SetInfinite(TReal& /*aVal*/, TInt /*aSign*/)
//
// Constructs infinities
//
	{
	asm("cmp r1, #0 ");					// test aSign
	asm("movne r1, #0x80000000 ");		// if nonzero, set sign bit
	asm("orr r1, r1, #0x70000000 ");	// set exponent to 7FF
	asm("orr r1, r1, #0x0FF00000 ");
	asm("mov r2, #0 ");					// mantissa=0
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("stmia r0, {r1,r2} ");
#else
	asm("str r2, [r0, #0] ");
	asm("str r1, [r0, #4] ");
#endif
	__JUMP(,lr);
	}



#ifndef __USE_VFP_MATH
__NAKED__ EXPORT_C TInt Math::Frac(TReal& /*aTrg*/, const TReal& /*aSrc*/)
/**
Calculates the fractional part of a number.

The fractional part is that after a decimal point.
Truncation is toward zero, so that
Frac(2.4)=0.4, Frac(2)=0, Frac(-1)=0, Frac(-1.4)=0.4.

@param aTrg A reference containing the result.
@param aSrc The number whose fractional part is required. 

@return KErrNone if successful, otherwise another of
        the system-wide error codes.
*/
	{
	// on entry r0=aTrg, r1=&Src
	// on exit r0=return code
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("ldmia r1, {r1,r2} ");		// r1,r2=aSrc
#else
	asm("ldr r2, [r1, #0] ");
	asm("ldr r1, [r1, #4] ");
#endif
	asm("and r3, r1, #0x80000000 ");
	asm("str r3, [sp, #-4]! ");		// save sign
	asm("mov r3, r1, lsr #20 ");
	asm("bic r3, r3, #0x800 ");		// r3=exponent of aSrc
	asm("mov r12, #0x300 ");
	asm("orr r12, r12, #0xFE ");	// r12=0x3FE
	asm("subs r3, r3, r12 ");		// r3=exponent of aSrc-0x3FE=number of integer bits
	asm("ble MathFrac0 ");			// if <=0, return aSrc unaltered
	asm("cmp r3, #53 ");
	asm("bge MathFrac1 ");			// if >=53 integer bits, there is no fractional part
	asm("mov r1, r1, lsl #11 ");	// left-justify mantissa in r1,r2
	asm("orr r1, r1, r2, lsr #21 ");
	asm("mov r2, r2, lsl #11 ");
	asm("cmp r3, #32 ");			// check for >=32 integer bits
	asm("bge MathFrac2 ");
	asm("rsb r12, r3, #32 ");
	asm("mov r1, r1, lsl r3 ");		// shift mantissa left by number of integer bits
	asm("orrs r1, r1, r2, lsr r12 ");
	asm("mov r2, r2, lsl r3 ");
	asm("mov r3, #0x300 ");			// r3 holds exponent = 0x3FE initially
	asm("orr r3, r3, #0xFE ");
	asm("beq MathFrac3 ");			// branch if >=32 shifts to normalise
#ifdef __CPU_ARM_HAS_CLZ
	CLZ(12,1);
	asm("mov r1, r1, lsl r12 ");
	asm("rsb r12, r12, #32 ");
	asm("orr r1, r1, r2, lsr r12 ");
	asm("rsb r12, r12, #32 ");
#else
	asm("mov r12, #32 ");			// else r12=32-number of shifts needed
	asm("cmp r1, #0x10000 ");		// calculate shift count
	asm("movcc r1, r1, lsl #16 ");
	asm("subcc r12, r12, #16 ");
	asm("cmp r1, #0x1000000 ");
	asm("movcc r1, r1, lsl #8 ");
	asm("subcc r12, r12, #8 ");
	asm("cmp r1, #0x10000000 ");
	asm("movcc r1, r1, lsl #4 ");
	asm("subcc r12, r12, #4 ");
	asm("cmp r1, #0x40000000 ");
	asm("movcc r1, r1, lsl #2 ");
	asm("subcc r12, r12, #2 ");
	asm("cmp r1, #0x80000000 ");
	asm("movcc r1, r1, lsl #1 ");
	asm("subcc r12, r12, #1 ");
	asm("orr r1, r1, r2, lsr r12 ");	// normalise
	asm("rsb r12, r12, #32 ");			// r12=shift count
#endif
	asm("mov r2, r2, lsl r12 ");
	asm("sub r3, r3, r12 ");			// exponent-=shift count
	asm("b MathFrac4 ");				// branch to assemble and store result

	// come here if >=32 shifts to normalise
	asm("MathFrac3: ");
	asm("sub r3, r3, #32 ");		// decrement exponent by 32
	asm("movs r1, r2 ");			// shift left by 32, set Z if result zero
	asm("mov r2, #0 ");
	asm("bne MathFrac6 ");			// if result nonzero, normalise
	asm("beq MathFrac5 ");			// branch if result zero

	// come here if >=32 integer bits
	asm("MathFrac2: ");
	asm("sub r3, r3, #32 ");
	asm("movs r1, r2, lsl r3 ");	// shift left by number of integer bits, set Z if result zero
	asm("mov r2, #0 ");
	asm("mov r3, #0x300 ");			// r3 holds exponent = 0x3FE initially
	asm("orr r3, r3, #0xFE ");
	asm("beq MathFrac5 ");			// branch if result zero
	asm("MathFrac6: ");
	asm("cmp r1, #0x10000 ");		// else normalise
	asm("movcc r1, r1, lsl #16 ");
	asm("subcc r3, r3, #16 ");
	asm("cmp r1, #0x1000000 ");
	asm("movcc r1, r1, lsl #8 ");
	asm("subcc r3, r3, #8 ");
	asm("cmp r1, #0x10000000 ");
	asm("movcc r1, r1, lsl #4 ");
	asm("subcc r3, r3, #4 ");
	asm("cmp r1, #0x40000000 ");
	asm("movcc r1, r1, lsl #2 ");
	asm("subcc r3, r3, #2 ");
	asm("cmp r1, #0x80000000 ");
	asm("movcc r1, r1, lsl #1 ");
	asm("subcc r3, r3, #1 ");

	// come here to assemble and store result
	asm("MathFrac4: ");
	asm("bic r1, r1, #0x80000000 ");	// remove integer bit
	asm("mov r2, r2, lsr #11 ");		// shift mantissa right by 11
	asm("orr r2, r2, r1, lsl #21 ");
	asm("mov r1, r1, lsr #11 ");
	asm("ldr r12, [sp] ");
	asm("orr r1, r1, r3, lsl #20 ");	// exponent into r1 bits 20-30
	asm("orr r1, r1, r12 ");			// sign bit into r1 bit 31

	// come here to return source unaltered
	asm("MathFrac0: ");
	asm("add sp, sp, #4 ");
	asm("MathFrac_ok: ");
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("stmia r0, {r1,r2} ");			// store result
#else
	asm("str r2, [r0, #0] ");
	asm("str r1, [r0, #4] ");
#endif
	asm("mov r0, #0 ");					// return KErrNone
	__JUMP(,lr);

	// come here if infinity, NaN or >=53 integer bits
	asm("MathFrac1: ");
	asm("cmp r3, #0x400 ");				// check for infinity/NaN
	asm("bhi MathFrac7 ");				// branch if so

	// come here to return zero
	asm("MathFrac5: ");
	asm("ldr r1, [sp], #4 ");			// r1 bit 31=sign, rest zero
	asm("mov r2, #0 ");
	asm("b MathFrac_ok ");

	// come here if infinity/NaN
	asm("MathFrac7: ");
	asm("movs r12, r1, lsl #12 ");		// check for infinity
	asm("cmpeq r2, #0 ");
	asm("bne MathFrac8 ");				// branch if NaN
	asm("ldr r1, [sp], #4 ");			// r1 bit 31=sign, rest zero
	asm("mov r2, #0 ");
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("stmia r0, {r1,r2} ");			// store zero result
#else
	asm("str r2, [r0, #0] ");
	asm("str r1, [r0, #4] ");
#endif
	asm("mvn r0, #8 ");					// return KErrOverflow
	__JUMP(,lr);
	asm("MathFrac8: ");					// NaN
	asm("add sp, sp, #4 ");
#ifdef __DOUBLE_WORDS_SWAPPED__
	asm("stmia r0, {r1,r2} ");			// store NaN unchanged
#else
	asm("str r2, [r0, #0] ");
	asm("str r1, [r0, #4] ");
#endif
	asm("mvn r0, #5 ");					// return KErrArgument
	__JUMP(,lr);
	}
#endif // __USE_VFP_MATH
#endif

#ifdef __REALS_MACHINE_CODED__
#ifndef __ARMCC__
extern "C" {

extern "C" void __math_exception(TInt aErrType);
__NAKED__ EXPORT_C TReal32 __addsf3(TReal32 /*a1*/, TReal32 /*a2*/)
//
// Add two floats
//
    {
	// a1 is in r0, a2 in r1 on entry; return with answer in r0
	asm("stmfd sp!, {r4-r8,lr} ");
	asm("bl ConvertTReal32ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
	asm("mov r4, r1 ");					// move into r4,r5,r6
	asm("mov r5, r2 ");
	asm("mov r6, r3 ");
	asm("mov r1, r0 ");					// a1 into r1
	asm("bl ConvertTReal32ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
	asm("bl TRealXAdd ");				// add a1+a2, result in r1,r2,r3
	asm("bl TRealXGetTReal32 ");		// convert result to TReal32 in r0, error code in r12
	asm("cmp r12, #0 ");				// check error code
	__CPOPRET(eq,"r4-r8,");
	asm("stmfd sp!, {r0} ");			// save result
	asm("mov r0, r12 ");				// error code into r0
	asm("bl __math_exception ");		// raise exception
	__POPRET("r0,r4-r8,");
    }

__NAKED__ EXPORT_C TReal64 __adddf3(TReal64 /*a1*/, TReal64 /*a2*/)
//
// Add two doubles
//
    {
	// a1 is in r0,r1 a2 in r2,r3 on entry; return with answer in r0,r1
	asm("stmfd sp!, {r4-r8,lr} ");
	asm("mov r7, r2 ");					// save a2
	asm("mov r8, r3 ");
	asm("mov r2, r1 ");					// a1 into r1,r2
	asm("mov r1, r0 ");
	asm("bl ConvertTReal64ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
	asm("mov r4, r1 ");					// move into r4,r5,r6
	asm("mov r5, r2 ");
	asm("mov r6, r3 ");
	asm("mov r1, r7 ");					// a2 into r1,r2
	asm("mov r2, r8 ");
	asm("bl ConvertTReal64ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
	asm("bl TRealXAdd ");				// add a1+a2, result in r1,r2,r3
	asm("bl TRealXGetTReal64 ");		// convert result to TReal64 in r0,r1 error code in r12
	asm("cmp r12, #0 ");				// check error code
	__CPOPRET(eq,"r4-r8,");
	asm("stmfd sp!, {r0,r1} ");			// save result
	asm("mov r0, r12 ");				// error code into r0
	asm("bl __math_exception ");		// raise exception
	__POPRET("r0,r1,r4-r8,");
    }

__NAKED__ EXPORT_C TReal32 __subsf3(TReal32 /*a1*/, TReal32 /*a2*/)
//
// Subtract two floats
//
    {
	// a1 is in r0, a2 in r1 on entry; return with answer in r0
	asm("stmfd sp!, {r4-r8,lr} ");
	asm("bl ConvertTReal32ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
	asm("mov r4, r1 ");					// move into r4,r5,r6
	asm("mov r5, r2 ");
	asm("mov r6, r3 ");
	asm("mov r1, r0 ");					// a1 into r1
	asm("bl ConvertTReal32ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
	asm("bl TRealXSubtract ");			// subtract a1-a2, result in r1,r2,r3
	asm("bl TRealXGetTReal32 ");		// convert result to TReal32 in r0, error code in r12
	asm("cmp r12, #0 ");				// check error code
	__CPOPRET(eq,"r4-r8,");
	asm("stmfd sp!, {r0} ");			// save result
	asm("mov r0, r12 ");				// error code into r0
	asm("bl __math_exception ");		// raise exception
	__POPRET("r0,r4-r8,");
	}

__NAKED__ EXPORT_C TReal64 __subdf3(TReal64 /*a1*/, TReal64 /*a2*/)
//
// Subtract two doubles
//
    {
	// a1 is in r0,r1 a2 in r2,r3 on entry; return with answer in r0,r1
	asm("stmfd sp!, {r4-r8,lr} ");
	asm("mov r7, r0 ");					// save a1
	asm("mov r8, r1 ");
	asm("mov r1, r2 ");					// a2 into r1,r2
	asm("mov r2, r3 ");
	asm("bl ConvertTReal64ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
	asm("mov r4, r1 ");					// move into r4,r5,r6
	asm("mov r5, r2 ");
	asm("mov r6, r3 ");
	asm("mov r1, r7 ");					// a1 into r1,r2
	asm("mov r2, r8 ");
	asm("bl ConvertTReal64ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
	asm("bl TRealXSubtract ");			// subtract a1-a2, result in r1,r2,r3
	asm("bl TRealXGetTReal64 ");		// convert result to TReal64 in r0,r1 error code in r12
	asm("cmp r12, #0 ");				// check error code
	__CPOPRET(eq,"r4-r8,");
	asm("stmfd sp!, {r0,r1} ");			// save result
	asm("mov r0, r12 ");				// error code into r0
	asm("bl __math_exception ");		// raise exception
	__POPRET("r0,r1,r4-r8,");
    }

__NAKED__ EXPORT_C TInt __cmpsf3(TReal32 /*a1*/, TReal32 /*a2*/)
//
// Compare two floats
//
    {
	// a1 in r0, a2 in r1 on entry
	asm("stmfd sp!, {lr} ");
	asm("bl CompareTReal32 ");			// compare the two numbers
	asm("mov r0, r0, lsl #28 ");
	asm("msr cpsr_flg, r0 ");			// N=unordered, Z=(a1>a2), C=(a1=a2), V=(a1<a2)
	asm("mov r0, #0 ");
	asm("mvnvs r0, #0 ");				// if a1<a2 r0=-1
	asm("moveq r0, #1 ");				// if a1>a2 r0=+1
	__POPRET("");

	// Compare two TReal32s in r0, r1.
	// Return 1 if r0<r1, 2 if r0=r1, 4 if r0>r1, 8 if unordered
	// Registers r0,r1,r12 modified
	asm("CompareTReal32: ");
	asm("mov r12, r0, lsr #23 ");
	asm("and r12, r12, #0xFF ");		// r12=r0 exponent
	asm("cmp r12, #0xFF ");				// check if r0 is a NaN
	asm("bne CompareTReal32a ");
	asm("movs r12, r0, lsl #9 ");		// exponent=FF, check mantissa
	asm("movne r0, #8 ");				// if not zero, r0 is a NaN so result is unordered
	__JUMP(ne,lr);
	asm("CompareTReal32a: ");
	asm("mov r12, r1, lsr #23 ");
	asm("and r12, r12, #0xFF ");		// r12=r1 exponent
	asm("cmp r12, #0xFF ");				// check if r1 is a NaN
	asm("bne CompareTReal32b ");
	asm("movs r12, r1, lsl #9 ");		// exponent=FF, check mantissa
	asm("movne r0, #8 ");				// if not zero, r1 is a NaN so result is unordered
	__JUMP(ne,lr);
	asm("CompareTReal32b: ");
	asm("bics r12, r0, #0x80000000 ");	// check if r0=0 (can be +0 or -0)
	asm("moveq r0, #0 ");				// if it is, make it +0
	asm("bics r12, r1, #0x80000000 ");	// check if r1=0 (can be +0 or -0)
	asm("moveq r1, #0 ");				// if it is, make it +0
	asm("teq r0, r1 ");					// test if signs different
	asm("bmi CompareTReal32c ");		// branch if different
	asm("cmp r0, r1 ");					// if same, check exponents + mantissas
	asm("moveq r0, #2 ");				// if equal, return 2
	__JUMP(eq,lr);
	asm("movhi r0, #4 ");				// if r0>r1, r0=4
	asm("movcc r0, #1 ");				// if r0<r1, r0=1
	asm("cmp r1, #0 ");					// check signs
	asm("eormi r0, r0, #5 ");			// if negative, switch 1 and 4
	__JUMP(,lr);
	asm("CompareTReal32c: ");			// come here if signs different
	asm("cmp r0, #0 ");					// check sign of r0
	asm("movpl r0, #4 ");				// if r0 nonnegative, then r0 is greater so return 4
	asm("movmi r0, #1 ");				// if r0 negative, return 1
	__JUMP(,lr);
    }

__NAKED__ EXPORT_C TInt __cmpdf3(TReal64 /*a1*/,TReal64 /*a2*/)
//
// Compare two doubles
//
    {
	// a1 in r0,r1, a2 in r2,r3 on entry
	asm("stmfd sp!, {lr} ");
	asm("bl CompareTReal64 ");			// compare the two numbers
	asm("mov r0, r0, lsl #28 ");
	asm("msr cpsr_flg, r0 ");			// N=unordered, Z=(a1>a2), C=(a1=a2), V=(a1<a2)
	asm("mov r0, #0 ");
	asm("mvnvs r0, #0 ");				// if a1<a2 r0=-1
	asm("moveq r0, #1 ");				// if a1>a2 r0=+1
	__POPRET("");

	// Compare two TReal64s in r0,r1 and r2,r3.
	// Return 1 if r0,r1<r2,r3
	// Return 2 if r0,r1=r2,r3
	// Return 4 if r0,r1>r2,r3
	// Return 8 if unordered
	// Registers r0,r1,r12 modified
	asm("CompareTReal64: ");
#ifndef __DOUBLE_WORDS_SWAPPED__
	asm("mov r12, r0 ");
	asm("mov r0, r1 ");
	asm("mov r1, r12 ");
	asm("mov r12, r2 ");
	asm("mov r2, r3 ");
	asm("mov r3, r12 ");
#endif
	asm("mov r12, r0, lsr #20 ");
	asm("bic r12, r12, #0x800 ");		// r12=first operand exponent
	asm("add r12, r12, #1 ");			// add 1 to get usable compare value
	asm("cmp r12, #0x800 ");			// check if first operand is a NaN
	asm("bne CompareTReal64a ");
	asm("movs r12, r0, lsl #12 ");		// exponent=7FF, check mantissa
	asm("cmpeq r1, #0 ");
	asm("movne r0, #8 ");				// if not zero, 1st op is a NaN so result is unordered
	__JUMP(ne,lr);
	asm("CompareTReal64a: ");
	asm("mov r12, r2, lsr #20 ");
	asm("bic r12, r12, #0x800 ");		// r12=second operand exponent
	asm("add r12, r12, #1 ");			// add 1 to get usable compare value
	asm("cmp r12, #0x800 ");			// check if second operand is a NaN
	asm("bne CompareTReal64b ");
	asm("movs r12, r2, lsl #12 ");		// exponent=7FF, check mantissa
	asm("cmpeq r3, #0 ");
	asm("movne r0, #8 ");				// if not zero, 2nd op is a NaN so result is unordered
	__JUMP(ne,lr);
	asm("CompareTReal64b: ");
	asm("bics r12, r0, #0x80000000 ");	// check if first operand is zero (can be +0 or -0)
	asm("cmpeq r1, #0 ");
	asm("moveq r0, #0 ");				// if it is, make it +0
	asm("bics r12, r2, #0x80000000 ");	// check if second operand is zero (can be +0 or -0)
	asm("cmpeq r3, #0 ");
	asm("moveq r2, #0 ");				// if it is, make it +0
	asm("teq r0, r2 ");					// test if signs different
	asm("bmi CompareTReal64c ");		// branch if different
	asm("cmp r0, r2 ");					// if same, check exponents + mantissas
	asm("cmpeq r1, r3 ");
	asm("moveq r0, #2 ");				// if equal, return 2
	__JUMP(eq,lr);
	asm("movhi r0, #4 ");				// if 1st operand > 2nd operand, r0=4
	asm("movcc r0, #1 ");				// if 1st operand < 2nd operand, r0=1
	asm("cmp r2, #0 ");					// check signs
	asm("eormi r0, r0, #5 ");			// if negative, switch 1 and 4
	__JUMP(,lr);
	asm("CompareTReal64c: ");			// come here if signs different
	asm("cmp r0, #0 ");					// check sign of r0
	asm("movpl r0, #4 ");				// if first operand nonnegative, return 4
	asm("movmi r0, #1 ");				// if first operand negative, return 1
	__JUMP(,lr);
    }

__NAKED__ EXPORT_C TInt __eqsf2(TReal32 /*a1*/, TReal32 /*a2*/)
//
// Compare if two floats are equal
//
    {
	// a1 in r0, a2 in r1 on entry
	asm("stmfd sp!, {lr} ");
	asm("bl CompareTReal32 ");			// compare the two numbers
	asm("tst r0, #2 ");
	asm("movne r0, #0 ");				// if ordered and equal return 0
	asm("moveq r0, #1 ");				// else return 1
	__POPRET("");
    }

__NAKED__ EXPORT_C TInt __eqdf2(TReal64 /*a1*/, TReal64 /*a2*/)
//
// Compare if two doubles are equal
//
    {
	// a1 in r0,r1, a2 in r2,r3 on entry
	asm("stmfd sp!, {lr} ");
	asm("bl CompareTReal64 ");			// compare the two numbers
	asm("tst r0, #2 ");
	asm("movne r0, #0 ");				// if ordered and equal return 0
	asm("moveq r0, #1 ");				// else return 1
	__POPRET("");
    }

__NAKED__ EXPORT_C TInt __nesf2(TReal32 /*a1*/, TReal32 /*a2*/)
//
// Compare if two floats are not equal
//
    {
	// a1 in r0, a2 in r1 on entry
	asm("stmfd sp!, {lr} ");
	asm("bl CompareTReal32 ");			// compare the two numbers
	asm("tst r0, #5 ");					// test if ordered and unequal
	asm("moveq r0, #0 ");				// if equal or unordered return 0
	asm("movne r0, #1 ");				// if ordered and unequal return 1
	__POPRET("");
    }

__NAKED__ EXPORT_C TInt __nedf2(TReal64 /*a1*/, TReal64 /*a2*/)
//
// Compare if two doubles are not equal
//
    {
	// a1 in r0,r1, a2 in r2,r3 on entry
	asm("stmfd sp!, {lr} ");
	asm("bl CompareTReal64 ");			// compare the two numbers
	asm("tst r0, #5 ");					// test if ordered and unequal
	asm("moveq r0, #0 ");				// if equal or unordered return 0
	asm("movne r0, #1 ");				// if ordered and unequal return 1
	__POPRET("");
    }

__NAKED__ EXPORT_C TInt __gtsf2(TReal32 /*a1*/, TReal32 /*a2*/)
//
// Compare if one float is greater than another
//
    {
	// a1 in r0, a2 in r1 on entry
	asm("stmfd sp!, {lr} ");
	asm("bl CompareTReal32 ");			// compare the two numbers
	asm("tst r0, #4 ");					// test if ordered and a1>a2
	asm("movne r0, #1 ");				// if ordered and a1>a2 return +1
	asm("mvneq r0, #0 ");				// else return -1
	__POPRET("");
    }

__NAKED__ EXPORT_C TInt __gtdf2(TReal64 /*a1*/, TReal64 /*a2*/)
//
// Compare if one double is greater than another
//
    {
	// a1 in r0,r1, a2 in r2,r3 on entry
	asm("stmfd sp!, {lr} ");
	asm("bl CompareTReal64 ");			// compare the two numbers
	asm("tst r0, #4 ");					// test if ordered and a1>a2
	asm("movne r0, #1 ");				// if ordered and a1>a2 return +1
	asm("mvneq r0, #0 ");				// else return -1
	__POPRET("");
    }

__NAKED__ EXPORT_C TInt __gesf2(TReal32 /*a1*/, TReal32 /*a2*/)
//
// Compare if one float is greater than or equal to another
//
    {
	// a1 in r0, a2 in r1 on entry
	asm("stmfd sp!, {lr} ");
	asm("bl CompareTReal32 ");			// compare the two numbers
	asm("tst r0, #6 ");					// test if ordered and a1>=a2
	asm("movne r0, #1 ");				// if ordered and a1>=a2 return +1
	asm("mvneq r0, #0 ");				// else return -1
	__POPRET("");
    }

__NAKED__ EXPORT_C TInt __gedf2(TReal64 /*a1*/, TReal64 /*a2*/)
//
// Compare if one double is greater than or equal to another
//
    {
	// a1 in r0,r1, a2 in r2,r3 on entry
	asm("stmfd sp!, {lr} ");
	asm("bl CompareTReal64 ");			// compare the two numbers
	asm("tst r0, #6 ");					// test if ordered and a1>=a2
	asm("movne r0, #1 ");				// if ordered and a1>=a2 return +1
	asm("mvneq r0, #0 ");				// else return -1
	__POPRET("");
    }

__NAKED__ EXPORT_C TInt __ltsf2(TReal32 /*a1*/, TReal32 /*a2*/)
//
// Compare if one float is less than another
//
    {
	// a1 in r0, a2 in r1 on entry
	asm("stmfd sp!, {lr} ");
	asm("bl CompareTReal32 ");			// compare the two numbers
	asm("tst r0, #1 ");					// test if ordered and a1<a2
	asm("mvnne r0, #0 ");				// if ordered and a1<a2 return -1
	asm("moveq r0, #1 ");				// else return +1
	__POPRET("");
    }

__NAKED__ EXPORT_C TInt __ltdf2(TReal64 /*a1*/, TReal64 /*a2*/)
//
// Compare if one double is less than another
//
    {
	// a1 in r0,r1, a2 in r2,r3 on entry
	asm("stmfd sp!, {lr} ");
	asm("bl CompareTReal64 ");			// compare the two numbers
	asm("tst r0, #1 ");					// test if ordered and a1<a2
	asm("mvnne r0, #0 ");				// if ordered and a1<a2 return -1
	asm("moveq r0, #1 ");				// else return +1
	__POPRET("");
    }

__NAKED__ EXPORT_C TInt __lesf2(TReal32 /*a1*/, TReal32 /*a2*/)
//
// Compare if one float is less than or equal to another
//
    {
	// a1 in r0, a2 in r1 on entry
	asm("stmfd sp!, {lr} ");
	asm("bl CompareTReal32 ");			// compare the two numbers
	asm("tst r0, #3 ");					// test if ordered and a1<=a2
	asm("mvnne r0, #0 ");				// if ordered and a1<=a2 return -1
	asm("moveq r0, #1 ");				// else return +1
	__POPRET("");
    }

__NAKED__ EXPORT_C TInt __ledf2(TReal64 /*a1*/, TReal64 /*a2*/)
//
// Compare if one double is less than or equal to another
//
    {
	// a1 in r0,r1, a2 in r2,r3 on entry
	asm("stmfd sp!, {lr} ");
	asm("bl CompareTReal64 ");			// compare the two numbers
	asm("tst r0, #3 ");					// test if ordered and a1<=a2
	asm("mvnne r0, #0 ");				// if ordered and a1<=a2 return -1
	asm("moveq r0, #1 ");				// else return +1
	__POPRET("");
    }

__NAKED__ EXPORT_C TReal32 __mulsf3(TReal32 /*a1*/,TReal32 /*a2*/)
//
// Multiply two floats
//
    {
	// a1 is in r0, a2 in r1 on entry; return with answer in r0
	asm("stmfd sp!, {r4-r7,lr} ");
	asm("bl ConvertTReal32ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
	asm("mov r4, r1 ");					// move into r4,r5,r6
	asm("mov r5, r2 ");
	asm("mov r6, r3 ");
	asm("mov r1, r0 ");					// a1 into r1
	asm("bl ConvertTReal32ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
	asm("bl TRealXMultiply ");			// multiply a1*a2, result in r1,r2,r3
	asm("bl TRealXGetTReal32 ");		// convert result to TReal32 in r0, error code in r12
	asm("cmp r12, #0 ");				// check error code
	__CPOPRET(eq,"r4-r7,");
	asm("stmfd sp!, {r0} ");			// save result
	asm("mov r0, r12 ");				// error code into r0
	asm("bl __math_exception ");		// raise exception
	__POPRET("r0,r4-r7,");
    }

__NAKED__ EXPORT_C TReal64 __muldf3(TReal64 /*a1*/, TReal64 /*a2*/)
//
// Multiply two doubles
//
    {
	// a1 is in r0,r1 a2 in r2,r3 on entry; return with answer in r0,r1
	asm("stmfd sp!, {r4-r8,lr} ");
	asm("mov r7, r2 ");					// save a2
	asm("mov r8, r3 ");
	asm("mov r2, r1 ");					// a1 into r1,r2
	asm("mov r1, r0 ");
	asm("bl ConvertTReal64ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
	asm("mov r4, r1 ");					// move into r4,r5,r6
	asm("mov r5, r2 ");
	asm("mov r6, r3 ");
	asm("mov r1, r7 ");					// a2 into r1,r2
	asm("mov r2, r8 ");
	asm("bl ConvertTReal64ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
	asm("bl TRealXMultiply ");			// multiply a1*a2, result in r1,r2,r3
	asm("bl TRealXGetTReal64 ");		// convert result to TReal64 in r0,r1 error code in r12
	asm("cmp r12, #0 ");				// check error code
	__CPOPRET(eq,"r4-r8,");
	asm("stmfd sp!, {r0,r1} ");			// save result
	asm("mov r0, r12 ");				// error code into r0
	asm("bl __math_exception ");		// raise exception
	__POPRET("r0,r1,r4-r8,");
    }

__NAKED__ EXPORT_C TReal32 __divsf3(TReal32 /*a1*/, TReal32 /*a2*/)
//
// Divide two floats
//
    {
	// a1 is in r0, a2 in r1 on entry; return with answer in r0
	asm("stmfd sp!, {r4-r9,lr} ");
	asm("bl ConvertTReal32ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
	asm("mov r4, r1 ");					// move into r4,r5,r6
	asm("mov r5, r2 ");
	asm("mov r6, r3 ");
	asm("mov r1, r0 ");					// a1 into r1
	asm("bl ConvertTReal32ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
	asm("bl TRealXDivide ");			// divide a1/a2, result in r1,r2,r3 error code in r12
	asm("mov r9, r12 ");				// save error code in case it's division by zero
	asm("bl TRealXGetTReal32 ");		// convert result to TReal32 in r0, error code in r12
	asm("cmn r9, #41 ");				// check for KErrDivideByZero
	asm("moveq r12, r9 ");
	asm("cmp r12, #0 ");				// check error code
	__CPOPRET(eq,"r4-r9,");
	asm("stmfd sp!, {r0} ");			// save result
	asm("mov r0, r12 ");				// error code into r0
	asm("bl __math_exception ");		// raise exception
	__POPRET("r0,r4-r9,");
    }

__NAKED__ EXPORT_C TReal64 __divdf3(TReal64 /*a1*/, TReal64 /*a2*/)
	//
	// Divide two doubles
	//
	{
	// a1 is in r0,r1 a2 in r2,r3 on entry; return with answer in r0,r1
	asm("stmfd sp!, {r4-r9,lr} ");
	asm("mov r7, r0 ");					// save a1
	asm("mov r8, r1 ");
	asm("mov r1, r2 ");					// a2 into r1,r2
	asm("mov r2, r3 ");
	asm("bl ConvertTReal64ToTRealX ");	// convert a2 to TRealX in r1,r2,r3
	asm("mov r4, r1 ");					// move into r4,r5,r6
	asm("mov r5, r2 ");
	asm("mov r6, r3 ");
	asm("mov r1, r7 ");					// a1 into r1,r2
	asm("mov r2, r8 ");
	asm("bl ConvertTReal64ToTRealX ");	// convert a1 to TRealX in r1,r2,r3
	asm("bl TRealXDivide ");			// divide a1/a2, result in r1,r2,r3
	asm("mov r9, r12 ");				// save error code in case it's division by zero
	asm("bl TRealXGetTReal64 ");		// convert result to TReal64 in r0,r1 error code in r12
	asm("cmn r9, #41 ");				// check for KErrDivideByZero
	asm("moveq r12, r9 ");
	asm("cmp r12, #0 ");				// check error code
	__CPOPRET(eq,"r4-r9,");
	asm("stmfd sp!, {r0,r1} ");			// save result
	asm("mov r0, r12 ");				// error code into r0
	asm("bl __math_exception ");		// raise exception
	__POPRET("r0,r1,r4-r9,");
	}

__NAKED__ EXPORT_C TReal32 __negsf2(TReal32 /*a1*/)
//
// Negate a float
//
    {
	// a1 in r0 on entry, return value in r0
	asm("eor r0, r0, #0x80000000 ");	// change sign bit
	__JUMP(,lr);
    }

__NAKED__ EXPORT_C TReal64 __negdf2(TReal64 /*a1*/)
//
// Negate a double
//
    {
	// a1 in r0,r1 on entry, return value in r0,r1
	asm("eor r0, r0, #0x80000000 ");	// change sign bit
	__JUMP(,lr);
    }

__NAKED__ EXPORT_C TReal32 __floatsisf(TInt /*a1*/)
//
// Convert int to float
//
    {
	// a1 in r0 on entry, return value in r0
	asm("cmp r0, #0 ");					// test for zero or negative
	__JUMP(eq,lr);
	asm("and ip, r0, #0x80000000 ");	// ip=bit 31 of r0 (sign bit)
	asm("rsbmi r0, r0, #0 ");			// if negative, negate it
	asm("mov r2, #0x9E ");				// r2=0x9E=exponent of 2^31
	asm("cmp r0, #0x00010000 ");		// normalise integer, adjusting exponent
	asm("movcc r0, r0, lsl #16 ");
	asm("subcc r2, r2, #16 ");
	asm("cmp r0, #0x01000000 ");
	asm("movcc r0, r0, lsl #8 ");
	asm("subcc r2, r2, #8 ");
	asm("cmp r0, #0x10000000 ");
	asm("movcc r0, r0, lsl #4 ");
	asm("subcc r2, r2, #4 ");
	asm("cmp r0, #0x40000000 ");
	asm("movcc r0, r0, lsl #2 ");
	asm("subcc r2, r2, #2 ");
	asm("cmp r0, #0x80000000 ");
	asm("movcc r0, r0, lsl #1 ");
	asm("subcc r2, r2, #1 ");
	asm("and r1, r0, #0xFF ");			// r1=bottom 8 bits=rounding bits
	asm("cmp r1, #0x80 ");				// check if we need to round up (carry=1 if we do)
	asm("moveqs r1, r0, lsr #9 ");		// if bottom 8 bits=0x80, set carry=LSB of mantissa
	asm("addcss r0, r0, #0x100 ");		// round up if necessary
	asm("addcs r2, r2, #1 ");			// if carry, increment exponent
	asm("bic r0, r0, #0x80000000 ");	// remove top bit (integer bit of mantissa implicit)
	asm("mov r0, r0, lsr #8 ");			// mantissa into r0 bits 0-22
	asm("orr r0, r0, r2, lsl #23 ");	// exponent into r0 bits 23-30
	asm("orr r0, r0, ip ");				// sign bit into r0 bit 31
	__JUMP(,lr);
    }

__NAKED__ EXPORT_C TReal64 __floatsidf(TInt /*a1*/)
//
// Convert int to double
//
    {
	// a1 in r0 on entry, return value in r0,r1
	asm("cmp r0, #0 ");					// test for zero or negative
	asm("moveq r1, #0 ");				// if zero, return 0
	__JUMP(eq,lr);
	asm("and ip, r0, #0x80000000 ");	// ip=bit 31 of r0 (sign bit)
	asm("rsbmi r0, r0, #0 ");			// if negative, negate it
	asm("mov r2, #0x400 ");				// r2=0x41E=exponent of 2^31
	asm("orr r2, r2, #0x1E ");
	asm("cmp r0, #0x00010000 ");		// normalise integer, adjusting exponent
	asm("movcc r0, r0, lsl #16 ");
	asm("subcc r2, r2, #16 ");
	asm("cmp r0, #0x01000000 ");
	asm("movcc r0, r0, lsl #8 ");
	asm("subcc r2, r2, #8 ");
	asm("cmp r0, #0x10000000 ");
	asm("movcc r0, r0, lsl #4 ");
	asm("subcc r2, r2, #4 ");
	asm("cmp r0, #0x40000000 ");
	asm("movcc r0, r0, lsl #2 ");
	asm("subcc r2, r2, #2 ");
	asm("cmp r0, #0x80000000 ");
	asm("movcc r0, r0, lsl #1 ");
	asm("subcc r2, r2, #1 ");
	asm("bic r0, r0, #0x80000000 ");	// remove top bit (integer bit of mantissa implicit)
	asm("mov r1, r0, lsl #21 ");		// low 11 bits of mantissa into r1
	asm("mov r0, r0, lsr #11 ");		// high 20 bits of mantissa into r0 bits 0-19
	asm("orr r0, r0, r2, lsl #20 ");	// exponent into r0 bits 20-30
	asm("orr r0, r0, ip ");				// sign bit into r0 bit 31
#ifndef __DOUBLE_WORDS_SWAPPED__
	asm("mov ip, r0 ");
	asm("mov r0, r1 ");
	asm("mov r1, ip ");
#endif
	__JUMP(,lr);
    }

__NAKED__ EXPORT_C TInt __fixsfsi(TReal32 /*a1*/)
//
// Convert float to int
//
    {
	// a1 in r0 on entry, return value in r0
	asm("mov r1, r0, lsr #23 ");
	asm("and r1, r1, #0xFF ");			// r1=exponent of a1
	asm("cmp r1, #0xFF ");				// check for NaN
	asm("bne fixsfsi1 ");
	asm("movs r2, r0, lsl #9 ");		// exponent=FF, check mantissa
	asm("movne r0, #0 ");				// if non-zero, a1 is a NaN so return 0
	__JUMP(ne,lr);
	asm("fixsfsi1: ");
	asm("rsbs r1, r1, #0x9E ");			// r1=number of shifts to produce integer
	asm("ble fixsfsi2 ");				// if <=0, saturate result
	asm("cmp r0, #0 ");					// check sign bit
	asm("orr r0, r0, #0x00800000 ");	// set implicit integer bit
	asm("mov r0, r0, lsl #8 ");			// shift mantissa up so MSB is in MSB of r0
	asm("mov r0, r0, lsr r1 ");			// r0=absolute integer
	asm("rsbmi r0, r0, #0 ");			// if negative, negate
	__JUMP(,lr);
	asm("fixsfsi2: ");
	asm("cmp r0, #0 ");					// check sign
	asm("mov r0, #0x80000000 ");
	asm("subpl r0, r0, #1 ");			// if -ve return 80000000, if +ve return 7FFFFFFF
	__JUMP(,lr);
    }

__NAKED__ EXPORT_C TInt __fixdfsi(TReal64 /*a1*/)
//
// Convert double to int
//
    {
	// a1 in r0,r1 on entry, return value in r0
#ifndef __DOUBLE_WORDS_SWAPPED__
	asm("mov r2, r0 ");
	asm("mov r0, r1 ");
	asm("mov r1, r2 ");
#endif
	asm("mov r2, r0, lsr #20 ");
	asm("bic r2, r2, #0x800 ");			// r1=exponent of a1
	asm("add r3, r2, #1 ");
	asm("cmp r3, #0x800 ");				// check for NaN
	asm("bne fixdfsi1 ");
	asm("movs r3, r0, lsl #12 ");		// exponent=FF, check mantissa
	asm("cmpeq r1, #0 ");
	asm("movne r0, #0 ");				// if non-zero, a1 is a NaN so return 0
	__JUMP(ne,lr);
	asm("fixdfsi1: ");
	asm("mov r3, #0x400 ");
	asm("orr r3, r3, #0x1E ");			// r3=0x41E (exponent of 2^31)
	asm("subs r2, r3, r2 ");			// r2=number of shifts to produce integer
	asm("ble fixdfsi2 ");				// if <=0, saturate result
	asm("cmp r2, #31 ");				// check if more than 31 shifts needed
	asm("movhi r0, #0 ");				// if so, underflow result to 0
	__JUMP(hi,lr);
	asm("cmp r0, #0 ");					// check sign bit
	asm("orr r0, r0, #0x00100000 ");	// set implicit integer bit
	asm("mov r0, r0, lsl #11 ");		// shift mantissa up so MSB is in MSB of r0
	asm("orr r0, r0, r1, lsr #21 ");	// put in bits from r1
	asm("mov r0, r0, lsr r2 ");			// r0=absolute integer
	asm("rsbmi r0, r0, #0 ");			// if negative, negate
	__JUMP(,lr);
	asm("fixdfsi2: ");
	asm("cmp r0, #0 ");					// check sign
	asm("mov r0, #0x80000000 ");
	asm("subpl r0, r0, #1 ");			// if -ve return 80000000, if +ve return 7FFFFFFF
	__JUMP(,lr);
    }

__NAKED__ EXPORT_C TReal64 __extendsfdf2(TReal32 /*a1*/)
//
// Convert a float to a double
//
    {
	// a1 in r0, return in r0,r1
	asm("mov r3, r0, lsr #3 ");
	asm("ands r3, r3, #0x0FF00000 ");	// r3 bits 20-27 hold exponent, Z=1 if zero/denormal
	asm("mov r1, r0, lsl #9 ");			// r1 = TReal32 mantissa << 9
	asm("and r0, r0, #0x80000000 ");	// leave only sign bit in r0
	asm("beq extendsfdf2a ");			// branch if zero/denormal
	asm("cmp r3, #0x0FF00000 ");		// check for infinity or NaN
	asm("orrcs r3, r3, #0x70000000 ");	// if infinity or NaN, exponent = 7FF
	asm("addcc r3, r3, #0x38000000 ");	// else exponent = TReal32 exponent + 380
	asm("orr r0, r0, r1, lsr #12 ");	// top 20 mantissa bits into r0 bits 0-19
	asm("mov r1, r1, lsl #20 ");		// remaining mantissa bits in r1 bits 29-31
	asm("orr r0, r0, r3 ");				// exponent into r0 bits 20-30
	asm("b 0f ");
	asm("extendsfdf2a: ");				// come here if zero or denormal
	asm("cmp r1, #0 ");					// check for zero
	asm("beq 0f ");
	asm("mov r3, #0x38000000 ");		// else exponent = 380 (highest denormal exponent)
	asm("cmp r1, #0x10000 ");			// normalise mantissa, decrementing exponent as needed
	asm("movcc r1, r1, lsl #16 ");
	asm("subcc r3, r3, #0x01000000 ");
	asm("cmp r1, #0x1000000 ");
	asm("movcc r1, r1, lsl #8 ");
	asm("subcc r3, r3, #0x00800000 ");
	asm("cmp r1, #0x10000000 ");
	asm("movcc r1, r1, lsl #4 ");
	asm("subcc r3, r3, #0x00400000 ");
	asm("cmp r1, #0x40000000 ");
	asm("movcc r1, r1, lsl #2 ");
	asm("subcc r3, r3, #0x00200000 ");
	asm("cmp r1, #0x80000000 ");
	asm("movcc r1, r1, lsl #1 ");
	asm("subcc r3, r3, #0x00100000 ");
	asm("add r1, r1, r1 ");				// shift mantissa left one more to remove integer bit
	asm("orr r0, r0, r1, lsr #12 ");	// top 20 mantissa bits into r0 bits 0-19
	asm("mov r1, r1, lsl #20 ");		// remaining mantissa bits in r1 bits 29-31
	asm("orr r0, r0, r3 ");				// exponent into r0 bits 20-30
	asm("0: ");
#ifndef __DOUBLE_WORDS_SWAPPED__
	asm("mov r3, r0 ");
	asm("mov r0, r1 ");
	asm("mov r1, r3 ");
#endif
	__JUMP(,lr);
    }

__NAKED__ EXPORT_C TReal32 __truncdfsf2(TReal64 /*a1*/)
//
// Convert a double to a float
// Raises an exception if conversion results in an error
//
    {
	asm("stmfd sp!, {lr} ");
	asm("bl TReal64GetTReal32 ");			// do the conversion
	asm("cmp r12, #0 ");					// check error code
	__CPOPRET(eq,"");
	asm("stmfd sp!, {r0} ");				// else save result
	asm("mov r0, r12 ");					// error code into r0
	asm("bl __math_exception ");			// raise exception
	__POPRET("r0,");

	// Convert TReal64 in r0,r1 to TReal32 in r0
	// Return error code in r12
	// r0-r3, r12 modified
	// NB This function is purely internal to EUSER and therefore IS ONLY EVER CALLED IN ARM MODE.
	asm("TReal64GetTReal32: ");
#ifndef __DOUBLE_WORDS_SWAPPED__
	asm("mov r2, r0 ");
	asm("mov r0, r1 ");
	asm("mov r1, r2 ");
#endif
	asm("mov r12, r0, lsr #20 ");
	asm("bic r12, r12, #0x800 ");			// r12=a1 exponent
	asm("sub r12, r12, #0x380 ");			// r12=exp in - 380 = result exponent if in range
	asm("cmp r12, #0xFF ");					// check if input exponent too big for TReal32
	asm("bge TReal64GetTReal32a ");			// branch if it is
	asm("mov r2, r0, lsl #11 ");			// left justify mantissa in r2:r1
	asm("orr r2, r2, r1, lsr #21 ");
	asm("mov r1, r1, lsl #11 ");
	asm("orr r2, r2, #0x80000000 ");		// set implied integer bit in mantissa
	asm("cmp r12, #0 ");
	asm("bgt TReal64GetTReal32b ");			// branch if normalised result
	asm("cmn r12, #23 ");					// check for total underflow or zero
	asm("bge TReal64GetTReal32e ");			// skip if not
	asm("bics r2, r0, #0x80000000 ");		// check if input value zero
	asm("cmpeq r1, #0 ");
	asm("moveq r12, #0 ");					// if zero return KErrNone
	asm("mvnne r12, #9 ");					// else return KErrUnderflow
	asm("and r0, r0, #0x80000000 ");		// return zero of appropriate sign
	asm("mov r1, #0 ");
	__JUMP(,lr);
	asm("TReal64GetTReal32e: ");			// result will be a denormal
	asm("add r12, r12, #31 ");				// r12=32-mantissa shift required = 32-(1-r12)
	asm("movs r3, r1, lsl r12 ");			// r3=lost bits when r2:r1 is shifted
	asm("orrne lr, lr, #1 ");				// if these are not zero, set rounded down flag
	asm("rsb r3, r12, #32 ");
	asm("mov r1, r1, lsr r3 ");
	asm("orr r1, r1, r2, lsl r12 ");
	asm("mov r2, r2, lsr r3 ");				// r2 top 24 bits now give unrounded result mantissa
	asm("mov r12, #0 ");					// result exponent will be zero
	asm("TReal64GetTReal32b: ");
	asm("movs r3, r2, lsl #24 ");			// top 8 truncated bits into top byte of r3
	asm("bpl TReal64GetTReal32c ");			// if top bit clear, truncate
	asm("cmp r3, #0x80000000 ");
	asm("cmpeq r1, #0 ");					// compare rounding bits to 1000...
	asm("bhi TReal64GetTReal32d ");			// if >, round up
	asm("tst lr, #1 ");						// check rounded-down flag
	asm("bne TReal64GetTReal32d ");			// if rounded down, round up
	asm("tst r2, #0x100 ");					// else round to even - test LSB of result mantissa
	asm("beq TReal64GetTReal32c ");			// if zero, truncate, else round up
	asm("TReal64GetTReal32d: ");			// come here to round up
	asm("adds r2, r2, #0x100 ");			// increment the mantissa
	asm("movcs r2, #0x80000000 ");			// if carry, mantissa=800000
	asm("addcs r12, r12, #1 ");				// and increment exponent
	asm("cmpmi r12, #1 ");					// if mantissa normalised, check exponent>0
	asm("movmi r12, #1 ");					// if normalised and exponent=0, set exponent to 1
	asm("TReal64GetTReal32c: ");			// come here to truncate
	asm("and r0, r0, #0x80000000 ");		// leave only sign bit in r0
	asm("orr r0, r0, r12, lsl #23 ");		// exponent into r0 bits 23-30
	asm("bic r2, r2, #0x80000000 ");		// remove integer bit from mantissa
	asm("orr r0, r0, r2, lsr #8 ");			// non-integer mantissa bits into r0 bits 0-22
	asm("cmp r12, #0xFF ");					// check for overflow
	asm("mvneq r12, #8 ");					// if overflow, return KErrOverflow
	asm("biceq pc, lr, #3 ");
	asm("bics r1, r0, #0x80000000 ");		// check for underflow
	asm("mvneq r12, #9 ");					// if underflow return KErrUnderflow
	asm("movne r12, #0 ");					// else return KErrNone
	asm("bic pc, lr, #3 ");
	asm("TReal64GetTReal32a: ");			// come here if overflow, infinity or NaN
	asm("add r3, r12, #1 ");
	asm("cmp r3, #0x480 ");					// check for infinity or NaN
	asm("movne r1, #0 ");					// if not, set mantissa to 0 for infinity result
	asm("movne r0, r0, lsr #20 ");
	asm("movne r0, r0, lsl #20 ");
	asm("mov r1, r1, lsr #29 ");			// assemble 23 bit mantissa in r1
	asm("orr r1, r1, r0, lsl #3 ");
	asm("bic r1, r1, #0xFF000000 ");
	asm("and r0, r0, #0x80000000 ");		// leave only sign in r0
	asm("orr r0, r0, #0x7F000000 ");		// r0 bits 23-30 = FF = exponent
	asm("orr r0, r0, #0x00800000 ");
	asm("orr r0, r0, r1 ");					// r0 bits 0-22 = result mantissa
	asm("movs r12, r0, lsl #9 ");			// check if result is infinity or NaN
	asm("mvneq r12, #8 ");					// if infinity return KErrOverflow
	asm("mvnne r12, #5 ");					// else return KErrArgument
	asm("bic pc, lr, #3 ");
    }
}	// end of extern "C" declaration
#endif
#endif