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__