kernel/eka/nkern/nklib.cpp
author hgs
Wed, 23 Jun 2010 12:58:21 +0100
changeset 177 a232af6b0b1f
permissions -rw-r--r--
201023_15
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
177
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
     1
// Copyright (c) 2010-2010 Nokia Corporation and/or its subsidiary(-ies).
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
     2
// All rights reserved.
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
     3
// This component and the accompanying materials are made available
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
     4
// under the terms of the License "Eclipse Public License v1.0"
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
     5
// which accompanies this distribution, and is available
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
     7
//
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
     8
// Initial Contributors:
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
     9
// Nokia Corporation - initial contribution.
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    10
//
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    11
// Contributors:
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    12
//
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    13
// Description:
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    14
// e32\nkern\nklib.cpp
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    15
// 
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    16
//
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    17
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    18
#include <e32atomics.h>
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    19
#include <nklib.h>
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    20
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    21
#ifndef __SRATIO_MACHINE_CODED__
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    22
void SRatio::Set(TUint32 aInt, TInt aDivisorExp)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    23
	{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    24
	iSpare1 = 0;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    25
	iSpare2 = 0;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    26
	iM = aInt;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    27
	if (iM)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    28
		{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    29
		TInt ms1 = __e32_find_ms1_32(iM);
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    30
		TInt shift = 31 - ms1;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    31
		iM <<= shift;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    32
		iX = (TInt16)(-shift - aDivisorExp);
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    33
		}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    34
	else
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    35
		iX = 0;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    36
	}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    37
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    38
TInt SRatio::Reciprocal()
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    39
	{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    40
	if (iM==0)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    41
		return KErrDivideByZero;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    42
	// Calculate 2^32/iM
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    43
	TInt exp=0;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    44
	if (iM == 0x80000000u)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    45
		{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    46
		// ratio = 2^(31+iX) so reciprocal = 2^(-31-iX) = 2^(31 + (-62-iX))
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    47
		exp = -62-iX;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    48
		}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    49
	else
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    50
		{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    51
		// 2^32/iM = 1.xxx
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    52
		TUint64 r64 = MAKE_TUINT64(0u-iM,0);
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    53
		TUint32 q32 = (TUint32)(r64/TUint64(iM));	// next 32 bits of result
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    54
		iM = 0x80000000u | (q32>>1);
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    55
		exp = -63-iX;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    56
		if (q32 & 1)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    57
			{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    58
			if (++iM==0)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    59
				iM=0x80000000u, ++exp;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    60
			}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    61
		}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    62
	if (exp < -32768)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    63
		{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    64
		iM = 0;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    65
		iX = 0;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    66
		return KErrUnderflow;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    67
		}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    68
	if (exp > 32767)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    69
		{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    70
		iM = 0xffffffffu;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    71
		iX = 32767;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    72
		return KErrOverflow;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    73
		}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    74
	iX = (TInt16)exp;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    75
	return KErrNone;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    76
	}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    77
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    78
TInt SRatio::Mult(TUint32& aInt32)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    79
	{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    80
	TUint64 x = aInt32;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    81
	x *= TUint64(iM);
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    82
	if (x==0)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    83
		{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    84
		aInt32 = 0;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    85
		return KErrNone;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    86
		}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    87
	TInt ms1 = __e32_find_ms1_64(x);
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    88
	TInt ms1b = ms1 + iX;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    89
	if (ms1b>=32)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    90
		{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    91
		aInt32 = ~0u;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    92
		return KErrOverflow;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    93
		}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    94
	if (ms1b<-1)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    95
		{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    96
		aInt32 = 0;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    97
		return KErrUnderflow;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    98
		}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
    99
	TInt shift = ms1b - ms1 + 31;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   100
	if (shift > 0)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   101
		x <<= shift;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   102
	else if (shift < 0)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   103
		x >>= (-shift);
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   104
	x += MAKE_TUINT64(0,0x40000000u);
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   105
	if (x >> 63)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   106
		{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   107
		aInt32 = ~0u;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   108
		return KErrOverflow;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   109
		}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   110
	aInt32 = (TUint32)(x>>31);
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   111
	return aInt32 ? KErrNone : KErrUnderflow;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   112
	}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   113
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   114
//TInt SRatio::Mult(TUint64& aInt64)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   115
//	{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   116
//	}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   117
#endif
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   118
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   119
void SRatioInv::Set(const SRatio* a)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   120
	{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   121
	if (a)
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   122
		{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   123
		iR = *a;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   124
		iI = iR;
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   125
		iI.Reciprocal();
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   126
		}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   127
	else
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   128
		{
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   129
		iR.Set(1);
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   130
		iI.Set(1);
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   131
		}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   132
	}
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   133
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   134
a232af6b0b1f 201023_15
hgs
parents:
diff changeset
   135