kernel/eka/kernel/arm/cutils.cia
changeset 0 a41df078684a
child 4 56f325a607ea
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/kernel/arm/cutils.cia	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,1534 @@
+// Copyright (c) 1994-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\kernel\arm\cutils.cia
+// 
+//
+
+//#define __EARLY_DEBUG__
+//#define __NE1__
+//#define __MI920__
+//#define __BOOTLDRIN__
+//#define __MCOT__
+
+#include <e32cia.h>
+#include <arm_mem.h>
+#include "nk_cpu.h"
+#include <kernel/kern_priv.h>
+#include <kernel/cache.h>
+
+#if defined(__MEMMODEL_MOVING__) || defined(__MEMMODEL_MULTIPLE__)
+#include <mmubase.h>
+#endif
+
+#ifdef __SMP__
+__NAKED__ TUint __arm_cpu_number()
+	{
+	asm("mrc	p15, 0, r0, c0, c0, 5 ");
+	asm("and	r0, r0, #15 ");
+	__JUMP(,lr);
+	}
+#endif
+
+#ifdef __EARLY_DEBUG__
+__NAKED__ void DebugOutputChar(TUint)
+//
+// Early debug print code - must hack this for the particular platform.
+// We assume bootstrap trace has already initialised the port.
+//
+	{
+#if defined(__MISA__)
+	// Brutus debug print code.
+	asm("ldr r1, __UartBase ");
+	asm("wait_tx_rdy: ");
+	asm("ldr r2, [r1, #0x20] ");
+	asm("tst r2, #0x04 ");
+	asm("beq wait_tx_rdy ");
+	asm("str r0, [r1, #0x14] ");
+	__JUMP(,lr);
+	asm("__UartBase: ");
+	asm(".word 0x63001000 ");
+#elif defined(__MAWD__)
+	// S5mx debug print code.
+	asm("ldr r1, __UartBase ");
+	asm("wait_tx_rdy: ");
+	asm("ldr r2, [r1, #0x10] ");
+	asm("tst r2, #0x20 ");
+	asm("bne wait_tx_rdy ");
+	asm("str r0, [r1, #0x00] ");
+	__JUMP(,lr);
+	asm("__UartBase: ");
+	asm(".word 0x63000700 ");
+#elif defined(__SAWD__)
+	// S5mx debug print code.
+	asm("ldr r1, __UartBase ");
+	asm("wait_tx_rdy: ");
+	asm("ldr r2, [r1, #0x10] ");
+	asm("tst r2, #0x20 ");
+	asm("bne wait_tx_rdy ");
+	asm("str r0, [r1, #0x00] ");
+	__JUMP(,lr);
+	asm("__UartBase: ");
+	asm(".word 0x80000700 ");
+#elif defined(__MI920__) || defined(__NI1136__) || defined(__BOOTLDRIN__)
+	// Integrator debug print code.
+	asm("ldr r1, __UartBase ");
+	asm("wait_tx_rdy: ");
+	asm("ldr r2, [r1, #0x18] ");
+	asm("tst r2, #0x20 ");
+	asm("bne wait_tx_rdy ");
+	asm("str r0, [r1, #0x00] ");
+	__JUMP(,lr);
+	asm("__UartBase: ");
+#if defined(__MI920__)
+	asm(".word 0x63006000 ");
+#elif defined(__NI1136__)
+	asm(".word 0xc6006000 ");
+#elif defined(__BOOTLDRIN__)
+	asm(".word 0x16000000 ");
+#endif
+#elif 0
+//#elif defined(__NI1136__)
+	// Use debug comms channel
+//	asm("mov r1, #0x1000 ");
+//	asm("mcr p14, 0, r1, c0, c1, 0 ");
+//	asm("1: ");
+//	asm("mrc p14, 0, r15, c0, c1, 0 ");		// read comm channel flags into CPSR
+//	asm("bcs 1b ");	// wait for space
+//	asm("mcr p14, 0, r0, c0, c5, 0 ");		// output character
+//	__JUMP(,lr);
+	asm("mov r1, #0xc3000000 ");
+	asm("add r1, r1, #0xc000 ");
+	asm("str r0, [r1, #0x20] ");
+	__JUMP(,lr);
+#elif defined(__MCOT__)
+	// Lubbock debug print code.
+	asm("ldr r1, __UartBase ");
+	asm("1: ");
+	asm("ldr r2, [r1, #0x14] ");
+	asm("tst r2, #0x20 ");
+	asm("beq 1b ");
+	asm("str r0, [r1, #0x00] ");
+	__JUMP(,lr);
+	asm("__UartBase: ");
+	asm(".word 0x63001000 ");
+#elif defined(__IS_OMAP1610__) || defined(__IS_OMAP1510__)
+	// omap 1510 and 1610 debug print code.
+	// N.B. Could also use JTAG DCC code from Arm::DebugOutJTAG()
+	asm("ldr r1, __UartBase ");
+	asm("1: ");
+	asm("ldrb r2, [r1, #0x14] ");
+	asm("tst r2, #0x20 ");
+	asm("beq 1b ");
+	asm("strb r0, [r1, #0x00] ");
+	__JUMP(,lr);
+	asm("__UartBase: ");
+	#if defined(__MEMMODEL_DIRECT__)
+	asm(".word 0xFFFB0000 ");	// Physical for single
+	#else
+	asm(".word 0x630B0000 ");	// Virtual for normal
+	#endif
+#elif defined(__NE1__)
+	asm("ldr	r1, __SuperPageAddress ");
+	asm("adr	r2, __UartBase ");
+	asm("ldr	r1, [r1] ");
+	asm("ldr	r1, [r1, #%a0]" : : "i" _FOFF(TSuperPage,iDebugPort));
+	asm("cmp	r1, #0 ");
+	asm("ldrne	r2, [r2, #4] ");
+	asm("ldreq	r2, [r2, #0] ");
+	asm("1: ");
+	asm("ldr	r3, [r2, #0x14] ");	// LSR
+	asm("tst	r3, #0x20 ");
+	asm("beq	1b ");
+	asm("str	r0, [r2, #0x00] ");	// THR
+	__JUMP(,lr);
+	asm("__UartBase: ");
+	#if defined(__MEMMODEL_DIRECT__)
+	asm(".word 0x18034000 ");
+	asm(".word 0x18034400 ");
+	#else
+	asm(".word 0xc6000000 ");
+	asm(".word 0xc6000400 ");
+	#endif
+	asm("__SuperPageAddress: ");
+	asm(".word SuperPageAddress ");
+#elif defined(__REALVIEW__)
+	// RealView platform debug print code.
+	asm("ldr r1, __SuperPageBase ");
+	asm("ldr r1, [r1] ");
+	asm("ldr r1, [r1, #%a0] " : : "i" _FOFF(TSuperPage,iDebugPort));
+	asm("cmp r1, #%a0 " : : "i" ((TInt)KNullDebugPort));
+	asm("bxeq lr ");                // debug output supressed
+	asm("adr r2, __UartBase ");
+	asm("ldr r1, [r2] ");
+	asm("1: ");
+	asm("ldr r2, [r1, #0x18] ");    // check status Tpl011::KHoFlags
+	asm("tst r2, #0x20 ");          // compare to Tpl011::KFlagTxFifoFull  
+	asm("bne 1b ");                 // if transmit data full, wait
+	asm("str r0, [r1] ");           // store to data register Tpl011::KHoData
+	asm("bx  lr ");
+	asm("__SuperPageBase: ");
+	asm(".word %a0 " : : "i" ((TInt)&SuperPageAddress));
+	asm("__UartBase: ");
+	asm(".word 0xc6004000 ");
+#endif
+	}
+#endif
+
+__NAKED__ EXPORT_C TInt Arm::DebugOutJTAG(TUint /*aChar*/)
+	{
+#if defined(__CPU_ARM920T__) || defined(__CPU_ARM720T__) || defined(__CPU_ARM926J__)
+	asm("mov r2, #0x100000 ");			// timeout
+	asm("1: ");
+	asm("mrc p14, 0, r1, c0, c0, 0 ");	// get debug comms control register
+	asm("tst r1, #2 ");					// test W bit (1=busy)
+	asm("subnes r2, r2, #1 ");			// if busy, decrement timeout
+	asm("bne 1b ");						// if busy and not timed out, loop
+	asm("tst r1, #2 ");
+	asm("mcreq p14, 0, r0, c1, c0, 0 ");	// if not busy, output value
+	asm("moveq r0, #0 ");				// and return KErrNone
+	asm("movne r0, #%a0" : : "i" ((TInt)KErrTimedOut));	// else return KErrTimedOut
+#elif defined(__CPU_ARM1020T__)
+	asm("mov r2, #0x100000 ");			// timeout
+	asm("1: ");
+	asm("mrc p14, 0, r1, c0, c1, 0 ");	// get DSCR
+	asm("movs r1, r1, lsl #25 ");		// test WE bit (1=empty) - set N flag if empty
+	asm("subpls r2, r2, #1 ");			// if busy, decrement timeout
+	asm("bpl 1b ");						// if busy and not timed out, loop
+	asm("cmp r1, #0 ");
+	asm("mcrmi p14, 0, r0, c0, c5, 0 ");	// if not busy, output value
+	asm("movmi r0, #0 ");				// and return KErrNone
+	asm("movpl r0, #%a0" : : "i" ((TInt)KErrTimedOut));	// else return KErrTimedOut
+#elif defined(__CPU_ARM1136__) || defined(__CPU_ARM1176__)
+	asm("mov r2, #0x100000 ");			// timeout
+	asm("1: ");
+	asm("mrc p14, 0, r15, c0, c1, 0 ");	// test DSCR, wDTRfull->C flag (1=full)
+	asm("subcss r2, r2, #1 ");			// if busy, decrement timeout
+	asm("bcs 1b ");						// if busy and not timed out, loop
+	asm("mrc p14, 0, r15, c0, c1, 0 ");	// test DSCR, wDTRfull->C flag (1=full)
+	asm("mcrcc p14, 0, r0, c0, c5, 0 ");	// if not busy, output value
+	asm("movcc r0, #0 ");				// and return KErrNone
+	asm("movcs r0, #%a0" : : "i" ((TInt)KErrTimedOut));	// else return KErrTimedOut
+#else
+	asm("mov r0, #%a0" : : "i" ((TInt)KErrNotSupported));
+#endif
+	__JUMP(,lr);
+	}
+
+__NAKED__ EXPORT_C TInt Arm::DebugInJTAG(TUint32& /*aRxData*/)
+	{
+#if defined(__CPU_ARM920T__) || defined(__CPU_ARM720T__) || defined(__CPU_ARM926J__)
+	asm("mrc p14, 0, r2, c0, c0, 0 ");	// get debug comms control register
+	asm("tst r2, #1 ");					// test R bit (1=data available)
+	asm("mrcne p14, 0, r2, c1, c0, 0 ");	// get RX data
+	asm("strne r2, [r0] ");				// store RX data
+	asm("movne r0, #0 ");				// return KErrNone
+	asm("moveq r0, #%a0" : : "i" ((TInt)KErrNotReady));	// if no data available return KErrNotReady
+#elif defined(__CPU_ARM1020T__)
+	asm("mrc p14, 0, r2, c0, c1, 0 ");	// get DSCR
+	asm("tst r2, #0x80 ");				// test RF bit (1=full)
+	asm("mrcne p14, 0, r2, c0, c5, 0 ");	// get RX data
+	asm("strne r2, [r0] ");				// store RX data
+	asm("movne r0, #0 ");				// return KErrNone
+	asm("moveq r0, #%a0" : : "i" ((TInt)KErrNotReady));	// if no data available return KErrNotReady
+#elif defined(__CPU_ARM1136__) || defined(__CPU_ARM1176__)
+	asm("mrc p14, 0, r15, c0, c1, 0 ");	// test DSCR, rDTRfull->Z flag (1=full)
+	asm("mrceq p14, 0, r2, c0, c5, 0 ");	// get RX data
+	asm("streq r2, [r0] ");				// store RX data
+	asm("moveq r0, #0 ");				// return KErrNone
+	asm("movne r0, #%a0" : : "i" ((TInt)KErrNotReady));	// if no data available return KErrNotReady
+#else
+	asm("mov r0, #%a0" : : "i" ((TInt)KErrNotSupported));
+#endif
+	__JUMP(,lr);
+	}
+
+__NAKED__ void KPrintf(const char*, ...)
+	{
+	asm("b  " CSM_ZN4Kern6PrintfEPKcz);
+	}
+
+__NAKED__ TInt A::CallSupervisorFunction(TSupervisorFunction, TAny*)
+//
+// Execute an F32 function in supervisor mode - might be THUMB.
+//
+	{
+	asm("mov r2, r0 ");					// r2=function ptr
+	asm("mov r0, r1 ");					// r0=argument
+	__JUMP(,r2);						// call function in correct mode
+	}
+
+#if defined (__DES8_MACHINE_CODED__)
+/**
+Checks whether the specified name is a valid DObject full name.
+
+A name is deemed to be invalid, if it contains an asterisk or a question
+mark.
+
+@param aName Name to check.
+	
+@return KErrNone, if valid;
+        KErrBadName, if invalid.
+*/
+#ifndef __KERNEL_MODE__
+#error "TDesC is not 8-bit as __KERNEL_MODE__ is not defined (see e32cmn.h)"
+#endif
+__NAKED__ EXPORT_C TInt Kern::ValidateFullName(const TDesC& /*aName*/)
+//
+// Check for * or ? in descriptor, return KErrBadName if found
+//
+	{
+	asm("ldr r2, [r0], #4 ");			// r2=length/type
+	asm("cmp r2, #0x50000000 ");
+	asm("mvncs r0, #%a0" : : "i" (~KErrBadDescriptor));
+	__JUMP(cs,lr);
+	asm("bics r3, r2, #0xF0000000 ");	// r3=length
+	asm("moveq r0, #0 ");				// if length=0, return KErrNone
+	__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("ValidateFullName_1: ");
+	asm("ldrb r1, [r0], #1 ");			// r1=*r0++
+	asm("cmp r1, #0x20 ");				// is it < 0x20 ?
+	asm("rsbhss r2, r1, #0x7f ");		// if not, compare 0x7f with char
+	asm("bls ValidateFullName_2 ");		// if char < 0x20 or char >= 0x7f, error
+	asm("cmp r1, #'*' ");				// is it *
+	asm("cmpne r1, #'?' ");				// if not, is it ?
+	asm("subnes r3, r3, #1 ");			// if neither of these, decrement length
+	asm("bne ValidateFullName_1 ");
+	
+	asm("ValidateFullName_2: ");		// About to return so did we
+	asm("cmp r3, #0 ");					// reach the end of string?
+	asm("moveq r0, #0 ");				// if we did, return KErrNone
+	asm("mvnne r0, #%a0" : : "i" (~KErrBadName));	// else return KErrBadName
+	__JUMP(,lr);
+	}
+#endif
+
+
+/**
+Default implementation for Kern::NanoWait, which waits for the specified time.
+
+@param aInterval The time to wait in nanoseconds.
+*/
+__NAKED__ void K::DoNanoWait(TUint32 /*aInterval*/)
+	{
+	asm("ldr r1, __NanoWaitCal ");
+	asm("ldr r1, [r1] ");				// r1=PP::NanoWaitCal
+
+	asm(".align 8");					// to make the 'nanowait_loop' start on a cache line
+	asm("nanowait_loop: ");
+	asm("subs r0, r0, r1 ");
+	asm("bhi nanowait_loop ");
+	__JUMP(,lr);
+
+	asm("__NanoWaitCal: ");
+	asm(".word  " CSM_ZN2PP11NanoWaitCalE );
+	}
+
+__NAKED__ void A::StartCrashDebugger(const TAny*, TInt)
+	{
+	USER_MEMORY_GUARD_OFF(,r0,r0);		// let crash debugger have unfettered access to user memory
+	asm("ldr r0, __MonitorEntryPoint ");
+	asm("ldmia r0, {r1-r3} ");			// r1 = debugger entry point
+	asm("mvn r0, r2 ");
+	asm("cmp r1, r0 ");					// r2 = complement of r1 if valid
+	asm("moveq r12, r1, lsr #2 ");
+	asm("muleq r0, r12, r2 ");			// r3 = (r1*r2/4)MOD 2^32 if valid
+	asm("cmpeq r3, r0 ");
+	__JUMP(ne,lr);						// if debugger entry point invalid, return
+#ifdef __SMP__
+	GET_RWNO_TID(,r0);
+	asm("ldr r0, [r0, #%a0]" : : "i" _FOFF(TSubScheduler,i_Regs));	// pass in address of stored registers
+#else
+	asm("ldr r0, __TheScheduler ");
+	asm("ldr r0, [r0, #%a0]" : : "i" _FOFF(TScheduler,i_Regs));	// pass in address of stored registers
+#endif
+	__JUMP(,r1);						// jump to monitor
+										// if it returns, return from this function and reboot
+
+	asm("__MonitorEntryPoint: ");
+	asm(".word  " CSM_ZN2PP17MonitorEntryPointE);
+	}
+
+
+/**	Increments atomically a counter that's initially positive
+
+	It checks the previous CPU mode and if it's User, it only applies user permissions when accessing aValue.
+	It doesn't increment if aValue is negative or zero.
+
+	@param aValue Reference to the counter to increment
+	@return Previous value of counter
+
+********** NO GOOD ON SMP ****************
+
+*/
+EXPORT_C __NAKED__ TInt Kern::KUSafeInc(TInt& /*aValue*/)
+	{
+	ASM_ASSERT_PAGING_SAFE
+	asm("mrs ip, cpsr ");
+	INTS_OFF_1(r2, ip, INTS_ALL_OFF);
+	asm("mrs r3, spsr ");		// check caller's mode
+	asm("mov r1, r0 ");			// address into r1
+	asm("tst r3, #0x0f ");		// test for user mode
+	asm("bne 1f ");				// branch if not
+	INTS_OFF_2(r2, ip, INTS_ALL_OFF);	// interrupts off
+	USER_MEMORY_GUARD_OFF(,r2,r2);
+	asm("ldrt r0, [r1] ");		// r0=original value, only allow user permissions
+	asm("cmp r0, #0 ");
+	asm("addgt r2, r0, #1 ");
+	asm("strgtt r2, [r1] ");	// if original value >0, increment
+	USER_MEMORY_GUARD_ON(,r2,r2);
+	asm("msr cpsr, ip ");		// restore interrupts
+	__JUMP(,lr);
+	asm("1: ");
+	INTS_OFF_2(r2, ip, INTS_ALL_OFF);	// interrupts off
+	asm("ldr r0, [r1] ");		// r0=original value
+	asm("cmp r0, #0 ");
+	asm("addgt r2, r0, #1 ");
+	asm("strgt r2, [r1] ");		// if >0, increment
+	asm("msr cpsr, ip ");		// restore interrupts
+	__JUMP(,lr);
+	}
+
+/**	Decrements atomically a counter that's initially positive
+
+	It checks the previous CPU mode and if it's User, it only applies user permissions when accessing aValue.
+	It doesn't decrement if aValue is negative or zero.
+
+	@param aValue Reference to the counter to decrement
+	@return Previous value of counter 
+
+	********** NO GOOD ON SMP ****************
+
+*/
+EXPORT_C __NAKED__ TInt Kern::KUSafeDec(TInt& /*aValue*/)
+	{
+	ASM_ASSERT_PAGING_SAFE
+	asm("mrs ip, cpsr ");
+	INTS_OFF_1(r2, ip, INTS_ALL_OFF);
+	asm("mrs r3, spsr ");		// check caller's mode
+	asm("mov r1, r0 ");			// address into r1
+	asm("tst r3, #0x0f ");		// test for user mode
+	asm("bne 1f ");				// branch if not
+	INTS_OFF_2(r2, ip, INTS_ALL_OFF);	// interrupts off
+	USER_MEMORY_GUARD_OFF(,r2,r2);
+	asm("ldrt r0, [r1] ");		// r0=original value, only allow user permissions
+	asm("subs r2, r0, #1 ");	// decrement
+	asm("strget r2, [r1] ");	// update if result >=0
+	USER_MEMORY_GUARD_ON(,r2,r2);
+	asm("msr cpsr, ip ");		// restore interrupts
+	__JUMP(,lr);
+	asm("1: ");
+	INTS_OFF_2(r2, ip, INTS_ALL_OFF);	// interrupts off
+	asm("ldr r0, [r1] ");		// r0=original value
+	asm("subs r2, r0, #1 ");	// decrement
+	asm("strge r2, [r1] ");		// update if result >=0
+	asm("msr cpsr, ip ");		// restore interrupts
+	__JUMP(,lr);
+	}
+
+#ifdef __HANDLES_MACHINE_CODED__
+EXPORT_C __NAKED__ DObject* DThread::ObjectFromHandle(TInt /*aHandle*/)
+	{
+	// r0=this, r1=aHandle
+	asm("adds ip, r1, r1 ");			// check for special handle (bit 31 set => special)
+	asm("bcs 2f ");						// if not, N flag indicates local handle
+	asm("ldrpl ip, [r0, #%a0]" : : "i" _FOFF(DThread,iOwningProcess));	// if not local, ip=aThread->iOwningProcess
+	asm("addmi ip, r0, #%a0" : : "i" _FOFF(DThread,iHandles));		// if local, ip=&aThread->iHandles
+	asm("addpl ip, ip, #%a0" : : "i" _FOFF(DProcess,iHandles));		// if not, ip=&aThread->iOwningProcess->iHandles
+
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+	asm("stmfd sp!, {r0,r1,ip,lr} ");	// save r0, r1, ip and lr
+	asm("mov r0, ip ");					// move RObjectIx this(ip) to r0
+	asm("bl _ZN9RObjectIx15AcquireReadLockEv") // call RObjectIx::AquireReadLock
+	asm("ldmfd sp!, {r0,r1,ip,lr} ");	// restore r0, r1, ip and lr
+#else
+	// system lock is held
+#endif
+	
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+// TODO: If handle lookup protected only by RW spin lock, must take a reference on the object
+// (__HANDLES_USE_RW_SPIN_LOCK__ is not supported or even finished)
+#endif
+
+	asm("mov r3, r1, lsl #17 ");		// r3=r1<<17 = index(aHandle)<<17
+	asm("mov r1, r1, lsl #2 ");			// r1=instance(Handle)<<18
+	asm("ldr r0, [ip, #%a0]" : : "i" _FOFF(RObjectIx,iCount));		// r0=iCount
+	asm("ldr ip, [ip, #%a0]" : : "i" _FOFF(RObjectIx,iSlots));		// ip=iSlots
+	asm("subs r0, r0, r3, lsr #17 ");	// r0 = iCount - index(aHandle) - 1
+	asm("ldrge r2, [ip, r3, lsr #14]! ");	// if count-1>=index, r2=pS->uniqueID:pS->instance, ip=iSlots+index(Handle)=pS ...
+	asm("ldrge r0, [ip, #4] ");			// ... and r0 = pointer to DObject ...
+	asm("andge r0, r0, #%a0" : : "i" (RObjectIx::EObjRObjMask));	// r0 = (pointer & EObjRObjMask);
+	asm("eorge r1, r1, r2, lsl #18 ");	// ... and check if instance(aHandle)<<18 == pS->(uid:instance)<<18
+	asm("movges r1, r1, lsr #18 ");
+	asm("movne r0, #0");				// ... else r0 = 0
+
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+	asm("stmfd sp!, {r0,ip,lr} ");	// save r0, ip and lr
+	asm("mov r0, ip ");					// move RObjectIx this(ip) to r0
+	asm("bl _ZN9RObjectIx15ReleaseReadLockEv") // call RObjectIx::ReleaseReadLock
+	asm("ldmfd sp!, {r0,ip,lr} ");	// restore r0, ip and lr
+#else
+	// system lock is held, nothing to do
+#endif
+
+	// r0 now either 0(EBadHandle) or valid pointer...
+	__JUMP(,lr);
+
+	asm("1: ");
+	asm("mov r0, #0 ");					// if wrong, bad handle
+	__JUMP(,lr);
+	
+	asm("2: ");							// r12=handle<<1 (valid values are ffff0000 and ffff0002)
+	asm("bic ip, ip, #0x10000 ");		// clear 'no close' flag
+#ifdef	__OBSOLETE_V1_IPC_SUPPORT__
+	asm("cmp ip, #0x10000000 ");
+	asm("blo dobj_pseudo_5 ");			// if handle<0x88000000, it's an IPC client thread pseudo handle
+#endif
+	asm("ldr r0, __TheScheduler ");
+	asm("ldr r0, [r0, #%a0]" : : "i" _FOFF(TScheduler,iCurrentThread));	// r0->current NThread
+	asm("adds ip, ip, #0x20000 ");		// valid values now 0 and 2
+	asm("ldreq r0, [r0, #%a0]" : : "i" (_FOFF(DThread,iOwningProcess)-_FOFF(DThread,iNThread)));
+	__JUMP(eq,lr);						// if handle = ffff8000, return TheCurrentThread->iOwningProcess
+	asm("cmp ip, #2 ");					// otherwise, handle = ffff8001 ?
+	asm("subeq r0, r0, #%a0" : : "i" _FOFF(DThread,iNThread));
+	__JUMP(eq,lr);						// if so, return TheCurrentThread
+	asm("b 1b ");						// else bad handle
+
+	asm("badobjectfault: ");
+	asm("mov r0, #%a0" : : "i" (EBadObjectType));
+	asm("b  " CSM_ZN1K5FaultENS_6TFaultE);
+	}
+
+
+/**
+Returns the kernel object that the given handle refers.
+
+The handle passed is looked up in the thread's handles collection if the handle is local or
+in the thread's owner process' collection otherwise. If aHandle is negative or not found in
+the thread's or process' collection then NULL is returned.
+Two special handle values KCurrentThreadHandle and KCurrentProcessHandle can be used to get
+a pointer to the current thread and the current process.
+
+aType is used to ensure that the object referred by the handle is of desired type.
+If the type of the object referred by aHandle is different from aType then NULL is returned.
+If aType is negative, the type of the object is ignored and no type checking is done.
+If aType is positive and greater than the maximum number of object types (ENumObjectTypes)
+the kernel will fault.
+
+@param aThread The thread that owns the handle passed.
+@param aHandle Handle to the object to be returned.
+@param aType TObjectType parameter specifying the type of the object referred by the handle.  
+
+@return Pointer to the DObject referred by the handle or NULL if the handle is not
+		found in the thread's handles collection.
+
+@pre Call in a thread context.
+@pre Can be used in a device driver.
+
+@see TObjectType
+@see DThread::ObjectFromHandle()
+*/
+EXPORT_C __NAKED__ DObject* Kern::ObjectFromHandle(DThread* /*aThread*/, TInt /*aHandle*/, TInt /*aType*/)
+	{
+	ASM_CHECK_PRECONDITIONS(MASK_NOT_ISR|MASK_NOT_IDFC);
+
+	// r0=aThread, r1=aHandle, r2=aType (-1=any, 0=thread, etc.)
+	asm("add r3, r2, #1 ");
+	asm("cmp r3, #%a0" : : "i" ((TInt)ENumObjectTypes));
+	asm("bhi badobjectfault ");						// invalid object type
+	// fall through
+	}
+
+EXPORT_C __NAKED__ DObject* DThread::ObjectFromHandle(TInt /*aHandle*/, TInt /*aType*/)
+	{
+	// r0=this, r1=aHandle, r2=aType (-1=any, 0=thread, etc.)
+	asm("adds ip, r1, r1 ");			// check for special handle (bit 31 set => special)
+	asm("bcs 2f ");						// if not, N flag indicates local handle
+	asm("ldrpl ip, [r0, #%a0]" : : "i" _FOFF(DThread,iOwningProcess));	// if not local, ip=aThread->iOwningProcess
+	asm("addmi ip, r0, #%a0" : : "i" _FOFF(DThread,iHandles));		// if local, ip=&aThread->iHandles
+	asm("addpl ip, ip, #%a0" : : "i" _FOFF(DProcess,iHandles));		// if not, ip=&aThread->iOwningProcess->iHandles
+
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+	asm("stmfd sp!, {r0-r2,ip,lr} ");	// save r0-r2, ip and lr
+	asm("mov r0, ip ");					// move RObjectIx this(ip) to r0
+	asm("bl _ZN9RObjectIx15AcquireReadLockEv") // call RObjectIx::AquireReadLock
+	asm("ldmfd sp!, {r0-r2,ip,lr} ");	// restore r0-r2, ip and lr
+#else
+	// system lock is held
+#endif
+	
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+// TODO: If handle lookup protected only by RW spin lock, must take a reference on the object
+#endif
+
+	asm("mov r3, r1, lsl #17 ");		// r3=r1<<17 = index(aHandle)<<17
+	asm("mov r1, r1, lsl #2 ");			// r1=instance(Handle)<<18
+	asm("ldr r0, [ip, #%a0]" : : "i" _FOFF(RObjectIx,iCount));		// r0=iCount
+	asm("ldr ip, [ip, #%a0]" : : "i" _FOFF(RObjectIx,iSlots));		// ip=iSlots
+	asm("mov r1, r1, lsr #18 ");		// r1=instance(Handle)
+	asm("cmp r0, r3, lsr #17 ");		// compare iCount with index(aHandle)
+	asm("ldrgt r0, [ip, r3, lsr #14]! ");	// if count>index, r0=pS->uniqueID:pS->instance, ip=iSlots+index(Handle)=pS
+	asm("ble 1f ");						// if count<=index, bad handle
+	asm("adds r3, r2, #1 ");			// r3=0 if any type of object is ok, r3=UID if not
+	asm("biceq r0, r0, r2, lsl #14 ");	// if it is, (r2 therefore -1) clear top 18 bits of r0
+	asm("orr r1, r1, r3, lsl #14 ");	// r1=aUniqueID(bits14-19):instance(Handle)(bits0-13)
+	asm("mov r0, r0, lsl #12 ");		// only interested in comparing lower 20 bits...
+	asm("mov r1, r1, lsl #12 ");
+	asm("cmp r0, r1 ");					// check instance, and unique ID if necessary
+	asm("ldreq r0, [ip, #4] ");			// if OK return pointer to DObject
+	asm("movne r0, #0");				// else r0 = 0
+	asm("andeq r0, r0, #%a0" : : "i" (RObjectIx::EObjRObjMask));	// r0 = (pointer & EObjRObjMask);
+
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+	asm("stmfd sp!, {r0,ip,lr} ");	// save r0, ip and lr
+	asm("mov r0, ip ");					// move RObjectIx this(ip) to r0
+	asm("bl _ZN9RObjectIx15ReleaseReadLockEv") // call RObjectIx::ReleaseReadLock
+	asm("ldmfd sp!, {r0,ip,lr} ");	// restore r0, ip and lr
+#else
+	// system lock is held, nothing to do
+#endif
+
+	// r0 now either 0(EBadHandle) or valid pointer...
+	__JUMP(,lr);
+
+	asm("1: ");
+	asm("mov r0, #0 ");					// if wrong, bad handle
+	__JUMP(,lr);
+	
+	asm("2: ");							// r12=handle<<1 (valid values are fffx0000 and fffx0002, x=e or f)
+	asm("bic ip, ip, #0x10000 ");		// clear 'no close' flag
+#ifdef	__OBSOLETE_V1_IPC_SUPPORT__
+	asm("cmp ip, #0x10000000 ");
+	asm("blo 4f ");						// if handle<0x88000000, it's an IPC client thread pseudo handle
+#endif
+	asm("ldr r0, __TheScheduler ");
+	asm("add ip, ip, #0x20000 ");		// valid values now 0 and 2
+	asm("cmp r2, #1 ");					// r2=container number or -1 if any object OK
+	asm("ldrle r0, [r0, #%a0]" : : "i" _FOFF(TScheduler,iCurrentThread));	// r0->current NThread
+	asm("bgt 1b ");						// if type is neither thread nor process nor any, bad handle
+	asm("beq 3f ");						// skip check for KCurrentThreadHandle if process required
+	asm("cmp ip, #2 ");					// handle = ffff8001 ?
+	asm("subeq r0, r0, #%a0" : : "i" _FOFF(DThread,iNThread));
+	__JUMP(eq,lr);						// if so, return TheCurrentThread
+	asm("cmn r2, #1 ");					// r2=-1 means any type of object will do
+	asm("bne 1b ");
+	asm("3: ");
+	asm("cmp ip, #0 ");					// handle = ffff8000 ?
+	asm("ldreq r0, [r0, #%a0]" : : "i" (_FOFF(DThread,iOwningProcess)-_FOFF(DThread,iNThread)));
+	__JUMP(eq,lr);						// if so, return TheCurrentThread->iOwningProcess
+	asm("b 1b ");						// else bad handle
+
+#ifdef	__OBSOLETE_V1_IPC_SUPPORT__
+	asm("4: ");
+	asm("cmp r2, #0 ");					// type must be thread or any
+	asm("bgt 1b ");						// if not, bad handle
+
+	asm("dobj_pseudo_5: ");
+	asm("add r1, r0, #%a0" : : "i" _FOFF(DThread,iNThread));	// r1->iNThread
+	asm("stmfd sp!, {r4,lr} ");
+	asm("bl do_lookup_thread_pseudo ");
+	asm("bcc 6f ");						// skip if bad handle
+	asm("cmp ip, #%a0" : : "i" ((TInt)RMessage2::EDisConnect));	// else check iFunction != RMessage2::EDisConnect
+	asm("ldrne r0, [r0, #%a0]" : : "i" _FOFF(RMessageK,iClient));
+	asm("moveq r0, #0 ");
+	asm("6: ");
+	asm("ldmfd sp!, {r4,pc} ");
+#endif
+	}
+
+
+/**
+Returns the kernel object that the given handle refers.
+
+The handle passed is looked up in the thread's handles collection if the handle is local or
+in the thread's owner process' collection otherwise. If aHandle is negative or not found in
+the thread's or process' collection then NULL is returned.
+Two special handle values KCurrentThreadHandle and KCurrentProcessHandle can be used to get
+a pointer to the current thread and the current process.
+
+aType is used to ensure that the object referred by the handle is of desired type.
+If the type of the object referred by aHandle is different from aType then NULL is returned.
+If aType is negative, the type of the object is ignored and no type checking is done.
+If aType is positive and greater than the maximum number of object types (ENumObjectTypes)
+the kernel will fault.
+
+@param aThread The thread that owns the handle passed.
+@param aHandle Handle to the object to be returned.
+@param aType TObjectType parameter specifying the type of the object referred by the handle.  
+@param aAttr Returns the attributes for this object.  
+
+@return Pointer to the DObject referred by the handle or NULL if the handle is not
+		found in the thread's handles collection.
+
+@pre Call in a thread context.
+@pre Can be used in a device driver.
+
+@see TObjectType
+@see DThread::ObjectFromHandle()
+*/
+EXPORT_C __NAKED__ DObject* Kern::ObjectFromHandle(DThread* /*aThread*/, TInt /*aHandle*/, TInt /*aType*/, TUint& /*aAttr*/)
+	{
+	ASM_CHECK_PRECONDITIONS(MASK_NOT_ISR|MASK_NOT_IDFC);
+
+	// r0=aThread, r1=aHandle, r2=aType (-1=any, 0=thread, etc.), r3=&aAttr
+	asm("add r2, r2, #1 ");				// compare against 0 to ENumObjectTypes
+	asm("cmp r2, #%a0" : : "i" ((TInt)ENumObjectTypes));
+	asm("sub r2, r2, #1 ");				// revert the adjustment (quicker than save/restore of used register)
+	asm("bhi badobjectfault ");			// invalid object type
+	// fall through
+	}
+
+EXPORT_C __NAKED__ DObject* DThread::ObjectFromHandle(TInt /*aHandle*/, TInt /*aObjType*/, TUint& /*aAttr*/)
+	{
+	// r0=this, r1=aHandle, r2=aType (-1=any, 0=thread, etc.), r3=&aAttr
+	asm("stmfd sp!, {r3}");				// save r3
+	asm("adds ip, r1, r1 ");			// check for special handle (bit 31 set => special)
+	asm("bcs 2f ");						// if not, N flag indicates local handle
+	asm("ldrpl ip, [r0, #%a0]" : : "i" _FOFF(DThread,iOwningProcess));	// if not local, ip=aThread->iOwningProcess
+	asm("addmi ip, r0, #%a0" : : "i" _FOFF(DThread,iHandles));		// if local, ip=&aThread->iHandles
+	asm("addpl ip, ip, #%a0" : : "i" _FOFF(DProcess,iHandles));		// if not, ip=&aThread->iOwningProcess->iHandles
+
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+	asm("stmfd sp!, {r0-r2,ip,lr} ");	// save r0-r2, ip and lr
+	asm("mov r0, ip ");					// move RObjectIx this(ip) to r0
+	asm("bl _ZN9RObjectIx15AcquireReadLockEv") // call RObjectIx::AquireReadLock
+	asm("ldmfd sp!, {r0-r2,ip,lr} ");	// restore r0-r2, ip and lr
+#else
+	// system lock is held
+#endif
+	
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+// TODO: If handle lookup protected only by RW spin lock, must take a reference on the object
+#endif
+
+	asm("mov r3, r1, lsl #17 ");		// r3=r1<<17 = index(aHandle)<<17
+	asm("mov r1, r1, lsl #2 ");			// r1=instance(Handle)<<18
+	asm("ldr r0, [ip, #%a0]" : : "i" _FOFF(RObjectIx,iCount));		// r0=iCount
+	asm("ldr ip, [ip, #%a0]" : : "i" _FOFF(RObjectIx,iSlots));		// ip=iSlots
+	asm("mov r1, r1, lsr #18 ");		// r1=instance(Handle)
+	asm("cmp r0, r3, lsr #17 ");		// compare iCount with index(aHandle)
+	asm("ldrgt r0, [ip, r3, lsr #14]! ");	// if count>index, r0=pS->uniqueID:pS->instance, ip=iSlots+index(Handle)=pS
+	asm("ble 1f ");						// if count<=index, bad handle
+	asm("adds r3, r2, #1 ");			// r3=0 if any type of object is ok, r3=UID if not
+	asm("biceq r0, r0, r2, lsl #14 ");	// if it is, (r2 therefore -1) clear top 18 bits of r0
+	asm("orr r1, r1, r3, lsl #14 ");	// r1=aUniqueID(bits14-19):instance(Handle)(bits0-13)
+	asm("mov r0, r0, lsl #12 ");		// only interested in comparing lower 20 bits...
+	asm("mov r1, r1, lsl #12 ");
+	asm("cmp r0, r1 ");					// check instance, and unique ID if necessary
+	asm("ldreq r0, [ip, #4] ");			// if OK return pointer to DObject
+	asm("movne r0, #0");				// else r0 = 0
+	asm("mov r2, r0");					// r2 = 0 or pointer(bits2-31):flags(bits0-1)
+	asm("andeq r0, r0, #%a0" : : "i" (RObjectIx::EObjRObjMask));	// r0 = (pointer & EObjRObjMask);
+
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+	asm("stmfd sp!, {r0,r2,ip,lr}");		// save r0, r2, ip and lr
+	asm("mov r0, ip ");					// move RObjectIx this(ip) to r0
+	asm("bl _ZN9RObjectIx15ReleaseReadLockEv") // call RObjectIx::ReleaseReadLock
+	asm("ldmfd sp!, {r0,r2,ip,lr}");		// restore r0, r2, ip and lr
+#else
+	// system lock is held, nothing to do
+#endif
+
+	asm("ldmfd sp!, {r3}");				// restore r3 (r3=&aAttr)
+	asm("cmp r0, #0");					// if r0!=0
+	asm("ldrne r1, [ip]");				//     r1=attributes:pS->uniqueID:pS->instance
+	asm("movne r1, r1, lsr #20");		//     r1=attributes(bits0-11)
+	asm("orrne r1, r1, r2, lsl #31 ");	//     r1=resv_flag(bit31):attributes(bits0-11)
+	asm("strne r1, [r3] ");				//     aAttr=resv_flag(bit31):attributes(bits0-11)
+	
+	// r0 now either 0(EBadHandle) or valid pointer...
+	__JUMP(,lr);
+
+	asm("1: ");
+	asm("add sp, sp, #4");				// pop and discard r3 (not used)
+	asm("mov r0, #0 ");					// if wrong, bad handle
+	__JUMP(,lr);
+	
+	asm("2: ");							// r12=handle<<1 (valid values are fffx0000 and fffx0002, x=e or f)
+	asm("bic ip, ip, #0x10000 ");		// clear 'no close' flag
+#ifdef	__OBSOLETE_V1_IPC_SUPPORT__
+	asm("cmp ip, #0x10000000 ");
+	asm("blo 4f ");						// if handle<0x88000000, it's an IPC client thread pseudo handle
+#endif
+	asm("ldr r0, __TheScheduler ");
+	asm("add ip, ip, #0x20000 ");		// valid values now 0 and 2
+	asm("cmp r2, #1 ");					// r2=container number or -1 if any object OK
+	asm("ldrle r0, [r0, #%a0]" : : "i" _FOFF(TScheduler,iCurrentThread));	// r0->current NThread
+	asm("bgt 1b ");						// if type is neither thread nor process nor any, bad handle
+	asm("beq 3f ");						// skip check for KCurrentThreadHandle if process required
+	asm("cmp ip, #2 ");					// handle = ffff8001 ?
+	asm("subeq r0, r0, #%a0" : : "i" _FOFF(DThread,iNThread));
+	asm("add sp, sp, #4");				// pop and discard r3 (not used)
+	__JUMP(eq,lr);						// if so, return TheCurrentThread
+	asm("cmn r2, #1 ");					// r2=-1 means any type of object will do
+	asm("bne 1b ");
+	asm("3: ");
+	asm("cmp ip, #0 ");					// handle = ffff8000 ?
+	asm("ldreq r0, [r0, #%a0]" : : "i" (_FOFF(DThread,iOwningProcess)-_FOFF(DThread,iNThread)));
+	asm("add sp, sp, #4");				// pop and discard r3 (not used)
+	__JUMP(eq,lr);						// if so, return TheCurrentThread->iOwningProcess
+	asm("b 1b ");						// else bad handle
+
+#ifdef	__OBSOLETE_V1_IPC_SUPPORT__
+	asm("4: ");
+	asm("cmp r2, #0 ");					// type must be thread or any
+	asm("bgt 1b ");						// if not, bad handle
+
+	asm("add sp, sp, #4");				// pop and discard r3 (not used)
+	asm("add r1, r0, #%a0" : : "i" _FOFF(DThread,iNThread));	// r1->iNThread
+	asm("stmfd sp!, {r4,lr} ");
+	asm("bl do_lookup_thread_pseudo ");
+	asm("bcc 6f ");						// skip if bad handle
+	asm("cmp ip, #%a0" : : "i" ((TInt)RMessage2::EDisConnect));	// else check iFunction != RMessage2::EDisConnect
+	asm("ldrne r0, [r0, #%a0]" : : "i" _FOFF(RMessageK,iClient));
+	asm("moveq r0, #0 ");
+	asm("6: ");
+	asm("ldmfd sp!, {r4,pc} ");
+#endif
+	}
+
+__NAKED__ DObject* K::ObjectFromHandle(TInt /*aHandle*/)
+//
+// Look up an object in the current thread/process handles array
+// Panic on bad handle
+// Enter and leave with system locked
+//
+	{
+	// r0=aHandle
+	asm("ldr r1, __TheScheduler ");
+	asm("adds ip, r0, r0 ");			// check for special handle (bit 31 set => special)
+	asm("ldr r1, [r1, #%a0]" : : "i" _FOFF(TScheduler,iCurrentThread));	// r1->current NThread
+	asm("bcs 2f ");						// if not, N flag indicates local handle
+	asm("ldrpl ip, [r1, #%a0]" : : "i" (_FOFF(DThread,iOwningProcess)-_FOFF(DThread,iNThread)));	// if not local, ip=aThread->iOwningProcess
+	asm("addmi ip, r1, #%a0" : : "i" (_FOFF(DThread,iHandles)-_FOFF(DThread,iNThread)));	// if local, ip=&current Thread->iHandles
+	asm("addpl ip, ip, #%a0" : : "i" _FOFF(DProcess,iHandles));		// if not, ip=&current Thread->iOwningProcess->iHandles
+
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+	asm("stmfd sp!, {r0,r1,ip,lr} ");	// save r0, r1, ip and lr
+	asm("mov r0, ip ");					// move RObjectIx this(ip) to r0
+	asm("bl _ZN9RObjectIx15AcquireReadLockEv") // call RObjectIx::AquireReadLock
+	asm("ldmfd sp!, {r0,r1,ip,lr} ");	// restore r0, r1, ip and lr
+#else
+	// system lock is held
+#endif
+	
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+// TODO: If handle lookup protected only by RW spin lock, must take a reference on the object
+#endif
+
+	asm("mov r3, r0, lsl #17 ");		// r3=r0<<17 = index(aHandle)<<17
+	asm("mov r1, r0, lsl #2 ");			// r1=instance(Handle)<<18
+	asm("ldr r0, [ip, #%a0]" : : "i" _FOFF(RObjectIx,iCount));		// r0=iCount
+	asm("ldr ip, [ip, #%a0]" : : "i" _FOFF(RObjectIx,iSlots));	// ip=iSlots
+	asm("subs r0, r0, r3, lsr #17 ");	// r0 = iCount - index(aHandle) - 1
+	asm("ldrge r2, [ip, r3, lsr #14]! ");	// if count-1>=index, r2=pS->uniqueID:pS->instance, ip=iSlots+index(Handle)=pS ...
+	asm("ldrge r0, [ip, #4] ");			// ... and r0 = pointer to DObject ...
+	asm("andge r0, r0, #%a0" : : "i" (RObjectIx::EObjRObjMask));	// r0 = (pointer & EObjRObjMask);
+	asm("eorge r1, r1, r2, lsl #18 ");	// ... and check if instance(aHandle)<<18 == pS->(uid:instance)<<18
+	asm("movges r1, r1, lsr #18 ");
+	asm("movne r0, #0");				// ... else r0 = 0
+
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+	asm("stmfd sp!, {r0,ip,lr} ");	// save r0, ip and lr
+	asm("mov r0, ip ");					// move RObjectIx this(ip) to r0
+	asm("bl _ZN9RObjectIx15ReleaseReadLockEv") // call RObjectIx::ReleaseReadLock
+	asm("ldmfd sp!, {r0,ip,lr} ");	// restore r0, ip and lr
+#else
+	// system lock is held, nothing to do
+#endif
+
+	asm("cmp r0, #0 ");					// check if this is a valid pointer
+	__JUMP(ne,lr);						// if OK, return pointer to DObject
+
+	asm("1: ");							// if wrong, bad handle
+	asm("mov r0, #%a0" : : "i" (EBadHandle));
+	asm("b  " CSM_ZN1K18PanicCurrentThreadEi);
+	
+	asm("2: ");							// r12=handle<<1 (valid values are fffx0000 and fffx0002, x=e or f)
+	asm("bic ip, ip, #0x10000 ");		// clear 'no close' flag
+#ifdef	__OBSOLETE_V1_IPC_SUPPORT__
+	asm("cmp ip, #0x10000000 ");
+	asm("blo 3f ");						// if handle<0x88000000, it's an IPC client thread pseudo handle
+#endif
+	asm("adds ip, ip, #0x20000 ");		// valid values now 0 and 2
+	asm("ldreq r0, [r1, #%a0]" : : "i" (_FOFF(DThread,iOwningProcess)-_FOFF(DThread,iNThread)));
+	__JUMP(eq,lr);						// if handle = ffff8000, return TheCurrentThread->iOwningProcess
+	asm("cmp ip, #2 ");					// otherwise, handle = ffff8001 ?
+	asm("subeq r0, r1, #%a0" : : "i" _FOFF(DThread,iNThread));
+	__JUMP(eq,lr);						// if so, return TheCurrentThread
+	asm("b 1b ");						// else bad handle
+
+#ifdef	__OBSOLETE_V1_IPC_SUPPORT__
+	asm("k_pseudo_4: ");
+	asm("cmp r1, #0 ");					// type must be thread or any
+	asm("bgt 1b ");						// if not, panic
+	asm("mov r1, r2 ");					// r1->current NThread
+
+	asm("3: ");
+	asm("stmfd sp!, {r4,lr} ");
+	asm("bl do_lookup_thread_pseudo ");
+	asm("bcc 1b ");						// panic if bad
+	asm("cmp ip, #%a0" : : "i" ((TInt)RMessage2::EDisConnect));	// else check iFunction != RMessage2::EDisConnect
+	asm("ldrne r0, [r0, #%a0]" : : "i" _FOFF(RMessageK,iClient));
+	asm("ldmnefd sp!, {r4,pc} ");
+	asm("b 1b ");
+#endif
+	}
+
+__NAKED__ DObject* K::ObjectFromHandle(TInt /*aHandle*/, TInt /*aType*/)
+//
+// Look up an object of specific type in the current thread/process handles array
+// Panic on bad handle
+// Enter and leave with system locked
+//
+	{
+	// r0=aHandle, r1=aType (-1=any, 0=thread, etc.)
+	asm("ldr r2, __TheScheduler ");
+	asm("adds ip, r0, r0 ");			// check for special handle (bit 31 set => special)
+	asm("ldr r2, [r2, #%a0]" : : "i" _FOFF(TScheduler,iCurrentThread));	// r2->current NThread
+	asm("bcs 2f ");						// if not, N flag indicates local handle
+	asm("ldrpl ip, [r2, #%a0]" : : "i" (_FOFF(DThread,iOwningProcess)-_FOFF(DThread,iNThread)));	// if not local, ip=aThread->iOwningProcess
+	asm("addmi ip, r2, #%a0" : : "i" (_FOFF(DThread,iHandles)-_FOFF(DThread,iNThread)));		// if local, ip=&aThread->iHandles
+	asm("addpl ip, ip, #%a0" : : "i" _FOFF(DProcess,iHandles));		// if not, ip=&aThread->iOwningProcess->iHandles
+
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+	asm("stmfd sp!, {r0,r1,ip,lr} ");	// save r0, r1, ip and lr
+	asm("mov r0, ip ");					// move RObjectIx this(ip) to r0
+	asm("bl _ZN9RObjectIx15AcquireReadLockEv") // call RObjectIx::AquireReadLock
+	asm("ldmfd sp!, {r0,r1,ip,lr} ");	// restore r0, r1, ip and lr
+#else
+	// system lock is held
+#endif
+	
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+// TODO: If handle lookup protected only by RW spin lock, must take a reference on the object
+#endif
+
+	asm("mov r3, r0, lsl #17 ");		// r3=r0<<17 = index(aHandle)<<17
+	asm("mov r2, r0, lsl #2 ");			// r2=instance(Handle)<<18
+	asm("ldr r0, [ip, #%a0]" : : "i" _FOFF(RObjectIx,iCount));		// r0=iCount
+	asm("ldr ip, [ip, #%a0]" : : "i" _FOFF(RObjectIx,iSlots));	// ip=iSlots
+	asm("mov r2, r2, lsr #18 ");		// r2=instance(Handle)
+	asm("cmp r0, r3, lsr #17 ");		// compare iCount with index(aHandle)
+	asm("ldrgt r0, [ip, r3, lsr #14]! ");	// if count>index, r0=pS->uniqueID:pS->instance, ip=iSlots+index(Handle)=pS
+	asm("ble 1f ");						// if count<=index, bad handle
+	asm("adds r3, r1, #1 ");			// r3=0 if any type of object is ok, r3=UID if not
+	asm("biceq r0, r0, r1, lsl #14 ");	// if it is, (therefore r1=-1) clear top 18 bits of r0
+	asm("orr r2, r2, r3, lsl #14 ");	// r2=aUniqueID(bits14-19):instance(Handle)(bits0-13)
+	asm("mov r0, r0, lsl #12 ");		// only interested in comparing lower 20 bits...
+	asm("mov r2, r2, lsl #12 ");
+	asm("cmp r0, r2 ");					// check instance, and unique ID if necessary
+	asm("ldreq r0, [ip, #4] ");			// if OK return pointer to DObject
+	asm("movne r0, #0");				// else r0 = 0
+	asm("andeq r0, r0, #%a0" : : "i" (RObjectIx::EObjRObjMask));	// r0 = (pointer & EObjRObjMask);
+
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+	asm("stmfd sp!, {r0,ip,lr} ");	// save r0, ip and lr
+	asm("mov r0, ip ");					// move RObjectIx this(ip) to r0
+	asm("bl _ZN9RObjectIx15ReleaseReadLockEv") // call RObjectIx::ReleaseReadLock
+	asm("ldmfd sp!, {r0,ip,lr} ");	// restore r0, ip and lr
+#else
+	// system lock is held, nothing to do
+#endif
+
+	asm("cmp r0, #0 ");					// check if this is a valid pointer
+	__JUMP(ne,lr);						// if OK, return pointer to DObject
+
+	asm("1: ");							// if wrong, bad handle
+	asm("mov r0, #%a0" : : "i" (EBadHandle));
+	asm("b  " CSM_ZN1K18PanicCurrentThreadEi);
+	
+	asm("2: ");							// r12=handle<<1 (valid values are fffx0000 and fffx0002, x=e or f)
+	asm("bic ip, ip, #0x10000 ");		// clear 'no close' flag
+#ifdef	__OBSOLETE_V1_IPC_SUPPORT__
+	asm("cmp ip, #0x10000000 ");
+	asm("blo k_pseudo_4 ");				// if handle<0x88000000, it's an IPC client thread pseudo handle
+#endif
+	asm("adds ip, ip, #0x20000 ");		// valid values now 0 and 2
+	asm("cmp r1, #1 ");					// r1=container number or -1 if any object OK
+	asm("bgt 1b ");						// if type is neither thread nor process nor any, bad handle
+	asm("beq 3f ");						// skip check for KCurrentThreadHandle if process required
+	asm("cmp ip, #2 ");					// handle = ffff8001 ?
+	asm("subeq r0, r2, #%a0" : : "i" _FOFF(DThread,iNThread));
+	__JUMP(eq,lr);						// if so, return TheCurrentThread
+	asm("cmn r1, #1 ");					// r1=-1 means any type of object will do
+	asm("bne 1b ");
+	asm("3: ");
+	asm("cmp ip, #0 ");					// handle = ffff8000 ?
+	asm("ldreq r0, [r2, #%a0]" : : "i" (_FOFF(DThread,iOwningProcess)-_FOFF(DThread,iNThread)));
+	__JUMP(eq,lr);						// if so, return TheCurrentThread->iOwningProcess
+	asm("b 1b ");						// else bad handle
+	}
+
+__NAKED__ DObject* K::ObjectFromHandle(TInt /*aHandle*/, TInt /*aObjType*/, TUint& /*aAttr*/)
+//
+// Look up an object of specific type in the current thread/process handles array
+// Panic on bad handle
+// Enter and leave with system locked
+//
+	{
+	// r0=aHandle, r1=aObjType (-1=any, 0=thread, etc.), r2=&aAttr
+	asm("stmfd sp!, {r2}");				// save r2
+	asm("ldr r2, __TheScheduler ");
+	asm("adds ip, r0, r0 ");			// check for special handle (bit 31 set => special)
+	asm("ldr r2, [r2, #%a0]" : : "i" _FOFF(TScheduler,iCurrentThread));	// r2->current NThread
+	asm("bcs 2f ");						// if not, N flag indicates local handle
+	asm("ldrpl ip, [r2, #%a0]" : : "i" (_FOFF(DThread,iOwningProcess)-_FOFF(DThread,iNThread)));	// if not local, ip=aThread->iOwningProcess
+	asm("addmi ip, r2, #%a0" : : "i" (_FOFF(DThread,iHandles)-_FOFF(DThread,iNThread)));		// if local, ip=&aThread->iHandles
+	asm("addpl ip, ip, #%a0" : : "i" _FOFF(DProcess,iHandles));		// if not, ip=&aThread->iOwningProcess->iHandles
+
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+	asm("stmfd sp!, {r0,r1,ip,lr} ");	// save r0, r1, ip and lr
+	asm("mov r0, ip ");					// move RObjectIx this(ip) to r0
+	asm("bl _ZN9RObjectIx15AcquireReadLockEv") // call RObjectIx::AquireReadLock
+	asm("ldmfd sp!, {r0,r1,ip,lr} ");	// restore r0, r1, ip and lr
+#else
+	// system lock is held
+#endif
+	
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+// TODO: If handle lookup protected only by RW spin lock, must take a reference on the object
+#endif
+
+	asm("mov r3, r0, lsl #17 ");		// r3=r0<<17 = index(aHandle)<<17
+	asm("mov r2, r0, lsl #2 ");			// r2=instance(Handle)<<18
+	asm("ldr r0, [ip, #%a0]" : : "i" _FOFF(RObjectIx,iCount));		// r0=iCount
+	asm("ldr ip, [ip, #%a0]" : : "i" _FOFF(RObjectIx,iSlots));	// ip=iSlots
+	asm("mov r2, r2, lsr #18 ");		// r2=instance(Handle)
+	asm("cmp r0, r3, lsr #17 ");		// compare iCount with index(aHandle)
+	asm("ldrgt r0, [ip, r3, lsr #14]! ");	// if count>index, r0=pS->uniqueID:pS->instance, ip=iSlots+index(Handle)=pS
+	asm("ble 1f ");						// if count<=index, bad handle
+	asm("adds r3, r1, #1 ");			// r3=0 if any type of object is ok, r3=UID if not
+	asm("biceq r0, r0, r1, lsl #14 ");	// if it is, (therefore r1=-1) clear top 18 bits of r0
+	asm("orr r2, r2, r3, lsl #14 ");	// r2=aUniqueID(bits14-19):instance(Handle)(bits0-13)
+	asm("mov r0, r0, lsl #12 ");		// only interested in comparing lower 20 bits...
+	asm("mov r2, r2, lsl #12 ");
+	asm("cmp r0, r2 ");					// check instance, and unique ID if necessary
+	asm("ldreq r0, [ip, #4] ");			// if OK return pointer to DObject
+	asm("movne r0, #0");				// else r0 = 0
+	asm("mov r3, r0");					// r3=0 or pointer(bits2-31):flags(bits0-1)
+	asm("andeq r0, r0, #%a0" : : "i" (RObjectIx::EObjRObjMask));	// r0 = (pointer & EObjRObjMask);
+
+#ifdef __HANDLES_USE_RW_SPIN_LOCK__
+	asm("stmfd sp!, {r0,r3,ip,lr} ");	// save r0, r3, ip and lr
+	asm("mov r0, ip ");					// move RObjectIx this(ip) to r0
+	asm("bl _ZN9RObjectIx15ReleaseReadLockEv") // call RObjectIx::ReleaseReadLock
+	asm("ldmfd sp!, {r0,r3,ip,lr} ");	// restore r0, r3, ip and lr
+#else
+	// system lock is held, nothing to do
+#endif
+
+	asm("ldmfd sp!, {r2}");				// restore r2 (r2=&aAttr)
+	asm("cmp r0, #0");					// if r0!=0
+	asm("ldrne r1, [ip]");				//     r1=attributes:pS->uniqueID:pS->instance
+	asm("movne r1, r1, lsr #20");		//     r1=attributes(bits0-11)
+	asm("orrne r1, r1, r3, lsl #31 ");	//     r1=resv_flag(bit31):attributes(bits0-11)
+	asm("strne r1, [r2] ");				//     aAttr=resv_flag(bit31):attributes(bits0-11)
+	
+	__JUMP(ne,lr);						//     return pointer to DObject
+
+	asm("1: ");							// if wrong, bad handle
+	asm("mov r0, #%a0" : : "i" (EBadHandle));
+	asm("b  " CSM_ZN1K18PanicCurrentThreadEi);
+	
+	asm("2: ");							// r12=handle<<1 (valid values are fffx0000 and fffx0002, x=e or f)
+	asm("add sp, sp, #4");				// pop and discard r2 (not used)
+	asm("bic ip, ip, #0x10000 ");		// clear 'no close' flag
+#ifdef	__OBSOLETE_V1_IPC_SUPPORT__
+	asm("cmp ip, #0x10000000 ");
+	asm("blo k_pseudo_4 ");				// if handle<0x88000000, it's an IPC client thread pseudo handle
+#endif
+	asm("adds ip, ip, #0x20000 ");		// valid values now 0 and 2
+	asm("cmp r1, #1 ");					// r1=container number or -1 if any object OK
+	asm("bgt 1b ");						// if type is neither thread nor process nor any, bad handle
+	asm("beq 3f ");						// skip check for KCurrentThreadHandle if process required
+	asm("cmp ip, #2 ");					// handle = ffff8001 ?
+	asm("subeq r0, r2, #%a0" : : "i" _FOFF(DThread,iNThread));
+	__JUMP(eq,lr);						// if so, return TheCurrentThread
+	asm("cmn r1, #1 ");					// r1=-1 means any type of object will do
+	asm("bne 1b ");
+	asm("3: ");
+	asm("cmp ip, #0 ");					// handle = ffff8000 ?
+	asm("ldreq r0, [r2, #%a0]" : : "i" (_FOFF(DThread,iOwningProcess)-_FOFF(DThread,iNThread)));
+	__JUMP(eq,lr);						// if so, return TheCurrentThread->iOwningProcess
+	asm("b 1b ");						// else bad handle
+	}
+#endif
+
+/**	Returns the current state of interrupts
+	
+	@param	aRequest indicates which state of interrupts should be returned
+			
+	@return if aRequest is ETrue, function returns ETrue if interrupts are enabled and EFalse otherwise
+			if aRequest is EFalse, function returns ETrue if interrupts are disabled and EFalse otherwise
+*/
+__NAKED__ TBool InterruptsStatus(TBool)
+	{
+	asm("cmp r0, #0 ");
+	asm("beq check_interrupts_disabled ");
+	//check that ints are enabled
+	asm("mrs r0, cpsr ");
+	asm("ands r0, r0, #%a0 " : : "i" ((TInt)KAllInterruptsMask));
+	asm("moveq r0,#1");				
+	asm("movne r0,#0");				
+	__JUMP(,lr);
+	asm("check_interrupts_disabled: ");	
+	asm("mrs r0, cpsr ");
+	asm("and r0, r0, #%a0 " : : "i" ((TInt)KAllInterruptsMask));
+	asm("cmp r0, #%a0 " : : "i" ((TInt)KAllInterruptsMask));
+	asm("moveq r0,#1");				
+	asm("movne r0,#0");				
+	__JUMP(,lr);
+	}
+
+extern "C" EXPORT_C __NAKED__ void pagecpy(TAny* /*aTrg*/, const TAny* /*aSrc*/)
+	{
+	// Source and destination 4k page aligned (and thus cache aligned)
+	// Fixed copy size of 4k
+	//  - easy as pie
+	asm("mov r2, #12 ");
+	// fall through to fastcpy
+	}
+
+extern "C" __NAKED__ void fastcpy(TAny* /*aTrg*/, const TAny* /*aSrc*/, TUint8 /*aPower*/)
+	{
+	asm("stmfd sp!, {r4-r9} ");
+	asm("mov ip, #-1 ");
+	asm("mvn ip, ip, lsl r2 ");
+	asm("pagecpy_loop: ");
+	PLD_ioff(1, 32);
+	PLD_ioff(1, 64);
+	asm("ldmia r1!, {r2-r9} ");
+	asm("stmia r0!, {r2-r9} ");
+	asm("ldmia r1!, {r2-r9} ");
+	asm("tst r1, ip ");
+	asm("stmia r0!, {r2-r9} ");
+	asm("bne pagecpy_loop ");
+	asm("ldmfd sp!, {r4-r9} ");
+	__JUMP(,lr);
+
+
+	asm("__TheScheduler: ");
+	asm(".word TheScheduler ");
+	}
+
+#if defined(__MEMMODEL_MOVING__) || defined(__MEMMODEL_MULTIPLE__)
+__NAKED__ TInt MmuBase::MoveKernelStackPage(DChunk* /*aChunk*/, TUint32 /*aOffset*/, TPhysAddr /*aOld*/,
+		TPhysAddr& /*aNew*/, TUint /*aBlockZoneId*/, TBool /*aBlockRest*/)
+	{
+	// Switch to a safe stack then call the regular MoveKernelPage
+	
+	asm("mov ip, sp ");
+	asm("ldr sp, [r0, #%a0]" : : "i" _FOFF(MmuBase,iAltStackBase));		// r0=this
+	asm("stmfd sp!, {ip,lr} ");
+	asm("ldr lr, [ip, #8] ");
+	asm("str lr, [sp, #-8]! ");
+	asm("ldr lr, [ip, #4] ");
+	asm("str lr, [sp, #-4]! ");
+	asm("ldr lr, [ip] ");
+	asm("str lr, [sp, #-4]! ");
+	asm("bl " CSM_ZN3Mmu14MoveKernelPageEP6DChunkmmRmji);
+	asm("ldmfd sp, {r1,r2,r3,ip,sp,pc} ");
+	}
+#endif
+
+__NAKED__ TInt K::FloatingPointSystemId(TUint32& /*aSysId*/)
+	{
+#if __CPU_HAS_VFP
+	VFP_FMRX(,1,VFP_XREG_FPSID);
+	asm("str r1, [r0] ");
+	asm("mov r0, #0 ");
+#else
+	asm("mov r0, #%a0 " : : "i" ((TInt)KErrNotSupported));
+#endif
+	__JUMP(,lr);
+	}
+
+#ifdef __CLIENT_REQUEST_MACHINE_CODED__
+
+__NAKED__ void TServerMessage::CallbackFunc(TAny* aData, TUserModeCallbackReason aReason)
+	{
+	// r0 -> TClientRequest object
+	// r1 == reason code: 0 => run, 1 => cancel
+
+	asm("ldr r3, [r0, #%a0]" : : "i" _FOFF(TClientRequest, iResult));
+	asm("teq r1, #%a0" : : "i" (EUserModeCallbackRun));
+	asm("teqeq r3, #0");					// iResult == KErrNone
+	asm("bne clientRequestCallback2");
+	asm("ldr ip, [r0, #%a0]" : : "i" _FOFF(TServerMessage, iMessagePtr));
+	asm("stmfd sp!, {r0, r4-r7}");
+	asm("ldr r0, [r0, #%a0]" : : "i" _FOFF(TServerMessage, iMessageData));
+	asm("mov r6, #0");
+	asm("ldr r1, [r0, #%a0]" : : "i" _FOFF(RMessageK, iFunction));
+	asm("ldr r7, [r0, #%a0]" : : "i" _FOFF(RMessageK, iSession));
+	asm("cmn r1, #%a0" : : "i" (-RMessage2::EDisConnect));
+	asm("beq setupDisconnect");
+
+	// HARDCODED(RMessageK)- this assumes KMaxMessageArguments is 4
+	asm("add r2, r0, #%a0" : : "i" _FOFF(RMessageK, iMsgArgs.iArgs));
+	asm("ldmia r2, {r2-r5}");
+
+	asm("userWrite:");						// NOTE: Z flag always clear here
+	asm("ldr r7, [r7, #%a0]" : : "i" _FOFF(DSession, iSessionCookie));
+#ifdef __USER_MEMORY_GUARDS_ENABLED__
+	asm("stmdb sp!,{r12}");
+	USER_MEMORY_GUARD_OFF(,r12,r12);
+	asm("ldmia sp!,{r12}");
+#endif
+	// HARDCODED(RMessage2)- this assumes the layout of the first 8 words of this structure
+	asm(".global __magic_address_svr_accept_1 ");
+	asm("__magic_address_svr_accept_1: ");	// this instruction is magically immune from exceptions
+	asm("strt r0, [ip], #4");
+	asm(".global __magic_address_svr_accept_2 ");
+	asm("__magic_address_svr_accept_2: ");	// this instruction is magically immune from exceptions
+	asm("strnet r1, [ip], #4");
+	asm(".global __magic_address_svr_accept_3 ");
+	asm("__magic_address_svr_accept_3: ");	// this instruction is magically immune from exceptions
+	asm("strnet r2, [ip], #4");
+	asm(".global __magic_address_svr_accept_4 ");
+	asm("__magic_address_svr_accept_4: ");	// this instruction is magically immune from exceptions
+	asm("strnet r3, [ip], #4");
+	asm(".global __magic_address_svr_accept_5 ");
+	asm("__magic_address_svr_accept_5: ");	// this instruction is magically immune from exceptions
+	asm("strnet r4, [ip], #4");
+	asm(".global __magic_address_svr_accept_6 ");
+	asm("__magic_address_svr_accept_6: ");	// this instruction is magically immune from exceptions
+	asm("strnet r5, [ip], #4");
+	asm(".global __magic_address_svr_accept_7 ");
+	asm("__magic_address_svr_accept_7: ");	// this instruction is magically immune from exceptions
+	asm("strnet r6, [ip], #4");
+	asm(".global __magic_address_svr_accept_8 ");
+	asm("__magic_address_svr_accept_8: ");	// this instruction is magically immune from exceptions
+	asm("strnet r7, [ip], #4");
+	USER_MEMORY_GUARD_ON(,r12,r12);
+	asm("ldmfd sp!, {r0, r4-r7}");
+	asm("mov r1, #%a0" : : "i" (EUserModeCallbackRun));
+	asm("mov r3, #0" );
+	asm("b clientRequestCallback2");
+
+	asm("setupDisconnect:");
+	asm("mov r2, #0");
+	asm("mov r3, #0");
+	asm("mov r4, #0");
+	asm("mov r5, #0");
+	asm("cmp r5, #1"); // clear zero flag
+	asm("b userWrite");
+ 	}
+
+__NAKED__ void TClientRequest::CallbackFunc(TAny* /*aData*/, TUserModeCallbackReason /*aReason*/)
+	{
+	// parameters:
+	//   r0 -> this
+	//   r1 == reason code
+	// locals:
+	//   r2 == old status
+	//   r3 == result 
+
+	asm("clientRequestCallback:");
+	asm("ldr r3, [r0, #%a0]" : : "i" _FOFF(TClientRequest, iResult));
+	asm("clientRequestCallback2:");
+	asm("stmfd sp!, {r0, r1, r3, lr} ");
+#ifdef _DEBUG
+	ASM_CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL);
+#endif
+	asm("mov ip, #%a0" : : "i" ((TInt)KRequestPending));
+	asm("str ip, [r0, #%a0]" : : "i" _FOFF(TClientRequest, iResult));
+	asm("mov r1, #%a0" : : "i" ((TInt)KClientRequestFlagClosing));
+	asm("add r0, r0, #%a0 " : : "i" _FOFF(TClientRequest, iStatus));
+	asm("bl __e32_atomic_and_ord32 ");
+	asm("mov r2, r0 ");
+	asm("ldmfd sp!, {r0, r1, r3, lr} ");
+	
+#ifdef _DEBUG
+	asm("teq r2, #0");
+	asm("tstne r2, #%a0" : : "i" ((TInt)KClientRequestFlagInUse));
+	asm("moveq r0, #%a0" : : "i" (K::EClientRequestCallbackInWrongState));
+	asm("bleq " CSM_ZN1K5FaultENS_6TFaultE);
+#endif	
+	USER_MEMORY_GUARD_OFF(,r12,r12);
+	asm("bic r12, r2, #%a0 " : : "i" ((TInt)KClientRequestFlagMask));
+	asm("teq r12, #%a0 " : : "i" ((TInt)KClientRequestNullStatus));
+	asm("teqne r1, #%a0" : : "i" (EUserModeCallbackCancel));
+	asm(".global __magic_address_client_request_callback ");
+	asm("__magic_address_client_request_callback: ");		// this instruction is magically immune from exceptions
+	asm("strnet r3, [r12]");
+	USER_MEMORY_GUARD_ON(,r12,r12);	
+	asm("tst r2, #%a0" : : "i" ((TInt)KClientRequestFlagClosing));
+	asm("bne " CSM_ZN4Kern9AsyncFreeEPv);
+	__JUMP(,lr);
+	}
+#endif
+
+#ifdef __REQUEST_COMPLETE_MACHINE_CODED__
+
+#ifndef __MEMMODEL_FLEXIBLE__
+__NAKED__ EXPORT_C void Kern::RequestComplete(DThread* /*aThread*/, TRequestStatus*& /*aStatus*/, TInt /*aReason*/)
+	{
+	ASM_CHECK_PRECONDITIONS(MASK_THREAD_STANDARD);
+	ASM_ASSERT_DATA_PAGING_SAFE;	// Assembler version needs paging check, c++ version calls RawWrite which checks already
+
+	ASM_DEBUG2(KernRequestComplete,r0,lr);
+
+	asm("stmfd	sp!, {r0-r2,lr} ");
+	asm("bl "	CSM_ZN5NKern10LockSystemEv);
+	asm("ldmfd	sp!, {r0-r2,lr} ");
+	asm("ldr	r3, [r1] ");
+	asm("teq	r3, #0 ");
+	asm("beq "	CSM_ZN5NKern12UnlockSystemEv);
+	asm("mov	r12, #0 ");
+	asm("str	r12, [r1] ");				// aStatus=NULL
+	asm("b		_asm_RequestComplete ");	// call into DThread::RequestComplete with r3 == status ptr
+	}
+#endif
+
+__NAKED__ EXPORT_C void Kern::RequestComplete(TRequestStatus*& /*aStatus*/, TInt /*aReason*/)
+	{
+	ASM_CHECK_PRECONDITIONS(MASK_KERNEL_UNLOCKED | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC);
+
+	asm("mov	r12, #0 ");
+#ifdef __CPU_ARM_HAS_LDREX_STREX
+	asm("1:		");
+	LDREX(		2, 0);			// read	
+	STREX(		3, 12, 0);		// write
+	asm("teq	r3, #0 ");		// success?
+	asm("bne	1b ");			// no!
+#else
+	asm("swp	r2, r12, [r0] ");
+#endif
+	asm("ldr	r3, __TheScheduler ");
+	asm("teq	r2, #0 ");		// clear zero flag if address is not null
+	USER_MEMORY_GUARD_OFF(,r0,r0);
+	asm(".global __magic_address_kern_request_complete ");
+	asm("__magic_address_kern_request_complete: ");   // this instruction is magically immune from exceptions
+	asm("strnet	r1, [r2] ");
+	USER_MEMORY_GUARD_ON(,r0,r0);
+	__JUMP(		eq, lr);		// return if address zero or store failed
+	asm("ldr	r0, [r3, #%a0]" : : "i" _FOFF(TScheduler,iCurrentThread));	// r0->current NThread
+	asm("b "	CSM_ZN5NKern19ThreadRequestSignalEP7NThread);
+	}
+
+#endif
+
+extern "C" __NAKED__ TInt read_and_parse_des_header_local(TAny* aUnused, TAny* aDesPtr, TDesHeader& aOut)
+	{
+	asm("mov r0, r1 ");
+	asm("mov r1, r2 ");
+	// fall through
+	}
+
+/**
+Read the header of a user-side descriptor in the current process, parse it, and populate a
+TDesHeader with the result.
+
+@param aDesPtr The descriptor for which information is to be fetched.
+@param aOut    On return, set to the parsed contents of the descriptor header.
+
+@return KErrNone if successful, or one of the system-wide error codes.
+
+@pre  Interrupts must be enabled.
+@pre  Kernel must be unlocked.
+@pre  No fast mutex can be held.
+@pre  Call in a thread context.
+@pre  Can be used in a device driver.
+*/
+__NAKED__ TInt K::USafeReadAndParseDesHeader(TAny* aDesPtr, TDesHeader& aOut)
+	{
+	// r0  -> user-side descriptor
+	// r1  -> parsed header out
+
+	asm("stmfd sp!, {lr} ");
+
+	USER_MEMORY_GUARD_OFF(,r12,r12);
+	
+	// set condition codes to 'hi' condition (unless we're reading a null pointer)
+	asm("cmp r0, #0");
+
+	// read first word of descriptor...
+	asm(".global __magic_address_readdesheader1 ");
+	asm("__magic_address_readdesheader1: ");			// this instruction is magically immune from exceptions
+	asm("ldrhit r2, [r0], #4");							// WILL SET Z FLAG AND MODIFY R12 IF EXCEPTION OCCURS
+
+	// r12 = length of this descriptor type...
+	asm("adrhi r12, LengthLookup");
+	asm("ldrhib r12, [r12, r2, lsr #28]");
+	asm("cmphi r12, #0");								// set zero flag for invalid descriptor type
+	// r3 = 2nd word of descriptor (if it is 8 bytes or more in size)...
+	asm("cmphi r12, #7");
+	asm(".global __magic_address_readdesheader2 ");
+	asm("__magic_address_readdesheader2: ");			// this instruction is magically immune from exceptions
+	asm("ldrhit r3, [r0], #4");							// WILL SET Z FLAG AND MODIFY R12 IF EXCEPTION OCCURS
+
+	// r12 = 3rd word of descriptor (if it is 12 bytes or more in size)...
+	asm("cmphi r12, #11");
+	asm(".global __magic_address_readdesheader3 ");
+	asm("__magic_address_readdesheader3: ");			// this instruction is magically immune from exceptions
+	asm("ldrhit r12, [r0], #4");						// WILL SET Z FLAG AND MODIFY R12 IF EXCEPTION OCCURS
+
+#ifdef __USER_MEMORY_GUARDS_ENABLED__
+	asm("str	r12, [sp, #-4]! ");
+	USER_MEMORY_GUARD_ON(,r12,r12);
+	asm("ldr	r12, [sp], #4 ");
+#endif
+	
+	asm("beq bad_descriptor ");			// Z flag set here if we took an exception
+	
+	asm("eor r14, r2, r2, lsr #1 ");
+	asm("msr cpsr_flg, r14 ");
+
+	                                    // r12 == header_in[2]
+	asm("movcc r12, r3 ");				// r12 = header_in[1] if EBufC, EPtrC
+	asm("movgt r12, r0 ");				// r12 = pointer to word after header if EBufC, EBuf
+	asm("addeq r12, r12, #4 ");			// r12 += sizeof(TDesC) if EBufCPtr
+
+	                                    // r3 == header_in[1]
+	                                    // r3 = KErrBadDescriptor if EBufC, EPtrC
+	asm("mvncc r3, #%a0" : : "i" (~TDesHeader::KConstMaxLength));  
+
+	                                    // r0 is an aligned pointer
+	asm("moveq r0, r12 ");              // r0 = pointer to des data if EBufCPtr
+	asm("tst r0, #3 ");                 // if (type == EBufCPtr && ((TUint)p & 3) != 0)
+	asm("bne bad_descriptor ");			//     return KErrBadDescriptor;
+	
+	asm("bic r14, r2, #0xf0000000 ");
+	asm("cmp r14, r3 ");				// if (len > max)
+	asm("bhi bad_descriptor ");			//     return KErrBadDescriptor;
+	
+	asm("stmia r1, {r2,r3,r12}");
+	asm("mov r0, #0 ");
+ 	__POPRET("");
+
+	asm("bad_descriptor: ");
+	asm("mvn r0, #%a0" : : "i" (~KErrBadDescriptor));
+ 	__POPRET("");
+	
+	asm("LengthLookup:");
+	asm(".byte 4,8,12,8,12,0,0,0,0,0,0,0,0,0,0,0");
+	}
+
+#ifdef __SMP__
+extern TSpinLock BTraceFilter2Lock;
+
+__NAKED__ TBool DBTraceFilter2::Check(TUint32 aUid)
+	{
+	asm("DBTraceFilter2_Check: ");
+	asm("stmdb	sp!, {lr}");
+	asm("ldr	r3, [r0,#%a0]" : : "i" _FOFF(DBTraceFilter2,iNumUids));
+	asm("add	r0, r0, #%a0" : : "i" _FOFF(DBTraceFilter2,iUids));
+	asm("mov	r2, #0");
+	asm("0:");
+	asm("cmp	r3, r2");
+	asm("bls	9f");
+	asm("add	r12, r2, r3");
+	asm("mov	r12, r12, asr #1");
+	asm("ldr	lr, [r0, r12, lsl #2]");
+	asm("cmp	r1, lr");
+	asm("addhi	r2, r12, #1");
+	asm("movlo	r3, r12");
+	asm("bne	0b");
+	asm("movs	r0, #1");
+	__POPRET("");
+	asm("9:");
+	asm("movs	r0, #0");
+	__POPRET("");
+	}
+
+
+__NAKED__ TBool SBTraceData::CheckFilter2(TUint32 aUid)
+	{
+	asm("btrace_check_filter2:");
+	// returns r0 = 0 or 1 indicating if trace passed the filter check
+	// returns r2 = trace context id
+
+	asm("stmdb	sp!, {r4-r8,lr}");
+	asm("mov	r4, r0 ");
+	asm("mov	r8, r1 ");
+	asm("mrs	r14, cpsr ");
+	__ASM_CLI();
+	GET_RWNO_TID(,r3);
+	asm("mov	r5, #0 ");			// r5 = TRUE if critical section entered
+	asm("and	r6, r14, #0x0f ");
+	asm("cmp	r6, #3 ");
+	asm("movhi	r6, #2 ");			// r6 = context ID = 1 for FIQ, 2 for IRQ/ABT/UND/SYS
+	asm("bne	1f ");				// branch if not mode_svc
+	asm("ldrb	r12, [r3, #%a0]" : : "i" _FOFF(TSubScheduler,iInIDFC));
+	asm("cmp	r12, #0 ");
+	asm("bne	1f ");				// branch if IDFC
+	asm("ldrb	r12, [r3, #%a0]" : : "i" _FOFF(TSubScheduler,iKernLockCount));
+	asm("ldr	r6, [r3, #%a0]" : : "i" _FOFF(TSubScheduler,iCurrentThread));
+	asm("cmp	r12, #0 ");			// kernel locked?
+	asm("bne	1f ");				// if so, don't enter CS
+	asm("msr	cpsr, r14 ");		// restore interrupts
+	asm("bl "	CSM_ZN5NKern14_ThreadEnterCSEv );
+	asm("mov	r5, #1 ");
+	asm("b		2f ");
+
+	asm("1: ");
+	asm("msr	cpsr, r14 ");		// restore interrupts
+	asm("2: ");						// r6 = context ID, r5 = TRUE if critical section entered
+
+	// DBTraceFilter2::Open()
+	asm("ldr	r0, __BTraceFilter2Lock ");
+	asm("bl "	CSM_ZN9TSpinLock11LockIrqSaveEv );
+	asm("ldr	r7, [r4, #%a0]" : : "i" _FOFF(SBTraceData,iFilter2));
+	asm("cmp	r7, #1 ");
+	asm("ldrhi	r2, [r7, #%a0]" : : "i" _FOFF(DBTraceFilter2,iAccessCount));
+	asm("addhi	r2, r2, #1 ");
+	asm("strhi	r2, [r7, #%a0]" : : "i" _FOFF(DBTraceFilter2,iAccessCount));
+	asm("mov	r1, r0 ");
+	asm("ldr	r0, __BTraceFilter2Lock ");
+	asm("bl "	CSM_ZN9TSpinLock16UnlockIrqRestoreEi );
+	asm("cmp	r7, #1 ");
+	asm("bls	3f ");
+
+	// DBTraceFilter2::Check()
+	asm("mov	r0, r7 ");
+	asm("mov	r1, r8 ");
+	asm("bl		DBTraceFilter2_Check ");
+	asm("mov	r8, r0 ");
+
+	// DBTraceFilter2::Close()
+	asm("ldr	r0, __BTraceFilter2Lock ");
+	asm("bl "	CSM_ZN9TSpinLock11LockIrqSaveEv );
+	asm("ldr	r2, [r7, #%a0]" : : "i" _FOFF(DBTraceFilter2,iAccessCount));
+	asm("ldr	r1, __DBTraceFilter2_iCleanupHead");
+	asm("subs	r2, r2, #1");
+	asm("str	r2, [r7, #%a0]" : : "i" _FOFF(DBTraceFilter2,iAccessCount));
+	asm("ldreq	r2, [r1] ");
+	asm("streq	r7, [r1] ");
+	asm("streq	r2, [r7, #%a0]" : : "i" _FOFF(DBTraceFilter2,iCleanupLink));
+	asm("mov	r1, r0 ");
+	asm("ldr	r0, __BTraceFilter2Lock ");
+	asm("bl "	CSM_ZN9TSpinLock16UnlockIrqRestoreEi );
+	asm("mov	r7, r8 ");		// r7 = result
+	asm("3: ");
+
+	// NKern::ThreadLeaveCS()
+	asm("cmp	r5, #0");
+	asm("blne "	CSM_ZN5NKern14_ThreadLeaveCSEv );
+	asm("mov	r0, r7 ");		// r0 = result
+	asm("mov	r2, r6 ");		// r2 = context id
+	__POPRET("r4-r8,");
+
+	asm("__DBTraceFilter2_iCleanupHead:");
+	asm(".word %a0" : : "i" ((TInt)&DBTraceFilter2::iCleanupHead));
+	asm("__BTraceFilter2Lock: ");
+	asm(".word %a0" : : "i" ((TInt)&BTraceFilter2Lock));
+	}
+#endif
+
+