kernel/eka/common/arm/cdes8.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\common\arm\cdes8.cia
// 
//

#include <e32cia.h>
#include "../common.h"

#define __FIXED_POINT_64BIT_DIV10__

#if defined(__DES8_MACHINE_CODED__) || defined(__EABI__)

GLREF_C void Des8PanicBadDesType();
GLREF_C void Des8PanicPosOutOfRange();

#endif

#ifdef __DES8_MACHINE_CODED__

GLREF_C void Des8PanicLengthNegative();
GLREF_C void Des8PanicMaxLengthNegative();
GLREF_C void Des8PanicLengthOutOfRange();
GLREF_C void Des8PanicDesOverflow();
GLREF_C void Des8PanicDesIndexOutOfRange();

__NAKED__ EXPORT_C const TUint8 *TDesC8::Ptr() const
//
// Return a pointer to the buffer.
//
	{
	asm("ldr r1, [r0], #4 ");
	asm("cmp r1, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("eor r1, r1, r1, lsr #1 ");
	asm("msr cpsr_flg, r1 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("addeq r0, r0, #4 ");
	__JUMP(,lr);
	}

#ifndef __EABI_CTORS__
__NAKED__ EXPORT_C TPtrC8::TPtrC8()
//
// Default constructor
//
	{
	asm("mov r1, #0x10000000 ");	// type=EPtrC, length=0
	asm("mov r2, #0 ");				// ptr=NULL
	asm("stmia r0, {r1,r2} ");
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TPtrC8::TPtrC8(const TDesC8& /*aDes*/)
//
// Constructor
//
	{
	asm("ldr r2, [r1], #4 ");		// r2 = type/length
	asm("bic r3, r2, #0xF0000000");	// r3 = length
	asm("orr r3, r3, #0x10000000");	// r3 = EPtrC + length
	asm("cmp r2, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("eor r2, r2, r2, lsr #1 ");
	asm("msr cpsr_flg, r2 ");
	asm("addcs r1, r1, #4 ");
	asm("ldrle r1, [r1] ");
	asm("addeq r1, r1, #4 ");		// r1 = aDes.Ptr()
	asm("str r3, [r0] ");
	asm("str r1, [r0, #4] ");
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TPtrC8::TPtrC8(const TUint8* /*aString*/)
//
// Constructor
//
	{
	asm("mov r2, r1 ");				// save aString pointer
	asm("1: ");
	asm("ldrb r3, [r1], #1 ");
	asm("cmp r3, #0 ");
	asm("bne 1b ");					// loop until we reach zero terminator
	asm("sub r1, r1, r2 ");			// r1 = length + 1
	asm("sub r1, r1, #1 ");			// r1 = length
	asm("orr r1, r1, #0x10000000 ");	// r1=EPtrC + length
	asm("stmia r0, {r1, r2} ");		// store type/length and ptr fields
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TPtrC8::TPtrC8(const TUint8* /*aBuf*/,TInt /*aLength*/)
//
// Constructor
//
	{
	asm("orrs r2, r2, #0x10000000 ");
	asm("strpl r2, [r0] ");
	asm("strpl r1, [r0, #4] ");
	__JUMP(pl,lr);
	asm("b  " CSM_Z23Des8PanicLengthNegativev);
	}

__NAKED__ EXPORT_C TPtr8::TPtr8(TUint8* /*aBuf*/,TInt /*aMaxLength*/)
//
// Constructor
//
	{
	asm("cmp r2, #0 ");
	asm("movpl r3, r1 ");
	asm("movpl r1, #0x20000000 ");	// length=0, EPtr
	asm("stmplia r0, {r1,r2,r3} ");
	__JUMP(pl,lr);
	asm("b  " CSM_Z26Des8PanicMaxLengthNegativev);
	}

__NAKED__ EXPORT_C TPtr8::TPtr8(TUint8* /*aBuf*/,TInt /*aLength*/,TInt /*aMaxLength*/)
//
// Constructor
//
	{
	asm("cmp r2, #0 ");				// check length>=0
	asm("cmpge r3, r2 ");			// if so, check maxlength>=length
	asm("movge r12, r1 ");
	asm("orrge r2, r2, #0x20000000 ");	// r2 = length + EPtr
	asm("stmgeia r0, {r2,r3,r12} ");
	__JUMP(ge,lr);
	asm("cmp r2, #0 ");
	asm("bmi  " CSM_Z23Des8PanicLengthNegativev);
	asm("cmp r3, #0 ");
	asm("bmi  " CSM_Z26Des8PanicMaxLengthNegativev);
	asm("b  " CSM_Z25Des8PanicLengthOutOfRangev);
	}

__NAKED__ EXPORT_C TPtr8::TPtr8(TBufCBase8& /*aLcb*/,TInt /*aMaxLength*/)
//
// Constructor
//
	{
	asm("mov r3, r1 ");
	asm("ldr r1, [r3] ");
	asm("bic r1, r1, #0xF0000000 ");		// r1=aLcb.Length()
	asm("cmp r1, r2 ");						// check against maxlength
	asm("orrle r1, r1, #0x40000000 ");		// r1=aLcb.Length() + EBufCPtr
	asm("stmleia r0, {r1,r2,r3} ");
	__JUMP(le,lr);
	asm("b  " CSM_Z25Des8PanicLengthOutOfRangev);
	}

__NAKED__ EXPORT_C TBufCBase8::TBufCBase8()
//
// Constructor
//
	{
	asm("mov r1, #0 ");
	asm("str r1, [r0] ");
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TBufCBase8::TBufCBase8(const TUint8* /*aString*/,TInt /*aMaxLength*/)
//
// Constructor
//
	{
	asm("mov r3, r1 ");					// save aString pointer
	asm("1: ");
	asm("ldrb r12, [r3], #1 ");
	asm("cmp r12, #0 ");
	asm("bne 1b ");						// loop until we reach zero terminator
	asm("sub r3, r3, r1 ");				// r3 = length + 1
	asm("sub r3, r3, #1 ");				// r3 = length (+EBufC)
	asm("cmp r3, r2 ");					// check against max length
	asm("bgt  " CSM_Z25Des8PanicLengthOutOfRangev);
	asm("stmfd sp!, {r0,lr} ");			// save registers for function call
	asm("str r3, [r0], #4 ");			// save length/type field, r0->buffer
	asm("mov r2, r3 ");					// length into r2 for function call
	asm("bl memmove ");
	__POPRET("r0,");
	}

__NAKED__ EXPORT_C TBufCBase8::TBufCBase8(const TDesC8& /*aDes*/,TInt /*aMaxLength*/)
//
// Constructor
//
	{
	asm("ldr r3, [r1], #4 ");			// r3 = type/length
	asm("bic r12, r3, #0xF0000000");	// r12 = length
	asm("cmp r12, r2 ");				// compare with maxlength
	asm("bgt  " CSM_Z25Des8PanicLengthOutOfRangev);
	asm("cmp r3, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r1, r1, #4 ");
	asm("ldrle r1, [r1] ");
	asm("addeq r1, r1, #4 ");			// r1 = aDes.Ptr()
	asm("stmfd sp!, {r0,lr} ");			// save registers for function call
	asm("str r12, [r0], #4 ");			// store length/type, r0->buffer
	asm("mov r2, r12 ");				// length into r2 for function call
	asm("bl memmove ");
	__POPRET("r0,");
	}
#endif

__NAKED__ EXPORT_C void TBufCBase8::Copy(const TUint8* /*aString*/,TInt /*aMaxLength*/)
//
// Copy from a string.
//
	{
	asm("mov r3, r1 ");					// save aString pointer
	asm("1: ");
	asm("ldrb r12, [r3], #1 ");
	asm("cmp r12, #0 ");
	asm("bne 1b ");						// loop until we reach zero terminator
	asm("sub r3, r3, r1 ");				// r3 = length + 1
	asm("sub r3, r3, #1 ");				// r3 = length (+EBufC)
	asm("cmp r3, r2 ");					// check against max length
	asm("bgt  " CSM_Z25Des8PanicLengthOutOfRangev);
	asm("str r3, [r0], #4 ");			// save length/type field, r0->buffer
	asm("mov r2, r3	");					// length into r2 for function call
	asm("b memmove ");
	}

__NAKED__ EXPORT_C void TBufCBase8::Copy(const TDesC8& /*aDes*/,TInt /*aMaxLength*/)
//
// Copy from a descriptor.
//
	{
	asm("ldr r3, [r1], #4 ");			// r3 = type/length
	asm("bic r12, r3, #0xF0000000");	// r12 = length
	asm("cmp r12, r2 ");				// compare with maxlength
	asm("bgt  " CSM_Z20Des8PanicDesOverflowv);
	asm("cmp r3, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r1, r1, #4 ");
	asm("ldrle r1, [r1] ");
	asm("addeq r1, r1, #4 ");			// r1 = aDes.Ptr()
	asm("str r12, [r0], #4 ");			// store length/type, r0->buffer
	asm("mov r2, r12 ");				// length into r2 for function call
	asm("b memmove ");
	}

#ifndef __EABI_CTORS__
__NAKED__ EXPORT_C TBufBase8::TBufBase8(TInt /*aMaxLength*/)
	{
	asm("mov r2, #0x30000000 ");		// EBuf + zero length
	asm("str r2, [r0] ");
	asm("str r1, [r0, #4] ");
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TBufBase8::TBufBase8(TInt /*aLength*/, TInt /*aMaxLength*/)
	{
	asm("cmp r1, #0 ");					// check length>=0
	asm("cmpge r2, r1 ");				// if so, check maxlength>=length
	asm("orrge r1, r1, #0x30000000 ");	// r1=length + EBuf
	asm("stmgeia r0, {r1,r2} ");		// store length/type and maxlength fields
	__JUMP(ge,lr);
	asm("cmp r2, #0 ");
	asm("bmi  " CSM_Z26Des8PanicMaxLengthNegativev);
	asm("b  " CSM_Z25Des8PanicLengthOutOfRangev);
	}

__NAKED__ EXPORT_C TBufBase8::TBufBase8(const TUint8* /*aString*/, TInt /*aMaxLength*/)
	{
	asm("mov r12, r1 ");				// save aString pointer
	asm("1: ");
	asm("ldrb r3, [r1], #1 ");
	asm("cmp r3, #0 ");
	asm("bne 1b ");						// loop until we reach zero terminator
	asm("sub r1, r1, r12 ");			// r1 = length + 1
	asm("sub r1, r1, #1 ");				// r1 = length
	asm("cmp r1, r2 ");					// compare to max length
	asm("bgt  " CSM_Z25Des8PanicLengthOutOfRangev);	// length too big, so panic
	asm("orr r1, r1, #0x30000000 ");	// if length<=max, r1=EBuf + length
	asm("stmfd sp!, {r0,lr} ");			// save registers for function call
	asm("stmia r0!, {r1, r2} ");		// store type/length and max length fields, r0->buffer
	asm("bic r2, r1, #0xf0000000 ");	// r2=length
	asm("mov r1, r12 ");				// r12=aString
	asm("bl memmove ");
	__POPRET("r0,");
	}

__NAKED__ EXPORT_C TBufBase8::TBufBase8(const TDesC8& /*aDes*/, TInt /*aMaxLength*/)
	{
	asm("ldr r3, [r1], #4 ");		// r3 = type/length
	asm("bic r12, r3, #0xF0000000");	// r12 = length
	asm("cmp r12, r2 ");				// compare with maxlength
	asm("bgt  " CSM_Z25Des8PanicLengthOutOfRangev);
	asm("cmp r3, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r1, r1, #4 ");
	asm("ldrle r1, [r1] ");
	asm("addeq r1, r1, #4 ");		// r1 = aDes.Ptr()
	asm("stmfd sp!, {r0,lr} ");		// save registers for function call
	asm("orr r12, r12, #0x30000000 ");	// add EBuf type field
	asm("str r12, [r0], #4 ");		// store length/type, r0->max length
	asm("str r2, [r0], #4 ");		// store max length, r0->buffer
	asm("bic r2, r12, #0xf0000000 ");	// length into r2 for function call
	asm("bl memmove ");
	__POPRET("r0,");
	}
#endif

__NAKED__ EXPORT_C void TDes8::SetLength(TInt /*aLength*/)
//
// Set the length of the descriptor, checking the length is O.K.
//
	{
	asm("ldmia r0, {r2,r3} ");			// r2=length/type, r3=maxlength
	asm("cmp r1, r3 ");					// check aLength against maxlength and for -ve values
	asm("bhi  " CSM_Z20Des8PanicDesOverflowv);
	asm("and r2, r2, #0xF0000000 ");	// r2=type field
	asm("cmp r2, #0x40000000 ");		// check for EBufCPtr
	asm("orr r2, r2, r1 ");				// r2=type + new length
	asm("str r2, [r0] ");				// store new length
	__JUMP(ne,lr);
	asm("ldr r2, [r0, #8] ");			// r2=pointer to TBufCBase
	asm("str r1, [r2] ");				// update length of TBufCBase
	__JUMP(,lr);
  	}

__NAKED__ EXPORT_C void TDes8::SetMax()
//
// Set the length to MaxLength().
//
	{
	asm("ldmia r0, {r1,r2} ");			// r1=length/type, r2=maxlength
	asm("and r1, r1, #0xF0000000 ");	// r1=type field
	asm("cmp r1, #0x40000000 ");		// check for EBufCPtr
	asm("orr r1, r1, r2 ");				// r1=type field + maxlength
	asm("str r1, [r0] ");				// store new length
	__JUMP(ne,lr);
	asm("ldr r1, [r0, #8] ");			// r1 = pointer to TBufCBase
	asm("str r2, [r1] ");				// update length of TBufCBase
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C void TDes8::Copy(const TUint8* /*aString*/)
//
// Copy a string to this descriptor.
//
	{
	asm("mov r2, r1 ");					// r2=aString
	asm("1: ");
	asm("ldrb r3, [r2], #1 ");
	asm("cmp r3, #0 ");
	asm("bne 1b ");						// loop until zero terminator reached
	asm("sub r2, r2, r1 ");
	asm("sub r2, r2, #1 ");				// r2=length of string
	asm("ldmia r0, {r3,r12} ");			// r3=type/length of this, r12=maxlength
	asm("cmp r2, r12 ");				// compare new length against maxlength
	asm("bgt  " CSM_Z20Des8PanicDesOverflowv);
	asm("cmp r3, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("and r3, r3, #0xF0000000 ");	// r3=type of this
	asm("orr r3, r3, r2 ");				// r3=new type/length
	asm("str r3, [r0], #4 ");			// store it
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("streq r2, [r0], #4 ");			// if EBufCPtr, update length of TBufCBase, r0=Ptr()
	asm("b memmove ");
	}

__NAKED__ EXPORT_C void TDes8::Copy(const TUint8* /*aBuf*/,TInt /*aLength*/)
//
// Copy the aLength characters to the descriptor.
//
	{
	asm("ldmia r0, {r3,r12} ");			// r3=type/length of this, r12=maxlength
	asm("cmp r2, r12 ");				// compare new length against maxlength
	asm("bhi  " CSM_Z20Des8PanicDesOverflowv);	// Des8Panic if >MaxLength or -ve
	asm("cmp r3, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("and r3, r3, #0xF0000000 ");	// r3=type of this
	asm("orr r3, r3, r2 ");				// r3=new type/length
	asm("str r3, [r0], #4 ");			// store it
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("streq r2, [r0], #4 ");			// if EBufCPtr, update length of TBufCBase, r0=Ptr()
	asm("b memmove ");
	}

__NAKED__ EXPORT_C void TDes8::Copy(const TDesC8& /*aDes*/)
//
// Copy a descriptor to this descriptor.
//
	{
	asm("ldr r3, [r1], #4 ");			// r3 = type/length of aDes
	asm("bic r12, r3, #0xF0000000");	// r12 = aDes.length
	asm("ldr r2, [r0, #4] ");			// r2=this.maxlength
	asm("cmp r12, r2 ");				// compare with maxlength
	asm("bgt  " CSM_Z20Des8PanicDesOverflowv);
	asm("ldr r2, [r0] ");				// get type of this
	asm("cmp r2, #0x50000000 ");		// check both descriptor types
	asm("cmpcc r3, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("and r2, r2, #0xF0000000 ");
	asm("orr r2, r12, r2 ");			// r2=new type/length of this
	asm("str r2, [r0], #4 ");			// store it
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r1, r1, #4 ");
	asm("ldrle r1, [r1] ");
	asm("addeq r1, r1, #4 ");			// r1 = aDes.Ptr()
	asm("eor r2, r2, r2, lsr #1 ");
	asm("msr cpsr_flg, r2 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("streq r12, [r0], #4 ");		// if EBufCPtr, update length of TBufCBase, r0=Ptr()
	asm("mov r2, r12 ");				// length into r2 for function call
	asm("b memmove ");
	}

#ifndef __KERNEL_MODE__
__NAKED__ EXPORT_C TPtr8 TDes8::LeftTPtr(TInt /*aLength*/) const
//
// Extract the left portion of the descriptor.
//
	{
	// On entry r0=return store ptr, r1=this, r2=aLength
	// Return TPtr8 ([r0]=length/type,[r0,#4]=maxLength,[r0,#8]=Ptr)
	asm("ldr r3, [r1], #4 ");				// r3=this.length/type
	asm("cmp r2, #0 ");						// check aLength>=0
	asm("blt Des8PanicPosOutOfRange__Fv ");	// if not panic
	asm("bic r12, r3, #0xF0000000 ");		// r12=this.Length()
	asm("cmp r2, r12 ");					// limit aLength to Length()
	asm("movgt r2, r12 ");
	asm("cmp r3, #0x50000000 ");			// check type() <= 4
	asm("bcs Des8PanicBadDesType__Fv ");	// if not, panic
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r1, r1, #4 ");
	asm("ldrle r1, [r1] ");
	asm("addeq r1, r1, #4 ");				// r1=this.Ptr()
	asm("mov r3, r1 ");						// r3=this.Ptr()
	asm("orr r1, r2, #0x20000000 ");		// r1=aLength + EPtr
	asm("stmia r0, {r1-r3} ");				
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TPtr8 TDes8::RightTPtr(TInt /*aLength*/) const
//
// Extract the right portion of the descriptor.
//
	{
	// On entry r0=return store ptr, r1=this, r2=aLength
	// Return TPtr8 ([r0]=length/type,[r0,#4]=maxLength,[r0,#8]=Ptr)
	asm("ldr r3, [r1], #4 ");				// r3=this.length/type
	asm("cmp r2, #0 ");						// check aLength>=0
	asm("blt Des8PanicPosOutOfRange__Fv ");	// if not, panic
	asm("bic r12, r3, #0xF0000000 ");		// r12=this.Length()
	asm("cmp r2, r12 ");					// limit aLength to Length()
	asm("movgt r2, r12 ");
	asm("cmp r3, #0x50000000 ");			// check type() <= 4
	asm("bcs Des8PanicBadDesType__Fv ");
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r1, r1, #4 ");
	asm("ldrle r1, [r1] ");
	asm("addeq r1, r1, #4 ");				// r1=this.Ptr()
	asm("add r3, r1, r12 ");				// r3=this.Ptr()+Length()
	asm("orr r1, r2, #0x20000000 ");		// r1=aLength + EPtr
	asm("sub r3, r3, r2 ");					// r3=Ptr()+Length()-aLength
	asm("stmia r0, {r1-r3} ");
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TPtr8 TDes8::MidTPtr(TInt /*aPos*/) const
//
// Extract the middle portion of the descriptor.
//
	{
	// On entry r0=return store ptr, r1=this, r2=aPos
	// Return TPtr8 ([r0]=length/type,[r0,#4]=maxLength,[r0,#8]=Ptr)
	asm("ldr r3, [r1], #4 ");				// r3=this.length/type
	asm("bic r12, r3, #0xF0000000 ");		// r12=this.Length()
	asm("cmp r2, #0 ");						// check aPos>=0
	asm("cmpge r12, r2 ");					// if so check Length()>=aPos
	asm("blt Des8PanicPosOutOfRange__Fv ");
	asm("cmp r3, #0x50000000 ");			// check type() <= 4
	asm("bcs Des8PanicBadDesType__Fv ");
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r1, r1, #4 ");
	asm("ldrle r1, [r1] ");
	asm("addeq r1, r1, #4 ");				// r1=this.Ptr()
	asm("add r3, r1, r2 ");					// r3=this.Ptr()+aPos
	asm("sub r2, r12, r2 ");				// r2=Length()-aPos (=newMaxLen)
	asm("orr r1, r2, #0x20000000 ");		// r1=Length()-aPos + EPtr (=newLen/Type)
	asm("stmia r0, {r1-r3} ");
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TPtr8 TDes8::MidTPtr(TInt /*aPos*/,TInt /*aLength*/) const
//
// Extract the middle portion of the descriptor.
//
	{
	// On entry r0=return store ptr, r1=this, r2=aPos, r3=aLength
	// Return TPtr8 ([r0]=length/type,[r0,#4]=maxLength,[r0,#8]=Ptr)
	asm("str r4, [sp, #-4]! ");				// save r4
	asm("ldr r12, [r1], #4 ");				// r12=this.length/type
	asm("mov r4, r1 ");
	asm("cmp r12, #0x50000000 ");			// check valid descriptor type
	asm("bcs Des8PanicBadDesType__Fv ");
	asm("eor r12, r12, r12, lsr #1 ");
	asm("msr cpsr_flg, r12 ");
	asm("ldr r12, [r1, #-4] ");
	asm("addcs r4, r4, #4 ");
	asm("ldrle r4, [r4] ");
	asm("bic r12, r12, #0xF0000000 ");		// r12=Length()
	asm("addeq r4, r4, #4 ");				// r4=this.Ptr()
	asm("cmp r2, #0 ");						// check aPos>=0
	asm("subge r12, r12, r2 ");				// if so, r12=Length()-aPos
	asm("cmpge r12, r3 ");					// and check Length()-aPos>=aLength
	asm("orrge r1, r3, #0x20000000 ");		// if so, r1=aLength + EPtr
	asm("addge r3, r4, r2 ");				// and r3=this.Ptr()+aPos
	asm("bicge r2, r1, #0xF0000000 ");		// and r2=aLength
	asm("stmgeia r0, {r1-r3} ");
	asm("ldrge r4, [sp], #4 ");
	__JUMP(ge,lr);
	asm("b Des8PanicPosOutOfRange__Fv ");
	}
#endif

__NAKED__ EXPORT_C const TUint8 &TDesC8::AtC(TInt /*anIndex*/) const
//
// Return a reference to the character in the buffer.
//
	{
	asm("ldr r2, [r0], #4 ");			// r2=length/type
	asm("bic r3, r2, #0xF0000000 ");	// r3=length
	asm("cmp r2, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("eor r2, r2, r2, lsr #1 ");
	asm("msr cpsr_flg, r2 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("addeq r0, r0, #4 ");			// r0=this.Ptr()
	asm("cmp r1, #0 ");					// check index>=0
	asm("cmpge r3, r1 ");				// if so, check Length()>index
	asm("addgt r0, r0, r1 ");			// return value = this.Ptr()+index
	__JUMP(gt,lr);
	asm("b  " CSM_Z27Des8PanicDesIndexOutOfRangev);
	}

__NAKED__ EXPORT_C TInt TDesC8::Locate(TChar /*aChar*/) const
//
// Locate character aChar in the descriptor.
//
	{
	asm("ldr r2, [r0], #4 ");			// r2=length/type
	asm("cmp r2, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("bics r3, r2, #0xF0000000 ");	// r3=length
	asm("mvneq r0, #0 ");				// if length=0, not found
	__JUMP(eq,lr);
	asm("eor r2, r2, r2, lsr #1 ");
	asm("msr cpsr_flg, r2 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("addeq r0, r0, #4 ");			// r0=this.Ptr()
	asm("add r3, r3, r0 ");				// r3=ptr+length
	asm("add r12, r0, #1 ");			// r12=ptr+1
	asm("1: ");
	asm("ldrb r2, [r0], #1 ");			// r2=*r0++
	asm("cmp r1, r2 ");					// is r1=match char?
	asm("cmpne r0, r3 ");				// if not, is r0=r3 (end pointer)
	asm("bne 1b ");
	asm("cmp r1, r2 ");					// did we find char?
	asm("subeq r0, r0, r12 ");			// if we did, return value = r0-ptr-1
	asm("mvnne r0, #0 ");				// else return value =-1
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TInt TDesC8::LocateReverse(TChar /*aChar*/) const
//
// Locate character aChar in the descriptor in reverse.
//
	{
	asm("ldr r2, [r0], #4 ");			// r2=length/type
	asm("cmp r2, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("bics r3, r2, #0xF0000000 ");	// r3=length
	asm("mvneq r0, #0 ");				// if length=0, not found
	__JUMP(eq,lr);
	asm("eor r2, r2, r2, lsr #1 ");
	asm("msr cpsr_flg, r2 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("addeq r0, r0, #4 ");			// r0=this.Ptr()
	asm("sub r0, r0, #1 ");				// r0=Ptr-1
	asm("1: ");
	asm("ldrb r2, [r0, r3] ");			// r2=Ptr[r3-1]
	asm("cmp r1, r2 ");					// is r1=match char?
	asm("subnes r3, r3, #1 ");			// if not, decrement char count
	asm("bne 1b ");
	asm("cmp r1, r2 ");					// did we find match char?
	asm("subeq r0, r3, #1 ");			// if we did, return value = r3-1
	asm("mvnne r0, #0 ");				// else return value =-1
	__JUMP(,lr);
	}

#ifndef __KERNEL_MODE__
__NAKED__ EXPORT_C TInt TDesC8::CompareF(const TDesC8& /*aDes*/) const
//
// Compare a descriptor to this descriptor folded.
//
	{
	asm("ldr r12, 1f ");
	asm("b comparebody ");
	asm("1: ");
	asm(".word  " CSM_ZN3Mem8CompareFEPKhiS0_i);
	}

__NAKED__ EXPORT_C TInt TDesC8::CompareC(const TDesC8& /*aDes*/) const
//
// Compare a descriptor to this descriptor collated.
//
	{
	asm("ldr r12, 1f ");
	asm("b comparebody ");
	asm("1: ");
	asm(".word  " CSM_ZN3Mem8CompareCEPKhiS0_i);
	}
#endif

__NAKED__ EXPORT_C TInt TDesC8::Compare(const TDesC8& /*aDes*/) const
//
// Compare a descriptor to this descriptor.
//
	{
	asm("ldr r12, 1f ");
	asm("comparebody: ");
	asm("mov r2, r1 ");						// r2=&aDes
	asm("ldr r3, [r0], #4 ");				// r3=this.length/type
	asm("cmp r3, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("bic r1, r3, #0xF0000000 ");		// r1=this.Length()
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("addeq r0, r0, #4 ");				// r0=this.Ptr()
	asm("ldr r3, [r2], #4 ");				// r3=aDes.length/type
	asm("cmp r3, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("ldr r3, [r2, #-4] ");
	asm("bic r3, r3, #0xF0000000 ");		// r3=aDes.Length()
	asm("addcs r2, r2, #4 ");
	asm("ldrle r2, [r2] ");
	asm("addeq r2, r2, #4 ");				// r2=aDes.Ptr()
	__JUMP(,r12);
	
	asm("1: ");
	asm(".word memcompare ");
	}
#endif // __DES8_MACHINE_CODED__

#if defined(__DES8_MACHINE_CODED__) && !defined(__EABI__)
__NAKED__ EXPORT_C TPtrC8 TDesC8::Left(TInt /*aLength*/) const
//
// Extract the left portion of the descriptor.
//
	{
	// On entry r0=this, r1=aLength
	// Return TPtrC8 in r0,r1
	asm("ldr r3, [r0], #4 ");				// r3=this.length/type
	asm("bic r12, r3, #0xF0000000 ");		// r12=this.Length()
	asm("cmp r1, #0 ");						// check aLength>=0
	asm("blt  " CSM_Z22Des8PanicPosOutOfRangev);	// if not panic
	asm("cmp r1, r12 ");					// else limit aLength to Length()
	asm("movgt r1, r12 ");
	asm("cmp r3, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("addeq r0, r0, #4 ");				// r0=this.Ptr()
	asm("orr r2, r1, #0x10000000 ");		// r2=aLength + EPtrC
	asm("mov r1, r0 ");						// r1=result ptr
	asm("mov r0, r2 ");						// r0=result type/length
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TPtrC8 TDesC8::Right(TInt /*aLength*/) const
//
// Extract the right portion of the descriptor.
//
	{
	// On entry r0=this, r1=aLength
	// Return TPtrC8 in r0,r1
	asm("ldr r3, [r0], #4 ");				// r3=this.length/type
	asm("bic r12, r3, #0xF0000000 ");		// r12=this.Length()
	asm("cmp r1, #0 ");						// check aLength>=0
	asm("blt  " CSM_Z22Des8PanicPosOutOfRangev);	// if not, panic
	asm("cmp r1, r12 ");					// else limit aLength to Length()
	asm("movgt r1, r12 ");
	asm("cmp r3, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("addeq r0, r0, #4 ");				// r0=this.Ptr()
	asm("add r3, r0, r12 ");				// r3=this.Ptr()+len
	asm("orr r0, r1, #0x10000000 ");		// r0=aLength + EPtrC
	asm("sub r1, r3, r1 ");					// r1=Ptr()+len-aLength
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TPtrC8 TDesC8::Mid(TInt /*aPos*/) const
//
// Extract the middle portion of the descriptor.
//
	{
	// On entry r0=this, r1=aPos
	// Return TPtrC8 in r0,r1
	asm("ldr r3, [r0], #4 ");				// r3=this.length/type
	asm("bic r12, r3, #0xF0000000 ");		// r12=this.Length()
	asm("cmp r1, #0 ");						// check aPos>=0
	asm("cmpge r12, r1 ");					// if so check Length()>=aPos
	asm("blt  " CSM_Z22Des8PanicPosOutOfRangev);
	asm("cmp r3, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("addeq r0, r0, #4 ");				// r0=this.Ptr()
	asm("sub r2, r12, r1 ");				// r2=len-aPos
	asm("add r1, r0, r1 ");					// r1=this.Ptr()+aPos
	asm("orr r0, r2, #0x10000000 ");		// r0=aLength + EPtrC
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TPtrC8 TDesC8::Mid(TInt /*aPos*/,TInt /*aLength*/) const
//
// Extract the middle portion of the descriptor.
//
	{
	// On entry r0=this, r1=aPos, r2=aLength
	// Return TPtrC8 in r0,r1
	asm("ldr r12, [r0], #4 ");				// r12=this.length/type
	asm("cmp r12, #0x50000000 ");			// check valid descriptor type
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("eor r12, r12, r12, lsr #1 ");
	asm("msr cpsr_flg, r12 ");
	asm("ldr r12, [r0, #-4] ");
	asm("bic r12, r12, #0xF0000000 ");		// r12=Length()
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("addeq r0, r0, #4 ");				// r0=this.Ptr()
	asm("cmp r1, #0 ");						// check aPos>=0
	asm("subge r12, r12, r1 ");				// if so, r12=Length()-aPos
	asm("cmpge r12, r2 ");					// and check Length()-aPos>=aLength
	asm("addge r1, r1, r0 ");				// if so, r1=Ptr()+aPos
	asm("orrge r0, r2, #0x10000000 ");		// and r0 = aLength + EPtrC
	__JUMP(ge,lr);
	asm("b  " CSM_Z22Des8PanicPosOutOfRangev);
	}
#endif // defined(__DES8_MACHINE_CODED__) && !defined(__EABI__)

#ifdef __DES8_MACHINE_CODED__

// Here are the __EABI__ compliant versions of the above
#ifdef __EABI__

__NAKED__ EXPORT_C TPtrC8 TDesC8::Left(TInt /*aLength*/) const
//
// Extract the left portion of the descriptor.
//
	{
	// On entry r0=return store ptr, r1=this, r2=aLength
	// Return TPtrC8 ([r0]=length/type,[r0,#4]=Ptr)
	asm("ldr r3, [r1], #4 ");				// r3=this.length/type
	asm("cmp r2, #0 ");					// check aLength>=0
	asm("blt Des8PanicPosOutOfRange__Fv ");			// if not panic
	asm("bic r12, r3, #0xF0000000 ");			// r12=this.Length()
	asm("cmp r2, r12 ");					// limit aLength to Length()
	asm("movgt r2, r12 ");
	asm("cmp r3, #0x50000000 ");				// check type() <= 4
	asm("bcs Des8PanicBadDesType__Fv ");			// if not, panic
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r1, r1, #4 ");
	asm("ldrle r1, [r1] ");
	asm("addeq r1, r1, #4 ");				// r1=this.Ptr()
	asm("mov r3, r1");					// r3=this.Ptr()
	asm("orr r1, r2, #0x10000000 ");			// r1=aLength + EPtrC
	asm("stmia r0, {r1,r3} ");				
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TPtrC8 TDesC8::Right(TInt /*aLength*/) const
//
// Extract the right portion of the descriptor.
//
	{
	// On entry r0=return store ptr, r1=this, r2=aLength
	// Return TPtrC8 ([r0]=length/type,[r0,#4]=Ptr)
	asm("ldr r3, [r1], #4 ");				// r3=this.length/type
	asm("cmp r2, #0 ");					// check aLength>=0
	asm("blt Des8PanicPosOutOfRange__Fv ");			// if not, panic
	asm("bic r12, r3, #0xF0000000 ");			// r12=this.Length()
	asm("cmp r2, r12 ");					// limit aLength to Length()
	asm("movgt r2, r12 ");
	asm("cmp r3, #0x50000000 ");				// check type() <= 4
	asm("bcs Des8PanicBadDesType__Fv ");
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r1, r1, #4 ");
	asm("ldrle r1, [r1] ");
	asm("addeq r1, r1, #4 ");				// r3=this.Ptr()
	asm("add r3, r1, r12 ");				// r3=this.Ptr()+Length()
	asm("orr r1, r2, #0x10000000 ");			// r1=aLength + EPtrC
	asm("sub r3, r3, r2 ");					// r3=Ptr()+Length()-aLength
	asm("stmia r0, {r1,r3} ");
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TPtrC8 TDesC8::Mid(TInt /*aPos*/) const
//
// Extract the middle portion of the descriptor.
//
	{
	// On entry r0=return store ptr, r1=this, r2=aPos
	// Return TPtrC8 ([r0]=length/type,[r0,#4]=Ptr)
	asm("ldr r3, [r1], #4 ");				// r3=this.length/type
	asm("bic r12, r3, #0xF0000000 ");			// r12=this.Length()
	asm("cmp r2, #0 ");					// check aPos>=0
	asm("cmpge r12, r2 ");					// if so check Length()>=aPos
	asm("blt Des8PanicPosOutOfRange__Fv ");
	asm("cmp r3, #0x50000000 ");				// check type() <= 4
	asm("bcs Des8PanicBadDesType__Fv ");
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r1, r1, #4 ");
	asm("ldrle r1, [r1] ");
	asm("addeq r1, r1, #4 ");				// r1=this.Ptr()
	asm("add r3, r1, r2 ");					// r3=this.Ptr()+aPos
	asm("sub r2, r12, r2 ");				// r2=Length()-aPos (=newMaxLen)
	asm("orr r1, r2, #0x10000000 ");		// r1=Length()-aPos + EPtrC (=newLen/Type)
	asm("stmia r0, {r1,r3} ");
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C TPtrC8 TDesC8::Mid(TInt /*aPos*/,TInt /*aLength*/) const
//
// Extract the middle portion of the descriptor.
//
	{
	// On entry r0=return store ptr, r1=this, r2=aPos, r3=aLength
	// Return TPtrC8 ([r0]=length/type,[r0,#4]=Ptr)
	asm("ldr r12, [r1], #4 ");				// r12=this.length/type
	asm("cmp r12, #0x50000000 ");			// check valid descriptor type
	asm("bcs Des8PanicBadDesType__Fv ");
	asm("eor r12, r12, r12, lsr #1 ");
	asm("msr cpsr_flg, r12 ");
	asm("ldr r12, [r1, #-4] ");
	asm("addcs r1, r1, #4 ");
	asm("ldrle r1, [r1] ");
	asm("bic r12, r12, #0xF0000000 ");			// r12=Length()
	asm("addeq r1, r1, #4 ");				// r1=this.Ptr()
	asm("cmp r2, #0 ");					// check aPos>=0
	asm("subge r12, r12, r2 ");				// if so, r12=Length()-aPos
	asm("cmpge r12, r3 ");					// and check Length()-aPos>=aLength
	asm("addge r2, r1, r2 ");				// if so r2=this.Ptr()+aPos
	asm("orrge r1, r3, #0x10000000 ");			// and r1=aLength + EPtrC
	asm("stmgeia r0, {r1,r2} ");
	__JUMP(ge,lr);
	asm("b Des8PanicPosOutOfRange__Fv ");
	}
#endif

__NAKED__ EXPORT_C void TDes8::Zero()
//
// Zero the buffer.
//
	{
	asm("ldr r1, [r0] ");				// r1=length/type
	asm("and r1, r1, #0xF0000000 ");	// r1=type field, zero length
	asm("cmp r1, #0x40000000 ");		// check for EBufCPtr
	asm("str r1, [r0] ");				// store zero length
	__JUMP(ne,lr);
	asm("ldr r2, [r0, #8] ");			// r2 = pointer to TBufCBase
	asm("mov r1, #0 ");
	asm("str r1, [r2] ");				// update length of TBufCBase
	__JUMP(,lr);
	}

#ifndef __KERNEL_MODE__
__NAKED__ EXPORT_C void TDes8::ZeroTerminate()
//
// Zero terminate at Length().
//
	{
	// Fall through to PtrZ below...
	}

__NAKED__ EXPORT_C const TUint8 *TDes8::PtrZ()
//
// Return a pointer to a 0 terminated string.
//
	{
	asm("ldmia r0, {r1,r2} ");			// r1=length/type, r2=maxlength
	asm("bic r3, r1, #0xF0000000 ");	// r3=Length();
	asm("cmp r3, r2 ");					// check Length()<MaxLength()
	asm("bge  " CSM_Z20Des8PanicDesOverflowv);
	asm("cmp r1, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("eor r1, r1, r1, lsr #1 ");
	asm("msr cpsr_flg, r1 ");
	asm("add r0, r0, #4 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("addeq r0, r0, #4 ");			// r0=Ptr()
	asm("mov r2, #0 ");
	asm("strb r2, [r0, r3] ");			// Ptr()[Length()]=0;
	__JUMP(,lr);
	}
#endif

__NAKED__ EXPORT_C void TDes8::Append(TChar /*aChar*/)
//
// Add a character at the end of the string.
//
	{
	asm("ldmia r0, {r2,r3} ");			// r2=length/type, r3=maxlength
	asm("bic r12, r2, #0xF0000000 ");	// r12=Length();
	asm("cmp r12, r3 ");				// check Length()<MaxLength()
	asm("bge  " CSM_Z20Des8PanicDesOverflowv);
	asm("cmp r2, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("add r2, r2, #1 ");				// increment length by 1
	asm("str r2, [r0] ");				// store new length
	asm("eor r2, r2, r2, lsr #1 ");
	asm("msr cpsr_flg, r2 ");
	asm("add r2, r0, #4 ");				// r2=this+4
	asm("addcs r2, r2, #4 ");
	asm("ldrle r2, [r2] ");
	asm("addeq r3, r12, #1 ");			// if EBufCPtr, r3=Length()+1
	asm("streq r3, [r2], #4 ");			// and update length of TBufCBase, r2=Ptr()
	asm("strb r1, [r2, r12] ");			// Ptr()[Length()]=aChar;
	__JUMP(,lr);
	}

__NAKED__ EXPORT_C void TDes8::Append(const TDesC8& /*aDes*/)
//
// Append a descriptor to this descriptor.
//
	{
	asm("ldr r3, [r1], #4 ");			// r3=aDes.length/type
	asm("cmp r3, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("bics r2, r3, #0xF0000000 ");	// r2=aDes.Length()
	__JUMP(eq,lr);
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("addcs r1, r1, #4 ");
	asm("ldrle r1, [r1] ");
	asm("addeq r1, r1, #4 ");			// r1=aDes.Ptr()
	asm("b appendbody ");	// use following routine for rest of job
	}

__NAKED__ EXPORT_C void TDes8::Append(const TUint8* /*aBuf*/,TInt /*aLength*/)
//
// Append aLength from aBuf characters to the descriptor.
//
	{
	asm("cmp r2, #0 ");					// check aLength>=0
	__JUMP(eq,lr);
	asm("blt  " CSM_Z23Des8PanicLengthNegativev);
	asm("appendbody: ");
	asm("ldmia r0, {r3,r12} ");			// r3=type/length, r12=maxlength
	asm("cmp r3, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("bic r3, r3, #0xF0000000 ");	// r3=Length()
	asm("sub r12, r12, r3 ");			// r12=MaxLength-Length
	asm("cmp r2, r12 ");				// check aLength<=(MaxLength-Length)
	asm("bgt  " CSM_Z20Des8PanicDesOverflowv);
	asm("ldr r12, [r0] ");
	asm("add r12, r12, r2 ");			// new length/type field
	asm("str r12, [r0], #4 ");			// store it
	asm("eor r12, r12, r12, lsr #1 ");
	asm("msr cpsr_flg, r12 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("ldreq r12, [r0] ");			// fetch length from TBufCBase
	asm("addeq r12, r12, r2 ");			// add aLength
	asm("streq r12, [r0], #4 ");		// update length of TBufCBase, r0=Ptr()
	asm("add r0, r0, r3 ");				// r0=Ptr()+Length()
	asm("b memmove ");
	}

__NAKED__ EXPORT_C void TDes8::FillZ()
//
// Fill the descriptor with 0.
//
	{
	asm("ldr r2, [r0] ");				// r2=length/type
	asm("cmp r2, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("bic r1, r2, #0xF0000000 ");	// r1=Length()
	asm("eor r2, r2, r2, lsr #1 ");
	asm("msr cpsr_flg, r2 ");
	asm("add r0, r0, #4 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("addeq r0, r0, #4 ");			// r0=Ptr()
	asm("b memclr ");
	}

__NAKED__ EXPORT_C void TDes8::Fill(TChar /*aChar*/)
//
// Fill the descriptor with aChar.
//
	{
	asm("ldr r3, [r0] ");				// r3=length/type
	asm("cmp r3, #0x50000000 ");
	asm("bcs  " CSM_Z19Des8PanicBadDesTypev);
	asm("bic r2, r3, #0xF0000000 ");	// r2=Length()
	asm("eor r3, r3, r3, lsr #1 ");
	asm("msr cpsr_flg, r3 ");
	asm("add r0, r0, #4 ");
	asm("addcs r0, r0, #4 ");
	asm("ldrle r0, [r0] ");
	asm("addeq r0, r0, #4 ");			// r0=Ptr()
	asm("b memset ");					// memset(Ptr(),aChar,Length())
	}
#endif //__DES8_MACHINE_CODED__

#ifdef __DES_MACHINE_CODED__
__NAKED__ GLDEF_C TInt __DoConvertNum(TUint /*aVal*/, TRadix /*aRadix*/, TUint /*aA*/, TUint8*& /*aDest*/)
	{
	asm("ldr ip, [r3] ");				// ip = aDest
	asm("cmp r1, #16 ");
	asm("beq do_convert_hex ");
	asm("cmp r1, #10 ");
	asm("beq do_convert_dec ");
#ifdef __KERNEL_MODE__
	asm("mov r0, #%a0" : : "i" ((TInt)EInvalidRadix));
	asm("b  " CSM_Z5Panic9TCdtPanic);
#else // !__KERNEL_MODE__
	asm("cmp r1, #2 ");
	asm("beq do_convert_bin ");
	asm("cmp r1, #8 ");
	asm("beq do_convert_oct ");
	asm("do_convert_any: ");
	asm("stmfd sp!, {r4-r8,lr} ");
	asm("mov r5, r1 ");					// save radix
	asm("and r6, r2, #0xff ");
	asm("sub r6, r6, #10 ");			// save aA - 10
	asm("mov r4, ip ");					// r4 = aDest
	asm("mov r7, r3 ");					// save &aDest
	asm("mov r8, r2");					// save aA
	asm("1: ");
	asm("mov r1, r5 ");					// r1 = radix
#ifndef __EABI__
	asm(".extern __umodsi3 ");
	asm("bl __umodsi3 ");				// do division, quotient->r3, rem->r0
	asm("mov r1, r0");					// move to make regs same as EABI function
	asm("mov r0, r3");
#else //__EABI__
	asm(".extern __aeabi_uidivmod ");
	asm("bl __aeabi_uidivmod ");		// do division, quotient->r0, rem->r1
#endif //__EABI__
	asm("cmp r1, #9 ");
	asm("addhi r1, r1, r6 ");			// r1 = (r1 > 9) ? (r1 + (aA - 10)) : r1 + '0'
	asm("addls r1, r1, #0x30 ");
	asm("tst r8, #0x100 ");
	asm("strneh r1, [r4, #-2]! ");		// *--r4 = (TUint16)r1
	asm("streqb r1, [r4, #-1]! ");		// *--r4 = (TUint8)r1
	asm("movs r1, r0 ");				// new aVal into r1
	asm("bne 1b ");
	asm("ldr ip, [r7] ");				// ip can be scratched by __aeabi_uidivmod
	asm("str r4, [r7] ");				// aDest = r4
	asm("sub r0, ip, r4 ");				// return aDest - r4
	__POPRET("r4-r8,");

	asm("do_convert_bin: ");
	asm("mov r2, r2, lsl #22 ");		// aA bit 8 into bit 30
	asm("adds r2, r2, r2 ");			// set V flag = aA bit 8
	asm("1: ");
	asm("movs r0, r0, lsr #1 ");		// aVal>>=1, bit 0 into carry, V unaffected
	asm("mov r1, #0x30 ");				// r1 = '0'
	asm("adc r1, r1, #0 ");				// add in carry
	asm("strvsh r1, [ip, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("strvcb r1, [ip, #-1]! ");		// else store 8 bits
	asm("bne 1b ");						// loop back if aVal still nonzero
	asm("ldr r1, [r3] ");				// r1 = original aDest
	asm("str ip, [r3] ");				// aDest = ip
	asm("sub r0, r1, ip ");				// return aDest - ip
	__JUMP(,lr);

	asm("do_convert_oct: ");
	asm("mov r2, r2, lsl #22 ");		// aA bit 8 into bit 30
	asm("adds r2, r2, r2 ");			// set V flag = aA bit 8
	asm("1: ");
	asm("and r1, r0, #7 ");				// r1 = aVal & 7
	asm("movs r0, r0, lsr #3 ");		// aVal>>=3, set Z accordingly, V unaffected
	asm("add r1, r1, #0x30 ");			// r1 += '0'
	asm("strvsh r1, [ip, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("strvcb r1, [ip, #-1]! ");		// else store 8 bits
	asm("bne 1b ");						// loop back if aVal still nonzero
	asm("ldr r1, [r3] ");				// r1 = original aDest
	asm("str ip, [r3] ");				// aDest = ip
	asm("sub r0, r1, ip ");				// return aDest - ip
	__JUMP(,lr);
#endif //__KERNEL_MODE__

	asm("do_convert_hex: ");
	asm("mov r1, r2, lsl #22 ");		// aA bit 8 into r1 bit 30
	asm("adds r1, r1, r1 ");			// set V flag = aA bit 8
	asm("and r2, r2, #0xff ");
	asm("sub r2, r2, #0x40 ");
	asm("1: ");
	asm("and r1, r0, #15 ");			// r1 = aVal & 15
	asm("add r1, r1, #0x36 ");			// r1 += '0'+6
	asm("tst r1, #0x40 ");
	asm("subeq r1, r1, #6 ");
	asm("addne r1, r1, r2 ");
	asm("movs r0, r0, lsr #4 ");		// aVal>>=4, V unaffected
	asm("strvsh r1, [ip, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("strvcb r1, [ip, #-1]! ");		// else store 8 bits
	asm("bne 1b ");						// loop back if aVal still nonzero
	asm("ldr r1, [r3] ");				// r1 = original aDest
	asm("str ip, [r3] ");				// aDest = ip
	asm("sub r0, r1, ip ");				// return aDest - ip
	__JUMP(,lr);

	asm("do_convert_dec: ");
	asm("and r2, r2, #0x100 ");			// mask all bits of aA except bit 8
	asm("orr r3, r3, r2, lsr #8 ");		// r3 bit 0 = aA bit 8
	asm("1: ");
    asm("sub r1, r0, #10 ");			// divide aVal by 10, r0=quotient, r1=remainder
    asm("sub r0, r0, r0, lsr #2 ");
    asm("add r0, r0, r0, lsr #4 ");
    asm("add r0, r0, r0, lsr #8 ");
    asm("add r0, r0, r0, lsr #16 ");
	asm("mov r0, r0, lsr #3 ");
	asm("add r2, r0, r0, lsl #2 ");
	asm("subs r1, r1, r2, lsl #1 ");
	asm("addpl r0, r0, #1 ");
	asm("addmi r1, r1, #10 ");
	asm("add r1, r1, #0x30 ");			// add '0' to remainder
	asm("tst r3, #1 ");					// test aA bit 8
	asm("strneh r1, [ip, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("streqb r1, [ip, #-1]! ");		// else store 8 bits
	asm("teq r0, #0 ");
	asm("bne 1b ");						// loop back if aVal still nonzero
	asm("bic r3, r3, #1 ");
	asm("ldr r1, [r3] ");				// r1 = original aDest
	asm("str ip, [r3] ");				// aDest = ip
	asm("sub r0, r1, ip ");				// return aDest - ip
	__JUMP(,lr);
	}

__NAKED__ GLDEF_C TInt __DoConvertNum(TUint64 /*aVal*/, TRadix /*aRadix*/, TUint /*aA*/, TUint8*& /*aDest*/)
	{
	asm("ldr ip, [sp] ");				// ip = &aDest
	asm("cmp r2, #16 ");
	asm("beq do_convert_hex64 ");
	asm("cmp r2, #10 ");
	asm("beq do_convert_dec64 ");
#ifdef __KERNEL_MODE__
	asm("mov r0, #%a0" : : "i" ((TInt)EInvalidRadix));
	asm("b  " CSM_Z5Panic9TCdtPanic);
#else // !__KERNEL_MODE__
	asm("cmp r2, #2 ");
	asm("beq do_convert_bin64 ");
	asm("cmp r2, #8 ");
	asm("beq do_convert_oct64 ");
	asm("stmfd sp!, {r4-r8,lr} ");
	asm("ldr r4, [ip] ");				// r4 = aDest
	asm("mov r5, r2 ");					// save radix
	asm("and r6, r3, #0xff ");			// r6 = aA & 0xff
	asm("sub r6, r6, #10 ");			// save a - 10
	asm("mov r7, ip ");					// save &aDest
	asm("mov r8, r3");					// save aA
	asm("teq r1, #0 ");					// aVal > 0xffffffffu
	asm("beq 2f ");
	asm("1: ");
	asm("mov r3, #0 ");
	asm("mov r2, r5 ");					// r3:r2 = radix
#ifndef __EABI__
	asm("stmfd sp!, {r4-r6} ");			// push the registers that are scratched by UDiv01
	asm(".extern UDiv01 ");
	asm("bl UDiv01 ");					// do division, quotient->r5:r4, rem->r6:r3
	asm("mov r0, r4");					// move to make regs same as EABI function
	asm("mov r1, r5");
	asm("mov r2, r3");
	asm("mov r3, r6");
	asm("ldmfd sp!, {r4-r6} ");			// pop the registers that are scratched by UDiv01
#else //__EABI__
	asm(".extern __aeabi_uldivmod ");
	asm("bl __aeabi_uldivmod ");		// do division, quotient->r1:r0, rem->r3:r2
#endif //__EABI__
	asm("cmp r2, #9 ");
	asm("addhi r2, r2, r6 ");			// r2 = (r2>9) ? r2+aA-10 : r2+'0'
	asm("addls r2, r2, #0x30 ");
	asm("tst r8, #0x100 ");
	asm("strneh r2, [r4, #-2]! ");		// *--r4 = (TUint16)r2
	asm("streqb r2, [r4, #-1]! ");		// *--r4 = (TUint8)r2
	asm("teq r1, #0 ");					// new aVal > 0xffffffffu
	asm("bne 1b ");
	asm("2: ");
	asm("mov r2, r8 ");					// r2 = aA
	asm("ldr r1, [r7] ");				// r1 = aDest
	asm("mov r3, r7 ");					// r3 = &aDest
	asm("sub r6, r1, r4 ");				// r6 = aDest - r4
	asm("mov r1, r5 ");					// r1 = radix
	asm("str r4, [r3] ");				// aDest = r4
	asm("mov ip, r4 ");					// ip = aDest
	asm("bl do_convert_any ");
	asm("add r0, r0, r6 ");				// r0 += r6
	__POPRET("r4-r8,");

	asm("do_convert_bin64: ");
	asm("mov r2, ip ");					// r2 = &aDest
	asm("ldr ip, [ip] ");				// ip = aDest
	asm("mov r3, r3, lsl #22 ");		// aA bit 8 into bit 30
	asm("adds r3, r3, r3 ");			// set V flag = aA bit 8
	asm("teq r1, #0 ");					// if (aVal <= 0xffffffffu)
	asm("moveq r1, ip ");				// r1 = orig. aDest in second half
	asm("beq 2f ");						// branch to second half of the loop
	asm("1: ");
	asm("movs r0, r0, lsr #1 ");		// aVal >>= 1, bit 0 into carry, V unaffected
	asm("mov r3, #0x30 ");				// r3 = '0'
	asm("adc r3, r3, #0 ");				// add in carry
	asm("strvsh r3, [ip, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("strvcb r3, [ip, #-1]! ");		// else store 8 bits
	asm("bne 1b ");						// loop back if (aVal & 0xffffffffu) still nonzero
	asm("ldr r0, [r2] ");				// r0 = original aDest
	asm("subvc r0, r0, #32 ");			// r0 = end of buffer for first word (8-bit descriptor)
	asm("subvs r0, r0, #64 ");			// r0 = end of buffer for first word (16-bit descriptor)
	asm("teq ip, r0 ");					// don't pad if we have already emitted 32 bits
	asm("beq finish_bin_zero_pad ");
	asm("bin_zero_pad: ");
	asm("mov r3, #0x30 ");				// r3 = '0'
	asm("bin_zero_pad_loop: ");
	asm("strvsh r3, [ip, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("strvcb r3, [ip, #-1]! ");		// else store 8 bits
	asm("teq ip, r0 ");
	asm("bne bin_zero_pad_loop ");		// loop back if padding not complete
	asm("finish_bin_zero_pad: ");
	asm("addvc r0, r0, #32 ");			// r0 = original aDest
	asm("addvs r0, r0, #64 ");			// r0 = original aDest
	asm("mov r3, r1 ");
	asm("mov r1, r0 ");
	asm("mov r0, r3 ");					// r1 = orig aDest, r0 = aVal >> 32
	asm("2: ");
	asm("movs r0, r0, lsr #1 ");		// aVal >>= 1, bit 0 into carry, V unaffected
	asm("mov r3, #0x30 ");				// r3 = '0'
	asm("adc r3, r3, #0 ");				// add in carry
	asm("strvsh r3, [ip, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("strvcb r3, [ip, #-1]! ");		// else store 8 bits
	asm("bne 2b ");						// loop back if aVal still nonzero
	asm("str ip, [r2] ");				// aDest = ip
	asm("sub r0, r1, ip ");				// return aDest - ip
	__JUMP(,lr);

	asm("do_convert_oct64: ");			// Convert as 31 + 33 bits when > 32 bits
	asm("mov r2, ip ");					// r2 = &aDest
	asm("ldr ip, [ip] ");				// ip = aDest
	asm("mov r3, r3, lsl #22 ");		// aA bit 8 into bit 30
	asm("adds r3, r3, r3 ");			// set V flag = aA bit 8
	asm("teq r1, #0 ");					// if (aVal <= 0xffffffffu)
	asm("moveq r1, ip ");				// r1 = orig. aDest in second half
	asm("beq 3f ");						// branch to second half of the loop
	asm("and r3, r0, #7 ");				// r3 = aVal & 7
	asm("mov r0, r0, lsr #3 ");			// aVal>>=3, set Z accordingly, V unaffected
	asm("orr r0, r0, r1, lsl #29 ");	//  note we now have the bottom 33 bits in r0:r3[2:0]
	asm("ands r0, r0, #0x3fffffff ");	//  and the top 31 bits in r1
	asm("mov r1, r1, lsr #1 ");
	asm("add r3, r3, #0x30 ");			// r3 += '0'
	asm("strvsh r3, [ip, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("strvcb r3, [ip, #-1]! ");		// else store 8 bits
	asm("beq 2f ");
	asm("1: ");
	asm("and r3, r0, #7 ");				// r3 = aVal & 7
	asm("movs r0, r0, lsr #3 ");		// aVal>>=3, set Z accordingly, V unaffected
	asm("add r3, r3, #0x30 ");			// r3 += '0'
	asm("strvsh r3, [ip, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("strvcb r3, [ip, #-1]! ");		// else store 8 bits
	asm("bne 1b ");						// loop back if (aVal & 0xffffffff) still nonzero
	asm("2: ");
	asm("ldr r0, [r2] ");				// r0 = original aDest
	asm("subvc r0, r0, #11 ");			// r0 = end of buffer for first word (8-bit descriptor)
	asm("subvs r0, r0, #22 ");			// r0 = end of buffer for first word (16-bit descriptor)
	asm("teq ip, r0 ");					// don't pad if we have already emitted 32 bits
	asm("beq finish_oct_zero_pad ");
	asm("oct_zero_pad: ");
	asm("mov r3, #0x30 ");				// r3 = '0'
	asm("oct_zero_pad_loop: ");
	asm("strvsh r3, [ip, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("strvcb r3, [ip, #-1]! ");		// else store 8 bits
	asm("teq ip, r0 ");
	asm("bne oct_zero_pad_loop ");		// loop back if padding not complete
	asm("finish_oct_zero_pad: ");
	asm("addvc r0, r0, #11 ");			// r0 = original aDest
	asm("addvs r0, r0, #22 ");			// r0 = original aDest
	asm("mov r3, r0 ");
	asm("mov r0, r1 ");
	asm("mov r1, r3 ");					// r1 = orig aDest, r0 = aVal >> 32
	asm("3: ");
	asm("and r3, r0, #7 ");				// r3 = aVal & 7
	asm("movs r0, r0, lsr #3 ");		// aVal>>=3, set Z accordingly, V unaffected
	asm("add r3, r3, #0x30 ");			// r3 += '0'
	asm("strvsh r3, [ip, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("strvcb r3, [ip, #-1]! ");		// else store 8 bits
	asm("bne 3b ");						// loop back if aVal still nonzero
	asm("str ip, [r2] ");				// aDest = ip
	asm("sub r0, r1, ip ");				// return aDest - ip
	__JUMP(,lr);

#endif //__KERNEL_MODE__

	asm("do_convert_hex64: ");
	asm("ldr ip, [ip] ");				// ip = aDest
	asm("mov r2, r3, lsl #22 ");		// aA bit 8 into r2 bit 30
	asm("adds r2, r2, r2 ");			// set V flag = aA bit 8
	asm("and r3, r3, #0xff ");			// aA = aA & 0xff
	asm("teq r1, #0 ");					// if (aVal <= 0xffffffffu)
	asm("sub r3, r3, #0x40 ");			// bias by ('0' + 16) either way => r3 = aA - ('0' + 16)
	asm("moveq r1, ip ");				// r1 = orig. aDest in second half
	asm("beq 2f ");						// branch to second half of the loop
	asm("1: ");
	asm("and r2, r0, #0xf ");			// r2 = aVal & 0xf
	asm("add r2, r2, #0x36 ");			// r2 += ('0' + 6)
	asm("tst r2, #0x40 ");				// if ((aVal & 0xf) > 9)
	asm("addne r2, r2, r3 ");			// r2 = (aVal & 0xf) + (aA - 10)
	asm("subeq r2, r2, #6 ");			// r2 = (aVal & 0xf) + '0'
	asm("movs r0, r0, lsr #4 ");		// aVal>>=4, V unaffected
	asm("strvsh r2, [ip, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("strvcb r2, [ip, #-1]! ");		// else store 8 bits
	asm("bne 1b ");						// loop back if (aVal & 0xffffffffu) still nonzero
	asm("ldr r0, [sp] ");				// r0 = &aDest
	asm("ldr r2, [r0] ");				// r2 = original aDest
	asm("subvc r0, r2, #8 ");			// r0 = end of buffer for first word (8-bit descriptor)
	asm("subvs r0, r2, #16 ");			// r0 = end of buffer for first word (16-bit descriptor)
	asm("teq ip, r0 ");					// don't pad if we have already emitted 32 bits
	asm("beq finish_hex_zero_pad ");
	asm("hex_zero_pad: ");
	asm("mov r2, #0x30 ");				// r3 = '0'
	asm("hex_zero_pad_loop: ");
	asm("strvsh r2, [ip, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("strvcb r2, [ip, #-1]! ");		// else store 8 bits
	asm("teq ip, r0 ");
	asm("bne hex_zero_pad_loop ");		// loop back if padding not complete
	asm("finish_hex_zero_pad: ");
	asm("addvc r0, r0, #8 ");			// r0 = original aDest
	asm("addvs r0, r0, #16 ");			// r0 = original aDest
	asm("mov r2, r0 ");
	asm("mov r0, r1 ");
	asm("mov r1, r2 ");					// r1 = orig aDest, r0 = aVal >> 32
	asm("2: ");
	asm("and r2, r0, #0xf ");			// r2 = aVal & 0xf
	asm("add r2, r2, #0x36 ");			// r2 += '0'+6
	asm("tst r2, #0x40 ");
	asm("subeq r2, r2, #6 ");			// r2 = (aVal & 0xf) + '0'
	asm("addne r2, r2, r3 ");			// r2 = (aVal & 0xf) + (aA - 10)
	asm("movs r0, r0, lsr #4 ");		// aVal>>=4, V unaffected
	asm("strvsh r2, [ip, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("strvcb r2, [ip, #-1]! ");		// else store 8 bits
	asm("bne 2b ");						// loop back if aVal still nonzero
	asm("ldr r2, [sp] ");				// r2 = &aDest
	asm("sub r0, r1, ip ");				// return aDest - ip
	asm("str ip, [r2] ");				// aDest = ip
	__JUMP(,lr);

#ifndef __FIXED_POINT_64BIT_DIV10__

	asm("do_convert_dec64: ");			// As generic case, except can save one reg as radix known
	asm("stmfd sp!, {r4-r6,lr} ");
	asm("ldr r4, [ip] ");				// r4 = aDest
	asm("mov r5, ip ");					// save &aDest
	asm("mov r6, r3");					// save aA
	asm("teq r1, #0 ");					// aVal > 0xffffffffu
	asm("beq 2f ");
	asm("1: ");
	asm("mov r3, #0 ");
	asm("mov r2, #10 ");				// r3:r2 = radix
#ifndef __EABI__
	asm("stmfd sp!, {r4-r6} ");			// push the registers that are scratched by UDiv01
	asm(".extern UDiv01 ");
	asm("bl UDiv01 ");					// do division, quotient->r5:r4, rem->r6:r3
	asm("mov r0, r4");					// move to make regs same as EABI function
	asm("mov r1, r5");
	asm("mov r2, r3");
	asm("mov r3, r6");
	asm("ldmfd sp!, {r4-r6} ");			// pop the registers that are scratched by UDiv01
#else //__EABI__
	asm(".extern __aeabi_uldivmod ");
	asm("bl __aeabi_uldivmod ");		// do division, quotient->r1:r0, rem->r3:r2
#endif //__EABI__
	asm("add r2, r2, #0x30 ");			// add '0' to remainder
	asm("tst r6, #0x100 ");
	asm("strneh r2, [r4, #-2]! ");		// *--r4 = (TUint16)r2
	asm("streqb r2, [r4, #-1]! ");		// *--r4 = (TUint8)r2
	asm("teq r1, #0 ");					// new aVal > 0xffffffffu
	asm("bne 1b ");
	asm("2: ");
	asm("mov r2, r6 ");					// r2 = aA
	asm("ldr r1, [r5] ");				// r1 = original aDest
	asm("mov r3, r5 ");					// r3 = &aDest
	asm("sub r6, r1, r4 ");				// r6 = original aDest - r4
	asm("mov r1, #10 ");				// r1 = radix
	asm("str r4, [r3] ");				// aDest = r4
	asm("mov ip, r4 ");					// ip = aDest
	asm("bl do_convert_dec ");
	asm("add r0, r0, r6 ");				// r0 += r6
	__POPRET("r4-r6,");

#else //__FIXED_POINT_64BIT_DIV10__

	asm("do_convert_dec64: ");			// Be extra cunning by doing fixed-point arithmetic using only shifts, adds and subtracts
	asm("stmfd sp!, {r4-r7,lr} ");		//  - avoids costs of potentially inefficient calls to __aeabi_uldivmod
	asm("mov r4, r3 ");					// r4 = aA
	asm("ldr r5, [ip] ");				// r5 = aDest
	asm("teq r1, #0 ");					// aVal > 0xffffffffu
	asm("beq 2f ");
	asm("1: ");
	asm("subs r2, r0, #10 ");			// divide aVal by 10, r1:r0=quotient, r3:r2=remainder
	asm("sbc r3, r1, #0 ");
	asm("mov r6, r0, lsr #2 ");			// NB: 0.8 rounded to 64 bits is:
	asm("orr r6, r6, r1, lsl #30 ");	// 		0.11001100110011001100110011001100110011001100110011001100110011
	asm("subs r0, r0, r6 ");
	asm("sbc r1, r1, r1, lsr #2 ");		// quotient -= quotient >> 2	(0.11)
	asm("mov r6, r0, lsr #4 ");
	asm("orr r6, r6, r1, lsl #28 ");
	asm("adds r0, r0, r6 ");
	asm("adc r1, r1, r1, lsr #4 ");		// quotient += quotient >> 4	(0.110011)
	asm("mov r6, r0, lsr #8 ");
	asm("orr r6, r6, r1, lsl #24 ");
	asm("adds r0, r0, r6 ");
	asm("adc r1, r1, r1, lsr #8 ");		// quotient += quotient >> 8	(0.11001100110011)
	asm("mov r6, r0, lsr #16 ");
	asm("orr r6, r6, r1, lsl #16 ");
	asm("adds r0, r0, r6 ");
	asm("adc r1, r1, r1, lsr #16 ");	// quotient += quotient >> 16	(0.110011001100110011001100110011)
	asm("adds r0, r0, r1 ");
	asm("adc r1, r1, #0 ");				// quotient += quotient >> 32	(0.11001100110011001100110011001100110011001100110011001100110011)
	asm("mov r0, r0, lsr #3 ");
	asm("orr r0, r0, r1, lsl #29 ");
	asm("mov r1, r1, lsr #3 ");			// quotient >>= 3		0.1 ==	(0.00011001100110011001100110011001100110011001100110011001100110011)
	asm("mov r7, r1, lsl #2 ");			// use r7:r6 as a temp
	asm("orr r7, r7, r0, lsr #30 ");
	asm("mov r6, r0, lsl #2 ");			// r7:r6 = quotient << 2 == 4 * |aVal/10|
	asm("adds r6, r6, r0 ");
	asm("adc r7, r7, r1 ");				// r7:r6 += quotient == 5 * |aVal/10|
	asm("mov r7, r7, lsl #1 ");
	asm("orr r7, r7, r6, lsr #31 ");
	asm("mov r6, r6, lsl #1 ");			// r7:r6 <<= 1 == 10 * |aVal/10|
	asm("subs r2, r2, r6 ");
	asm("sbcs r3, r3, r7 ");			// r3:r2 = aVal - (10 * |aVal/10|) == remainder
	asm("bpl fix_quotient ");
	asm("adds r2, r2, #10 ");
	asm("adc r3, r3, #0 ");				// fix remainder
	asm("b fix_end ");
	asm("fix_quotient: ");
	asm("adds r0, r0, #1 ");
	asm("adc r1, r1, #0 ");				// increment quotient
	asm("fix_end: ");
	asm("add r2, r2, #0x30 ");			// add '0' to remainder
	asm("tst r4, #0x100 ");				// test aA bit 8
	asm("strneh r2, [r5, #-2]! ");		// if aA bit 8 set, store 16 bits
	asm("streqb r2, [r5, #-1]! ");		// else store 8 bits
	asm("teq r1, #0 ");
	asm("bne 1b ");						// loop back if new aVal > 0xffffffffu
	asm("2: ");
	asm("mov r2, r4 ");					// r2 = aA
	asm("ldr r1, [ip] ");				// r1 = original aDest
	asm("mov r3, ip ");					// r3 = &aDest
	asm("sub r6, r1, r5 ");				// r6 = original aDest - r5
	asm("str r5, [r3] ");				// aDest = r5
	asm("mov r1, #10 ");				// r1 = radix
	asm("mov ip, r5 ");					// ip = aDest
	asm("bl do_convert_dec ");
	asm("add r0, r0, r6 ");				// r0 += r6
	__POPRET("r4-r7,");

#endif //__FIXED_POINT_64BIT_DIV10__

	}

#endif //__DES_MACHINE_CODED__