We need a way to pass flags to rombuilds in Raptor via extension flm interfaces, so that the CPP pass
of the rom input files can be informed what toolchain we are building with and conditionally
include or exclude files depending on whether the toolchain could build them.
// Copyright (c) 2010-2010 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\nkern\arm\nklib.cia
//
//
#include <e32atomics.h>
#include <nklib.h>
#ifdef __SRATIO_MACHINE_CODED__
__NAKED__ void SRatio::Set(TUint32 /*aInt*/, TInt /*aDivisorExp*/)
{
#ifdef __CPU_ARM_HAS_CLZ
CLZ( 3,1); // r3=31-MSB(r1), 32 if r1=0
asm("add r2, r2, r3 "); // r2=shift+aDivisorExp
asm("movs r1, r1, lsl r3 "); // shift r1 left so bit 31=1
asm("rsb r2, r2, #0 "); // r2 = -shift-aDivisorExp
asm("moveq r2, #0 "); // if aInt=0, r2=0
asm("bicne r2, r2, #0xff000000 "); // else clear iSpare fields
asm("bicne r2, r2, #0x00ff0000 "); //
#else
asm("rsb r2, r2, #0 "); // r2 = -aDivisorExp
asm("cmp r1, #0x00010000 "); // if aInt top 16 bits clear ...
asm("movcc r1, r1, lsl #16 "); // ... shift 16 bits left ...
asm("subcc r2, r2, #16 "); // ... and subtract 16 from iX
asm("cmp r1, #0x01000000 ");
asm("movcc r1, r1, lsl #8 ");
asm("subcc r2, r2, #8 ");
asm("cmp r1, #0x10000000 ");
asm("movcc r1, r1, lsl #4 ");
asm("subcc r2, r2, #4 ");
asm("cmp r1, #0x40000000 ");
asm("movcc r1, r1, lsl #2 ");
asm("subcc r2, r2, #2 ");
asm("cmp r1, #0x80000000 ");
asm("subcc r2, r2, #1 ");
asm("cmp r1, #0 ");
asm("moveq r2, #0 "); // if aInt=0, r2=0
asm("bicne r2, r2, #0xff000000 "); // else clear iSpare fields
asm("bicne r2, r2, #0x00ff0000 "); //
#endif
asm("stmia r0, {r1,r2} "); // iM in r1, iX in bottom 16 bits of r2
__JUMP(, lr);
}
__NAKED__ TInt SRatio::Reciprocal()
{
asm("ldr r1, [r0] "); // r1 = iM
asm("ldrsh r12, [r0, #4] "); // r12 = iX
asm("rsbs r2, r1, #0 ");
asm("beq 0f "); // divide by zero
asm("add r12, r12, #63 ");
asm("rsb r12, r12, #0 "); // r12 = -63 - iX
asm("addvs r12, r12, #1 "); // if iM==0x80000000 r12 = -62 - iX (ratio = 2^(31+iX) so reciprocal = 2^(-31-iX) = 2^(31 + (-62-iX))
asm("bvs 1f "); // iM=0x80000000
// 2^(32+iX) > r > 2^(31+iX)
// 2^(-32-iX) < 1/r < 2^(-31-iX)
// 2^(31+(-63-iX)) < 1/r < 2^(31+(-62-iX))
asm("mov r2, #0 "); // accumulates result
asm("mov r3, #0x80000000 "); // 33 bit accumulator in C:R3 initialised to 2^32
asm("2: ");
asm("adds r3, r3, r3 ");
asm("cmpcc r3, r1 ");
asm("subcs r3, r3, r1 "); // if C=1 or r3>=r1, r3-=r1
asm("adcs r2, r2, r2 "); // next result bit
asm("bcc 2b "); // finished when we have 33 bits (when top bit shifted off)
asm("movs r2, r2, lsr #1 "); // rounding bit into C
asm("orr r2, r2, #0x80000000 "); // top bit back
asm("adcs r2, r2, #0 "); // add rounding bit
asm("movcs r2, #0x80000000 "); // if carry, increment exponent
asm("addcs r12, r12, #1 ");
asm("1: ");
asm("cmp r12, #-32768 ");
asm("blt 9f "); // underflow
asm("cmp r12, #32768 ");
asm("bge 8f "); // overflow
asm("str r2, [r0] "); // iM
asm("strh r12, [r0, #4] "); // iX
asm("mov r0, #0 ");
__JUMP(, lr);
asm("0: ");
asm("mov r0, #%a0" : : "i" ((TInt)KErrDivideByZero));
__JUMP(, lr);
asm("8: ");
asm("mov r0, #%a0" : : "i" ((TInt)KErrOverflow));
__JUMP(, lr);
asm("9: ");
asm("mov r0, #%a0" : : "i" ((TInt)KErrUnderflow));
__JUMP(, lr);
}
__NAKED__ TInt SRatio::Mult(TUint32& /*aInt32*/)
{
asm("ldr r3, [r0] "); // r3 = iM
asm("mov r12, r0 ");
asm("ldr r0, [r1] "); // r0 = aInt32
asm("cmp r3, #0 ");
asm("cmpne r0, #0 ");
asm("beq 0f "); // result zero
asm("umull r2, r3, r0, r3 "); // r3:r2 = aInt32 * iM (lowest value 0x0000000080000000)
asm("ldrsh r12, [r12, #4] "); // r12 = iX
#ifdef __CPU_ARM_HAS_CLZ
CLZ( 0, 3); // r0 = number of leading zeros in r3:r2 (can't be >32)
#else
asm("str r12, [sp, #-4]! ");
asm("movs r12, r3 ");
asm("mov r0, #0 ");
asm("cmp r12, #0x00010000 ");
asm("movcc r12, r12, lsl #16 ");
asm("addcc r0, r0, #16 ");
asm("cmp r12, #0x01000000 ");
asm("movcc r12, r12, lsl #8 ");
asm("addcc r0, r0, #8 ");
asm("cmp r12, #0x10000000 ");
asm("movcc r12, r12, lsl #4 ");
asm("addcc r0, r0, #4 ");
asm("cmp r12, #0x40000000 ");
asm("movcc r12, r12, lsl #2 ");
asm("addcc r0, r0, #2 ");
asm("cmp r12, #0 ");
asm("ldr r12, [sp], #4 "); // r12 = iX
asm("addgt r0, r0, #1 ");
asm("moveq r0, #32 "); // r0 = number of leading zeros in r3:r2 (can't be >32)
#endif
asm("rsb r0, r0, #63 "); // bit number of most significant bit
asm("add r0, r0, r12 "); // bit number of most significant bit after exponent shift
asm("cmp r0, #32 ");
asm("bge 8f "); // overflow
asm("cmp r0, #-1 ");
asm("blt 9f "); // underflow
asm("adds r12, r12, #32 "); // shift needed to get result into top 32 bits (>0 left, <0 right)
asm("beq 1f "); // no shift
asm("blt 2f "); // right shift
asm("rsb r0, r12, #32 ");
asm("mov r3, r3, lsl r12 ");
asm("orr r3, r3, r2, lsr r0 ");
asm("mov r2, r2, lsl r12 "); // r3:r2 <<= r12
asm("b 1f ");
asm("2: ");
asm("rsb r12, r12, #0 ");
asm("rsb r0, r12, #32 ");
asm("mov r2, r2, lsr r12 ");
asm("orr r2, r2, r3, lsl r0 ");
asm("mov r3, r3, lsr r12 "); // r3:r2 >>= r12
asm("1: ");
asm("adds r2, r2, r2 "); // rounding
asm("adcs r3, r3, #0 ");
asm("bcs 8f "); // overflow
asm("beq 9f "); // underflow
asm("mov r0, #0 ");
asm("str r3, [r1] ");
__JUMP(, lr);
asm("0: ");
asm("mov r0, #0 ");
asm("str r0, [r1] ");
__JUMP(, lr);
asm("8: ");
asm("mvn r0, #0 ");
asm("str r0, [r1] ");
asm("mov r0, #%a0" : : "i" ((TInt)KErrOverflow));
__JUMP(, lr);
asm("9: ");
asm("mov r0, #0 ");
asm("str r0, [r1] ");
asm("mov r0, #%a0" : : "i" ((TInt)KErrUnderflow));
__JUMP(, lr);
}
//TInt SRatio::Mult(TUint64& aInt64)
// {
// }
#endif