kernel/eka/nkernsmp/arm/ncutilf.cia
branchRCL_3
changeset 256 c1f20ce4abcf
parent 0 a41df078684a
child 257 3e88ff8f41d5
equal deleted inserted replaced
249:a179b74831c9 256:c1f20ce4abcf
    17 
    17 
    18 #include <e32cia.h>
    18 #include <e32cia.h>
    19 #include <arm.h>
    19 #include <arm.h>
    20 #include <arm_gic.h>
    20 #include <arm_gic.h>
    21 #include <arm_tmr.h>
    21 #include <arm_tmr.h>
    22 
       
    23 
    22 
    24 
    23 
    25 __NAKED__ void Arm::GetUserSpAndLr(TAny*) 
    24 __NAKED__ void Arm::GetUserSpAndLr(TAny*) 
    26 	{
    25 	{
    27 	asm("stmia	r0, {r13, r14}^ ");
    26 	asm("stmia	r0, {r13, r14}^ ");
   285 	__JUMP(,	lr);
   284 	__JUMP(,	lr);
   286 	}
   285 	}
   287 #endif
   286 #endif
   288 
   287 
   289 
   288 
   290 
   289 #if defined(__NKERN_TIMESTAMP_USE_LOCAL_TIMER__)
   291 /** Get the current value of the system timestamp
   290 #error Use of local timer for NKern::Timestamp() no longer supported
   292 
   291 
   293 @publishedPartner
   292 #elif defined(__NKERN_TIMESTAMP_USE_SCU_GLOBAL_TIMER__)
   294 @prototype
   293 // Code to access global timer in Cortex A9 r1p0
   295 */
   294 
       
   295 #ifndef	__CPU_ARM_HAS_GLOBAL_TIMER_BLOCK
       
   296 #error NKern::Timestamp() wants global timer, but global timer not present.
       
   297 #endif
       
   298 
   296 EXPORT_C __NAKED__ TUint64 NKern::Timestamp()
   299 EXPORT_C __NAKED__ TUint64 NKern::Timestamp()
   297 	{
   300 	{
   298 	asm("ldr	r3, __TheScheduler ");
   301 	asm("ldr	r3, __TheScheduler ");
   299 	asm("mrs	r12, cpsr ");				// r12 = saved interrupt mask
   302 	asm("mrs	r12, cpsr ");				// r12 = saved interrupt mask
   300 	asm("ldr	r2, [r3, #%a0]" : : "i" _FOFF(TScheduler,i_LocalTimerAddr));	// r2 points to local timer
   303 	asm("stmfd	sp!, {r4-r7} ");
       
   304 	asm("ldr	r4, [r3, #%a0]" : : "i" _FOFF(TScheduler,iSX.iGlobalTimerAddr));		// r4 points to global timer
   301 	__ASM_CLI();							// disable all interrupts
   305 	__ASM_CLI();							// disable all interrupts
   302 	GET_RWNO_TID(,r3);						// r3 -> TSubScheduler
   306 	asm("ldr	r6, [r3, #%a0]" : : "i" _FOFF(TScheduler,iSX.iCount0));					// r6 = count value of last frequency change (low)
   303 	asm("ldr	r1, [r2, #%a0]" : : "i" _FOFF(ArmLocalTimer,iTimerCount));		// r1 = current timer counter
   307 	asm("ldr	r7, [r3, #%a0]" : : "i" (_FOFF(TScheduler,iSX.iCount0)+4));				// r7 = count value of last frequency change (high)
   304 	asm("ldr	r0, [r3, #%a0]" : : "i" _FOFF(TSubScheduler,i_LastTimerSet));	// r0 = last value written to timer counter
   308 	asm("ldr	r2, [r4, #%a0]" : : "i" _FOFF(ArmGlobalTimer,iTimerCountHigh));			// r2 = current timer counter high word
   305 	asm("ldr	r2, [r3, #%a0]" : : "i" _FOFF(TSubScheduler,i_TimerMultI));		// r2 = scaling factor
   309 
   306 	asm("sub	r0, r0, r1 ");				// elapsed timer ticks since last timestamp sync
   310 	// To read 64 bit timer value, read high, low, high
   307 	asm("umull	r1, r2, r0, r2 ");			// r2:r1 = elapsed ticks * scaling factor
   311 	// If two high values match -> OK, else repeat
   308 	asm("ldr	r0, [r3, #%a0]!" : : "i" _FOFF(TSubScheduler,iLastTimestamp64));	// r0 = last timestamp sync point, low word
   312 	asm("1:		");
   309 	asm("ldr	r3, [r3, #4] ");			// r3 = last timestamp sync point, high word
   313 	asm("mov	r1, r2 ");					// r1 = previous value of timer counter high word
   310 	asm("adds	r1, r1, #0x00800000 ");		// add 2^23 (rounding)
   314 	asm("ldr	r0, [r4, #%a0]" : : "i" _FOFF(ArmGlobalTimer,iTimerCountLow));			// r0 = current timer counter low word
   311 	asm("adcs	r2, r2, #0 ");
   315 	asm("ldr	r2, [r4, #%a0]" : : "i" _FOFF(ArmGlobalTimer,iTimerCountHigh));			// r2 = current timer counter high word
   312 	asm("mov	r1, r1, lsr #24 ");			// divide by 2^24
   316 	asm("mov	r5, r3 ");					// r5 = &TheScheduler
   313 	asm("orr	r1, r1, r2, lsl #8 ");		// r1 = elapsed time since last timestamp sync
   317 	asm("cmp	r1, r2 ");					// high word changed?
       
   318 	asm("bne	1b ");						// if so, retry
       
   319 
       
   320 	// Now have R1:R0 = 64 bit global timer count
       
   321 	asm("ldr	r3, [r5, #%a0]" : : "i" _FOFF(TScheduler,iSX.iGTimerFreqRI.iI.iM));		// r3 = period multiplier
       
   322 	asm("ldrsh	r4, [r5, #%a0]" : : "i" _FOFF(TScheduler,iSX.iGTimerFreqRI.iI.iX));		// r4 = period multiplier shift
       
   323 	asm("subs	r6, r0, r6 ");				// r7:r6 = ticks from last frequency change
       
   324 	asm("sbcs	r7, r1, r7 ");
       
   325 	asm("umull	r0, r1, r6, r3 ");
       
   326 	asm("mov	r2, #0 ");
       
   327 	asm("umlal	r1, r2, r7, r3 ");			// r2:r1:r0 = delta * period multiplier
       
   328 	asm("ldr	r6, [r5, #%a0]!" : : "i" _FOFF(TScheduler,iSX.iTimestamp0));			// r6 = timestamp at last freq change (low)
       
   329 	asm("ldr	r7, [r5, #4] ");														// r7 = timestamp at last freq change (high)
   314 	asm("msr	cpsr, r12 ");				// restore interrupts
   330 	asm("msr	cpsr, r12 ");				// restore interrupts
   315 	asm("adds	r0, r0, r1 ");				// r1:r0 = last timestamp sync point + elapsed time since last timestamp sync
   331 	asm("rsb	r4, r4, #0 ");
   316 	asm("adcs	r1, r3, #0 ");
   332 	asm("rsb	r3, r4, #32 ");
   317 	__JUMP(,lr);
   333 	asm("movs	r0, r0, lsr r4 ");			// rounding bit into C
       
   334 	asm("orr	r0, r0, r1, lsl r3 ");
       
   335 	asm("mov	r1, r1, lsr r4 ");
       
   336 	asm("orr	r1, r1, r2, lsl r3 ");		// r1:r0 = (delta * period multiplier) >> period multiplier shift
       
   337 	asm("adcs	r0, r0, r6 ");				// scaled delta + timestamp at last freq change
       
   338 	asm("adcs	r1, r1, r7 ");
       
   339 	asm("ldmfd	sp!, {r4-r7} ");
       
   340 	__JUMP(,lr);
       
   341 
   318 	asm("__TheScheduler: ");
   342 	asm("__TheScheduler: ");
   319 	asm(".word	%a0" : : "i" ((TInt)&TheScheduler));
   343 	asm(".word	%a0" : : "i" ((TInt)&TheScheduler));
   320 	}
   344 	}
       
   345 
       
   346 // Compensate for a change of frequency of the clocking driving the ARM Global Timer
       
   347 // Call with interrupts disabled
       
   348 __NAKED__ void ArmGlobalTimerFreqChg(const SRatioInv* /*aNewGTimerFreqRI*/)
       
   349 	{
       
   350 	asm("ldr	r3, __TheScheduler ");
       
   351 	asm("stmfd	sp!, {r4-r7} ");
       
   352 	asm("ldr	r4, [r3, #%a0]" : : "i" _FOFF(TScheduler,iSX.iGlobalTimerAddr));		// r4 points to global timer
       
   353 	asm("ldr	r6, [r3, #%a0]" : : "i" _FOFF(TScheduler,iSX.iCount0));					// r6 = count value of last frequency change (low)
       
   354 	asm("ldr	r7, [r3, #%a0]" : : "i" (_FOFF(TScheduler,iSX.iCount0)+4));				// r7 = count value of last frequency change (high)
       
   355 	asm("ldr	r12, [r4, #%a0]" : : "i" _FOFF(ArmGlobalTimer,iTimerCountHigh));		// r12 = current timer counter high word
       
   356 	asm("mov	r5, r3 ");					// r5 = &TheScheduler
       
   357 
       
   358 	// To read 64 bit timer value, read high, low, high
       
   359 	// If two high values match -> OK, else repeat
       
   360 	asm("1:		");
       
   361 	asm("mov	r3, r12 ");					// r3 = previous value of timer counter high word
       
   362 	asm("ldr	r2, [r4, #%a0]" : : "i" _FOFF(ArmGlobalTimer,iTimerCountLow));			// r0 = current timer counter low word
       
   363 	asm("ldr	r12, [r4, #%a0]" : : "i" _FOFF(ArmGlobalTimer,iTimerCountHigh));		// r12 = current timer counter high word
       
   364 	asm("cmp	r3, r12 ");					// high word changed?
       
   365 	asm("bne	1b ");						// if so, retry
       
   366 
       
   367 	// Now have R3:R2 = 64 bit global timer count
       
   368 	asm("str	r2, [r5, #%a0]" : : "i" _FOFF(TScheduler,iSX.iCount0));					// update count value at last frequency change
       
   369 	asm("str	r3, [r5, #%a0]" : : "i" (_FOFF(TScheduler,iSX.iCount0)+4));				// to be equal to current count value
       
   370 	asm("subs	r6, r2, r6 ");				// r7:r6 = ticks (at old frequency) from last frequency change
       
   371 	asm("sbcs	r7, r3, r7 ");
       
   372 	asm("ldr	r3, [r5, #%a0]" : : "i" _FOFF(TScheduler,iSX.iGTimerFreqRI.iI.iM));		// r3 = old period multiplier
       
   373 	asm("ldrsh	r4, [r5, #%a0]" : : "i" _FOFF(TScheduler,iSX.iGTimerFreqRI.iI.iX));		// r4 = old period multiplier shift
       
   374 	asm("ldmia	r0, {r0,r1,r2,r12} ");		// r1:r0=new frequency multiplier, r12:r2=new period multiplier
       
   375 	asm("str	r0, [r5, #%a0]" : : "i" _FOFF(TScheduler,iSX.iGTimerFreqRI.iR.iM));		// update frequency multiplier
       
   376 	asm("str	r1, [r5, #%a0]" : : "i" _FOFF(TScheduler,iSX.iGTimerFreqRI.iR.iX));		// update frequency multiplier
       
   377 	asm("str	r2, [r5, #%a0]" : : "i" _FOFF(TScheduler,iSX.iGTimerFreqRI.iI.iM));		// update period multiplier
       
   378 	asm("str	r12, [r5, #%a0]" : : "i" _FOFF(TScheduler,iSX.iGTimerFreqRI.iI.iX));	// update period multiplier
       
   379 	asm("umull	r0, r1, r6, r3 ");
       
   380 	asm("mov	r2, #0 ");
       
   381 	asm("umlal	r1, r2, r7, r3 ");			// r2:r1:r0 = delta * old period multiplier
       
   382 	asm("ldr	r6, [r5, #%a0]!" : : "i" _FOFF(TScheduler,iSX.iTimestamp0));			// r6 = timestamp at last freq change (low)
       
   383 	asm("ldr	r7, [r5, #4] ");														// r7 = timestamp at last freq change (high)
       
   384 	asm("rsb	r4, r4, #0 ");
       
   385 	asm("rsb	r3, r4, #32 ");
       
   386 	asm("movs	r0, r0, lsr r4 ");			// rounding bit into C
       
   387 	asm("orr	r0, r0, r1, lsl r3 ");
       
   388 	asm("mov	r1, r1, lsr r4 ");
       
   389 	asm("orr	r1, r1, r2, lsl r3 ");		// r1:r0 = (delta * old period multiplier) >> old period multiplier shift
       
   390 	asm("adcs	r0, r0, r6 ");				// scaled delta + timestamp at last freq change
       
   391 	asm("adcs	r1, r1, r7 ");
       
   392 	asm("stmia	r5, {r0,r1} ");				// timestamp at last freq change = now
       
   393 	__DATA_MEMORY_BARRIER_Z__(r12);			/* Ensure all updates visible */
       
   394 	asm("ldmfd	sp!, {r4-r7} ");
       
   395 	__JUMP(,lr);
       
   396 	}
       
   397 
       
   398 #elif defined(__NKERN_TIMESTAMP_USE_INLINE_BSP_CODE__)
       
   399 #define __DEFINE_NKERN_TIMESTAMP_ASM__
       
   400 #include <variant_timestamp.h>
       
   401 #undef __DEFINE_NKERN_TIMESTAMP_ASM__
       
   402 #elif defined(__NKERN_TIMESTAMP_USE_BSP_CALLOUT__)
       
   403 // Code to call function defined in variant
       
   404 #else
       
   405 #error No definition for NKern::Timestamp()
       
   406 #endif
   321 
   407 
   322 
   408 
   323 extern "C" __NAKED__ TLinAddr get_sp_svc()
   409 extern "C" __NAKED__ TLinAddr get_sp_svc()
   324 	{
   410 	{
   325 	asm("mrs	r1, cpsr ");
   411 	asm("mrs	r1, cpsr ");
   357 	asm("msr	cpsr, r1 ");
   443 	asm("msr	cpsr, r1 ");
   358 	__JUMP(,	lr);
   444 	__JUMP(,	lr);
   359 
   445 
   360 	asm("1:		");
   446 	asm("1:		");
   361 	GET_RWNO_TID(,r3);
   447 	GET_RWNO_TID(,r3);
   362 	asm("ldr	r2, [r3, #%a0]" : : "i" _FOFF(TSubScheduler,i_FiqStackTop));	// if so, r2->top of FIQ stack
   448 	asm("ldr	r2, [r3, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iFiqStackTop));	// if so, r2->top of FIQ stack
   363 	asm("ldr	r0, [r2, #-4] ");			// get return address
   449 	asm("ldr	r0, [r2, #-4] ");			// get return address
   364 	asm("msr	cpsr, r1 ");
   450 	asm("msr	cpsr, r1 ");
   365 	__JUMP(,	lr);
   451 	__JUMP(,	lr);
   366 	}
   452 	}
   367 
   453 
   592 	SPIN_LOCK_MARK_ACQ()
   678 	SPIN_LOCK_MARK_ACQ()
   593 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
   679 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
   594 	__JUMP(,lr);
   680 	__JUMP(,lr);
   595 
   681 
   596 	asm("2: ");
   682 	asm("2: ");
       
   683 	asm("ldr	r1, __CrashState ");
   597 	ARM_WFE;
   684 	ARM_WFE;
   598 	asm("ldrb r1, [r0, #0] ");				/* read out count again */
   685 	asm("ldr	r1, [r1] ");				/* check for system crash while we were waiting */
   599 	asm("b 3b ");
   686 	asm("cmp	r1, #0 ");
       
   687 	asm("bne	9f ");
       
   688 	asm("ldrb	r1, [r0, #0] ");			/* read out count again */
       
   689 	asm("b		3b ");
       
   690 	asm("9:		");
       
   691 	__ASM_CRASH();							/* system crashed while we were waiting */
   600 	}
   692 	}
   601 
   693 
   602 __NAKED__ EXPORT_C void TSpinLock::UnlockIrq()
   694 __NAKED__ EXPORT_C void TSpinLock::UnlockIrq()
   603 	{
   695 	{
   604 	SPIN_UNLOCK_ENTRY_CHECK()
   696 	SPIN_UNLOCK_ENTRY_CHECK()
   613 	}
   705 	}
   614 
   706 
   615 __NAKED__ EXPORT_C TBool TSpinLock::FlashIrq()
   707 __NAKED__ EXPORT_C TBool TSpinLock::FlashIrq()
   616 	{
   708 	{
   617 	GET_RWNO_TID(,r12);						/* r12 -> TSubScheduler */
   709 	GET_RWNO_TID(,r12);						/* r12 -> TSubScheduler */
   618 	asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,i_GicCpuIfcAddr));
   710 	asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iGicCpuIfcAddr));
   619 	asm("ldrh r1, [r0, #0] ");
   711 	asm("ldrh r1, [r0, #0] ");
   620 	asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending));
   712 	asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending));
   621 	asm("sub r1, r1, r1, lsr #8 ");			/* r1 low byte = (out - in) mod 256 */
   713 	asm("sub r1, r1, r1, lsr #8 ");			/* r1 low byte = (out - in) mod 256 */
   622 	asm("and r1, r1, #0xFF ");
   714 	asm("and r1, r1, #0xFF ");
   623 	asm("cmp r1, #0xFF ");					/* if out - in = -1, no-one else waiting */
   715 	asm("cmp r1, #0xFF ");					/* if out - in = -1, no-one else waiting */
   653 	SPIN_LOCK_MARK_ACQ()
   745 	SPIN_LOCK_MARK_ACQ()
   654 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
   746 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
   655 	__JUMP(,lr);
   747 	__JUMP(,lr);
   656 
   748 
   657 	asm("2: ");
   749 	asm("2: ");
       
   750 	asm("ldr	r1, __CrashState ");
   658 	ARM_WFE;
   751 	ARM_WFE;
   659 	asm("ldrb r1, [r0, #0] ");				/* read out count again */
   752 	asm("ldr	r1, [r1] ");				/* check for system crash while we were waiting */
   660 	asm("b 3b ");
   753 	asm("cmp	r1, #0 ");
       
   754 	asm("bne	9f ");
       
   755 	asm("ldrb	r1, [r0, #0] ");			/* read out count again */
       
   756 	asm("b		3b ");
       
   757 	asm("9:		");
       
   758 	__ASM_CRASH();							/* system crashed while we were waiting */
   661 	}
   759 	}
   662 
   760 
   663 __NAKED__ EXPORT_C void TSpinLock::UnlockOnly()
   761 __NAKED__ EXPORT_C void TSpinLock::UnlockOnly()
   664 	{
   762 	{
   665 	SPIN_UNLOCK_ENTRY_CHECK()
   763 	SPIN_UNLOCK_ENTRY_CHECK()
   711 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
   809 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
   712 	asm("and r0, r12, #%a0" : : "i" ((TInt)KAllInterruptsMask));	/* return original CPSR I and F bits */
   810 	asm("and r0, r12, #%a0" : : "i" ((TInt)KAllInterruptsMask));	/* return original CPSR I and F bits */
   713 	__JUMP(,lr);
   811 	__JUMP(,lr);
   714 
   812 
   715 	asm("2: ");
   813 	asm("2: ");
       
   814 	asm("ldr	r1, __CrashState ");
   716 	ARM_WFE;
   815 	ARM_WFE;
   717 	asm("ldrb r1, [r0, #0] ");				/* read out count again */
   816 	asm("ldr	r1, [r1] ");				/* check for system crash while we were waiting */
   718 	asm("b 3b ");
   817 	asm("cmp	r1, #0 ");
       
   818 	asm("bne	9f ");
       
   819 	asm("ldrb	r1, [r0, #0] ");			/* read out count again */
       
   820 	asm("b		3b ");
       
   821 	asm("9:		");
       
   822 	__ASM_CRASH();							/* system crashed while we were waiting */
   719 	}
   823 	}
   720 
   824 
   721 __NAKED__ EXPORT_C void TSpinLock::UnlockIrqRestore(TInt)
   825 __NAKED__ EXPORT_C void TSpinLock::UnlockIrqRestore(TInt)
   722 	{
   826 	{
   723 	SPIN_UNLOCK_ENTRY_CHECK()
   827 	SPIN_UNLOCK_ENTRY_CHECK()
   735 	}
   839 	}
   736 
   840 
   737 __NAKED__ EXPORT_C TBool TSpinLock::FlashIrqRestore(TInt)
   841 __NAKED__ EXPORT_C TBool TSpinLock::FlashIrqRestore(TInt)
   738 	{
   842 	{
   739 	GET_RWNO_TID(,r12);						/* r12 -> TSubScheduler */
   843 	GET_RWNO_TID(,r12);						/* r12 -> TSubScheduler */
   740 	asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,i_GicCpuIfcAddr));
   844 	asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iGicCpuIfcAddr));
   741 	asm("ldrh r2, [r0, #0] ");
   845 	asm("ldrh r2, [r0, #0] ");
   742 	asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending));
   846 	asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending));
   743 	asm("sub r2, r2, r2, lsr #8 ");			/* r2 low byte = (out - in) mod 256 */
   847 	asm("sub r2, r2, r2, lsr #8 ");			/* r2 low byte = (out - in) mod 256 */
   744 	asm("and r2, r2, #0xFF ");
   848 	asm("and r2, r2, #0xFF ");
   745 	asm("cmp r2, #0xFF ");					/* if out - in = -1, no-one else waiting */
   849 	asm("cmp r2, #0xFF ");					/* if out - in = -1, no-one else waiting */
   777 	asm("bl " CSM_ZN5NKern15PreemptionPointEv);
   881 	asm("bl " CSM_ZN5NKern15PreemptionPointEv);
   778 	asm("ldr r0, [sp], #4 ");
   882 	asm("ldr r0, [sp], #4 ");
   779 	asm("bl " CSM_ZN9TSpinLock8LockOnlyEv);
   883 	asm("bl " CSM_ZN9TSpinLock8LockOnlyEv);
   780 	asm("mov r0, #1 ");
   884 	asm("mov r0, #1 ");
   781 	asm("ldr pc, [sp], #4 ");
   885 	asm("ldr pc, [sp], #4 ");
       
   886 
       
   887 	asm("__CrashState: ");
       
   888 	asm(".word	%a0" : : "i" ((TInt)&CrashState));
   782 	}
   889 	}
   783 
   890 
   784 
   891 
   785 /******************************************************************************
   892 /******************************************************************************
   786  * Read/Write Spin lock
   893  * Read/Write Spin lock
  1159 	RWSPIN_RLOCK_MARK_ACQ()
  1266 	RWSPIN_RLOCK_MARK_ACQ()
  1160 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
  1267 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
  1161 	__JUMP(,lr);
  1268 	__JUMP(,lr);
  1162 
  1269 
  1163 	asm("2: ");
  1270 	asm("2: ");
       
  1271 	asm("ldr	r1, __CrashState ");
  1164 	ARM_WFE;
  1272 	ARM_WFE;
  1165 	asm("ldr r1, [r0, #0] ");				/* read out.w count again */
  1273 	asm("ldr	r1, [r1] ");				/* check for system crash while we were waiting */
  1166 	asm("b 3b ");
  1274 	asm("cmp	r1, #0 ");
       
  1275 	asm("bne	9f ");
       
  1276 	asm("ldr	r1, [r0, #0] ");			/* read out.w count again */
       
  1277 	asm("b		3b ");
       
  1278 	asm("9:		");
       
  1279 	__ASM_CRASH();							/* system crashed while we were waiting */
  1167 	}
  1280 	}
  1168 
  1281 
  1169 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqR()
  1282 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqR()
  1170 	{
  1283 	{
  1171 	RWSPIN_RUNLOCK_ENTRY_CHECK()
  1284 	RWSPIN_RUNLOCK_ENTRY_CHECK()
  1183 	}
  1296 	}
  1184 
  1297 
  1185 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqR()
  1298 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqR()
  1186 	{
  1299 	{
  1187 	GET_RWNO_TID(,r12);						/* r12 -> TSubScheduler */
  1300 	GET_RWNO_TID(,r12);						/* r12 -> TSubScheduler */
  1188 	asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,i_GicCpuIfcAddr));
  1301 	asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iGicCpuIfcAddr));
  1189 	asm("ldr r2, [r0, #0] ");
  1302 	asm("ldr r2, [r0, #0] ");
  1190 	asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending));
  1303 	asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending));
  1191 	asm("eor r2, r2, r2, lsr #16 ");		/* r2 low byte = out.w ^ in.w = 0 if no writers waiting */
  1304 	asm("eor r2, r2, r2, lsr #16 ");		/* r2 low byte = out.w ^ in.w = 0 if no writers waiting */
  1192 	asm("tst r2, #0xFF ");
  1305 	asm("tst r2, #0xFF ");
  1193 	asm("addeq r3, r3, #1 ");
  1306 	asm("addeq r3, r3, #1 ");
  1228 	RWSPIN_WLOCK_MARK_ACQ()
  1341 	RWSPIN_WLOCK_MARK_ACQ()
  1229 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
  1342 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
  1230 	__JUMP(,lr);
  1343 	__JUMP(,lr);
  1231 
  1344 
  1232 	asm("2: ");
  1345 	asm("2: ");
       
  1346 	asm("ldr	r1, __CrashState ");
  1233 	ARM_WFE;
  1347 	ARM_WFE;
  1234 	asm("ldr r1, [r0, #0] ");				/* read out count again */
  1348 	asm("ldr	r1, [r1] ");				/* check for system crash while we were waiting */
  1235 	asm("b 3b ");
  1349 	asm("cmp	r1, #0 ");
       
  1350 	asm("bne	9f ");
       
  1351 	asm("ldr	r1, [r0, #0] ");			/* read out count again */
       
  1352 	asm("b		3b ");
       
  1353 	asm("9:		");
       
  1354 	__ASM_CRASH();							/* system crashed while we were waiting */
  1236 	}
  1355 	}
  1237 
  1356 
  1238 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqW()
  1357 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqW()
  1239 	{
  1358 	{
  1240 	RWSPIN_WUNLOCK_ENTRY_CHECK()
  1359 	RWSPIN_WUNLOCK_ENTRY_CHECK()
  1249 	}
  1368 	}
  1250 
  1369 
  1251 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqW()
  1370 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqW()
  1252 	{
  1371 	{
  1253 	GET_RWNO_TID(,r12);						/* r12 -> TSubScheduler */
  1372 	GET_RWNO_TID(,r12);						/* r12 -> TSubScheduler */
  1254 	asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,i_GicCpuIfcAddr));
  1373 	asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iGicCpuIfcAddr));
  1255 	asm("ldr r2, [r0, #0] ");
  1374 	asm("ldr r2, [r0, #0] ");
  1256 	asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending));
  1375 	asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending));
  1257 	asm("add r2, r2, #0x00010000 ");		/* increment out.w */
  1376 	asm("add r2, r2, #0x00010000 ");		/* increment out.w */
  1258 	asm("tst r2, #0x00FF0000 ");			/* if wraparound, revert carry */
  1377 	asm("tst r2, #0x00FF0000 ");			/* if wraparound, revert carry */
  1259 	asm("subeq r2, r2, #0x01000000 ");
  1378 	asm("subeq r2, r2, #0x01000000 ");
  1298 	RWSPIN_RLOCK_MARK_ACQ()
  1417 	RWSPIN_RLOCK_MARK_ACQ()
  1299 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
  1418 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
  1300 	__JUMP(,lr);
  1419 	__JUMP(,lr);
  1301 
  1420 
  1302 	asm("2: ");
  1421 	asm("2: ");
       
  1422 	asm("ldr	r1, __CrashState ");
  1303 	ARM_WFE;
  1423 	ARM_WFE;
  1304 	asm("ldr r1, [r0, #0] ");				/* read out.w count again */
  1424 	asm("ldr	r1, [r1] ");				/* check for system crash while we were waiting */
  1305 	asm("b 3b ");
  1425 	asm("cmp	r1, #0 ");
       
  1426 	asm("bne	9f ");
       
  1427 	asm("ldr	r1, [r0, #0] ");			/* read out.w count again */
       
  1428 	asm("b		3b ");
       
  1429 	asm("9:		");
       
  1430 	__ASM_CRASH();							/* system crashed while we were waiting */
  1306 	}
  1431 	}
  1307 
  1432 
  1308 __NAKED__ EXPORT_C void TRWSpinLock::UnlockOnlyR()
  1433 __NAKED__ EXPORT_C void TRWSpinLock::UnlockOnlyR()
  1309 	{
  1434 	{
  1310 	RWSPIN_RUNLOCK_ENTRY_CHECK()
  1435 	RWSPIN_RUNLOCK_ENTRY_CHECK()
  1360 	RWSPIN_WLOCK_MARK_ACQ()
  1485 	RWSPIN_WLOCK_MARK_ACQ()
  1361 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
  1486 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
  1362 	__JUMP(,lr);
  1487 	__JUMP(,lr);
  1363 
  1488 
  1364 	asm("2: ");
  1489 	asm("2: ");
       
  1490 	asm("ldr	r1, __CrashState ");
  1365 	ARM_WFE;
  1491 	ARM_WFE;
  1366 	asm("ldr r1, [r0, #0] ");				/* read out count again */
  1492 	asm("ldr	r1, [r1] ");				/* check for system crash while we were waiting */
  1367 	asm("b 3b ");
  1493 	asm("cmp	r1, #0 ");
       
  1494 	asm("bne	9f ");
       
  1495 	asm("ldr	r1, [r0, #0] ");			/* read out count again */
       
  1496 	asm("b		3b ");
       
  1497 	asm("9:		");
       
  1498 	__ASM_CRASH();							/* system crashed while we were waiting */
  1368 	}
  1499 	}
  1369 
  1500 
  1370 __NAKED__ EXPORT_C void TRWSpinLock::UnlockOnlyW()
  1501 __NAKED__ EXPORT_C void TRWSpinLock::UnlockOnlyW()
  1371 	{
  1502 	{
  1372 	RWSPIN_WUNLOCK_ENTRY_CHECK()
  1503 	RWSPIN_WUNLOCK_ENTRY_CHECK()
  1426 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
  1557 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
  1427 	asm("and r0, r12, #%a0" : : "i" ((TInt)KAllInterruptsMask));	/* return original CPSR I and F bits */
  1558 	asm("and r0, r12, #%a0" : : "i" ((TInt)KAllInterruptsMask));	/* return original CPSR I and F bits */
  1428 	__JUMP(,lr);
  1559 	__JUMP(,lr);
  1429 
  1560 
  1430 	asm("2: ");
  1561 	asm("2: ");
       
  1562 	asm("ldr	r1, __CrashState ");
  1431 	ARM_WFE;
  1563 	ARM_WFE;
  1432 	asm("ldr r1, [r0, #0] ");				/* read out.w count again */
  1564 	asm("ldr	r1, [r1] ");				/* check for system crash while we were waiting */
  1433 	asm("b 3b ");
  1565 	asm("cmp	r1, #0 ");
       
  1566 	asm("bne	9f ");
       
  1567 	asm("ldr	r1, [r0, #0] ");			/* read out.w count again */
       
  1568 	asm("b		3b ");
       
  1569 	asm("9:		");
       
  1570 	__ASM_CRASH();							/* system crashed while we were waiting */
  1434 	}
  1571 	}
  1435 
  1572 
  1436 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqRestoreR(TInt)
  1573 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqRestoreR(TInt)
  1437 	{
  1574 	{
  1438 	RWSPIN_RUNLOCK_ENTRY_CHECK()
  1575 	RWSPIN_RUNLOCK_ENTRY_CHECK()
  1453 	}
  1590 	}
  1454 
  1591 
  1455 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqRestoreR(TInt)
  1592 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqRestoreR(TInt)
  1456 	{
  1593 	{
  1457 	GET_RWNO_TID(,r12);						/* r12 -> TSubScheduler */
  1594 	GET_RWNO_TID(,r12);						/* r12 -> TSubScheduler */
  1458 	asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,i_GicCpuIfcAddr));
  1595 	asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iGicCpuIfcAddr));
  1459 	asm("ldr r2, [r0, #0] ");
  1596 	asm("ldr r2, [r0, #0] ");
  1460 	asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending));
  1597 	asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending));
  1461 	asm("eor r2, r2, r2, lsr #16 ");		/* r2 low byte = out.w ^ in.w = 0 if no writers waiting */
  1598 	asm("eor r2, r2, r2, lsr #16 ");		/* r2 low byte = out.w ^ in.w = 0 if no writers waiting */
  1462 	asm("tst r2, #0xFF ");
  1599 	asm("tst r2, #0xFF ");
  1463 	asm("addeq r3, r3, #1 ");
  1600 	asm("addeq r3, r3, #1 ");
  1500 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
  1637 	__DATA_MEMORY_BARRIER__(r3);			/* we have got the lock */
  1501 	asm("and r0, r12, #%a0" : : "i" ((TInt)KAllInterruptsMask));	/* return original CPSR I and F bits */
  1638 	asm("and r0, r12, #%a0" : : "i" ((TInt)KAllInterruptsMask));	/* return original CPSR I and F bits */
  1502 	__JUMP(,lr);
  1639 	__JUMP(,lr);
  1503 
  1640 
  1504 	asm("2: ");
  1641 	asm("2: ");
       
  1642 	asm("ldr	r1, __CrashState ");
  1505 	ARM_WFE;
  1643 	ARM_WFE;
  1506 	asm("ldr r1, [r0, #0] ");				/* read out count again */
  1644 	asm("ldr	r1, [r1] ");				/* check for system crash while we were waiting */
  1507 	asm("b 3b ");
  1645 	asm("cmp	r1, #0 ");
       
  1646 	asm("bne	9f ");
       
  1647 	asm("ldr	r1, [r0, #0] ");			/* read out count again */
       
  1648 	asm("b		3b ");
       
  1649 	asm("9:		");
       
  1650 	__ASM_CRASH();							/* system crashed while we were waiting */
  1508 	}
  1651 	}
  1509 
  1652 
  1510 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqRestoreW(TInt)
  1653 __NAKED__ EXPORT_C void TRWSpinLock::UnlockIrqRestoreW(TInt)
  1511 	{
  1654 	{
  1512 	RWSPIN_WUNLOCK_ENTRY_CHECK()
  1655 	RWSPIN_WUNLOCK_ENTRY_CHECK()
  1524 	}
  1667 	}
  1525 
  1668 
  1526 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqRestoreW(TInt)
  1669 __NAKED__ EXPORT_C TBool TRWSpinLock::FlashIrqRestoreW(TInt)
  1527 	{
  1670 	{
  1528 	GET_RWNO_TID(,r12);						/* r12 -> TSubScheduler */
  1671 	GET_RWNO_TID(,r12);						/* r12 -> TSubScheduler */
  1529 	asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,i_GicCpuIfcAddr));
  1672 	asm("ldr r12, [r12, #%a0]" : : "i" _FOFF(TSubScheduler,iSSX.iGicCpuIfcAddr));
  1530 	asm("ldr r2, [r0, #0] ");
  1673 	asm("ldr r2, [r0, #0] ");
  1531 	asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending));
  1674 	asm("ldr r3, [r12, #%a0]" : : "i" _FOFF(GicCpuIfc,iHighestPending));
  1532 	asm("add r2, r2, #0x00010000 ");		/* increment out.w */
  1675 	asm("add r2, r2, #0x00010000 ");		/* increment out.w */
  1533 	asm("tst r2, #0x00FF0000 ");			/* if wraparound, revert carry */
  1676 	asm("tst r2, #0x00FF0000 ");			/* if wraparound, revert carry */
  1534 	asm("subeq r2, r2, #0x01000000 ");
  1677 	asm("subeq r2, r2, #0x01000000 ");