os/kernelhwsrv/kernel/eka/euser/epoc/arm/uc_utl.cia
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/euser/epoc/arm/uc_utl.cia	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1519 @@
     1.4 +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// e32\euser\epoc\arm\uc_utl.cia
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include <e32cia.h>
    1.22 +#include <u32std.h>
    1.23 +#include <e32base.h>
    1.24 +#include <e32rom.h>
    1.25 +#include <e32svr.h>
    1.26 +#include <e32hashtab.h>
    1.27 +#include <u32exec.h>
    1.28 +#include "uc_std.h"
    1.29 +
    1.30 +
    1.31 +#if defined(__MEM_MACHINE_CODED__)
    1.32 +EXPORT_C __NAKED__ void Mem::Swap(TAny* /*aPtr1*/, TAny* /*aPtr2*/, TInt /*aLength*/)
    1.33 +/**
    1.34 +Swaps a number of bytes of data between two specified locations.
    1.35 +
    1.36 +The source and target areas can overlap.
    1.37 +
    1.38 +@param aPtr1   A pointer to the first location taking part in the swap. 
    1.39 +@param aPtr2   A pointer to second location taking part in the swap. 
    1.40 +@param aLength The number of bytes to be swapped between the two locations. 
    1.41 +               This value must not be negative.
    1.42 +
    1.43 +@panic USER 94 In debug builds only, if aLength is negative.
    1.44 +*/
    1.45 +    {
    1.46 +
    1.47 +    asm("   cmp      r0,r1");
    1.48 +    asm("   cmpne    r2,#0");
    1.49 +	__JUMP(eq,lr);
    1.50 +//
    1.51 +// Test for same alignment, if more than 16 bytes to swap
    1.52 +//
    1.53 +    asm("   and      r3,r0,#3");
    1.54 +    asm("   and      ip,r1,#3");
    1.55 +    asm("   cmp      r2,#16");
    1.56 +    asm("   addlt    r3,r3,#4");
    1.57 +    asm("   cmp      r3,ip");
    1.58 +    asm("   beq      same_aligned_swap");
    1.59 +
    1.60 +    asm("   stmfd    sp!,{r4,lr}");
    1.61 +
    1.62 +    asm("swap_loop:");
    1.63 +
    1.64 +    asm("   ldrb     r3,[r0]");
    1.65 +    asm("   ldrb     r4,[r1]");
    1.66 +    asm("   strb     r3,[r1],#1");
    1.67 +    asm("   strb     r4,[r0],#1");
    1.68 +    asm("   subs     r2,r2,#1");
    1.69 +	asm("beq swap_exit1 ");
    1.70 +
    1.71 +    asm("   ldrb     r3,[r0]");
    1.72 +    asm("   ldrb     r4,[r1]");
    1.73 +    asm("   strb     r3,[r1],#1");
    1.74 +    asm("   strb     r4,[r0],#1");
    1.75 +    asm("   subs     r2,r2,#1");
    1.76 +	asm("beq swap_exit1 ");
    1.77 +
    1.78 +    asm("   ldrb     r3,[r0]");
    1.79 +    asm("   ldrb     r4,[r1]");
    1.80 +    asm("   strb     r3,[r1],#1");
    1.81 +    asm("   strb     r4,[r0],#1");
    1.82 +    asm("   subs     r2,r2,#1");
    1.83 +	asm("beq swap_exit1 ");
    1.84 +
    1.85 +    asm("   ldrb     r3,[r0]");
    1.86 +    asm("   ldrb     r4,[r1]");
    1.87 +    asm("   strb     r3,[r1],#1");
    1.88 +    asm("   strb     r4,[r0],#1");
    1.89 +    asm("   subs     r2,r2,#1");
    1.90 +    asm("   bne      swap_loop");
    1.91 +	asm("swap_exit1: ");
    1.92 +	__POPRET("r4,");
    1.93 +
    1.94 +    asm("same_aligned_swap:");
    1.95 +
    1.96 +    asm("   stmfd    sp!,{r4-r10,lr}");
    1.97 +//
    1.98 +// r3 contains the byte offset from word alignment, 0,1,2 or 3
    1.99 +// subtract 1 to get -1,0,1 or 2, and if -1 make it 3
   1.100 +// that gives us 0,1,2 or 3 if the alignment is 3,2,1 or 0 respectively
   1.101 +// We can use that to jump directly to the appropriate place for
   1.102 +// swapping the relevent number of bytes to achieve word alignment
   1.103 +// r4 is set to 3-r3 to correct the length for the number of bytes
   1.104 +// swapped
   1.105 +//
   1.106 +    asm("   subs     r3,r3,#1");
   1.107 +    asm("   movmi    r3,#3");
   1.108 +    asm("   rsb      r4,r3,#3");
   1.109 +    asm("   sub      r2,r2,r4");
   1.110 +	asm("   add      pc,pc,r3,asl #4");
   1.111 +	asm("	nop ");	// never executed
   1.112 +//
   1.113 +// Jumps here if 3 bytes to swap before word aligned
   1.114 +//
   1.115 +    asm("   ldrb     r4,[r0]");
   1.116 +    asm("   ldrb     ip,[r1]");
   1.117 +    asm("   strb     r4,[r1],#1");
   1.118 +    asm("   strb     ip,[r0],#1");
   1.119 +//
   1.120 +// Jumps here if 2 bytes to swap before word aligned
   1.121 +//
   1.122 +    asm("   ldrb     r4,[r0]");
   1.123 +    asm("   ldrb     ip,[r1]");
   1.124 +    asm("   strb     r4,[r1],#1");
   1.125 +    asm("   strb     ip,[r0],#1");
   1.126 +//
   1.127 +// Jumps here if 1 byte to swap before word aligned
   1.128 +//
   1.129 +    asm("   ldrb     r4,[r0]");
   1.130 +    asm("   ldrb     ip,[r1]");
   1.131 +    asm("   strb     r4,[r1],#1");
   1.132 +    asm("   strb     ip,[r0],#1");
   1.133 +//
   1.134 +// We are now word aligned. Fast swapping, here we come...
   1.135 +//
   1.136 +    asm("word_aligned_swap:");
   1.137 +    asm("   movs     ip,r2,lsr #6"); // Number of 64 blocks to swap
   1.138 +    asm("   beq      its_smaller_swap");
   1.139 +
   1.140 +    asm("swap_64_bytes:");
   1.141 +    asm("   ldmia    r1,{r3-r6}");
   1.142 +    asm("   ldmia    r0,{r7-r10}");
   1.143 +    asm("   stmia    r1!,{r7-r10}");
   1.144 +    asm("   stmia    r0!,{r3-r6}");
   1.145 +    asm("   ldmia    r1,{r3-r6}");
   1.146 +    asm("   ldmia    r0,{r7-r10}");
   1.147 +    asm("   stmia    r1!,{r7-r10}");
   1.148 +    asm("   stmia    r0!,{r3-r6}");
   1.149 +    asm("   ldmia    r1,{r3-r6}");
   1.150 +    asm("   ldmia    r0,{r7-r10}");
   1.151 +    asm("   stmia    r1!,{r7-r10}");
   1.152 +    asm("   stmia    r0!,{r3-r6}");
   1.153 +    asm("   ldmia    r1,{r3-r6}");
   1.154 +    asm("   ldmia    r0,{r7-r10}");
   1.155 +    asm("   stmia    r1!,{r7-r10}");
   1.156 +    asm("   stmia    r0!,{r3-r6}");
   1.157 +    asm("   subs     ip,ip,#1");
   1.158 +    asm("   bne      swap_64_bytes");
   1.159 +//
   1.160 +// Less than 64 bytes to go...
   1.161 +//
   1.162 +    asm("its_smaller_swap:");
   1.163 +    asm("   ands     r2,r2,#63");
   1.164 +	asm("beq swap_exit2 ");
   1.165 +    asm("   cmp      r2,#4");
   1.166 +    asm("   blt      finish_swap");
   1.167 +    asm("final_swap_loop:");
   1.168 +    asm("   ldr      r3,[r1]");
   1.169 +    asm("   ldr      ip,[r0]");
   1.170 +    asm("   str      r3,[r0],#4");
   1.171 +    asm("   str      ip,[r1],#4");
   1.172 +    asm("   subs     r2,r2,#4");
   1.173 +    asm("   cmp      r2,#4");
   1.174 +    asm("   bge      final_swap_loop");
   1.175 +//
   1.176 +// Less than 4 bytes to go...
   1.177 +//
   1.178 +    asm("finish_swap:");
   1.179 +    asm("   tst      r2,#2");
   1.180 +    asm("   ldrneb   r3,[r0]");
   1.181 +    asm("   ldrneb   ip,[r1]");
   1.182 +    asm("   strneb   r3,[r1],#1");
   1.183 +    asm("   strneb   ip,[r0],#1");
   1.184 +    asm("   ldrneb   r3,[r0]");
   1.185 +    asm("   ldrneb   ip,[r1]");
   1.186 +    asm("   strneb   r3,[r1],#1");
   1.187 +    asm("   strneb   ip,[r0],#1");
   1.188 +
   1.189 +    asm("   tst      r2,#1");
   1.190 +    asm("   ldrneb   r3,[r0]");
   1.191 +    asm("   ldrneb   ip,[r1]");
   1.192 +    asm("   strneb   r3,[r1],#1");
   1.193 +    asm("   strneb   ip,[r0],#1");
   1.194 +
   1.195 +	asm("swap_exit2: ");
   1.196 +	__POPRET("r4-r10,");
   1.197 +    }
   1.198 +#endif
   1.199 +
   1.200 +#ifdef __REGIONS_MACHINE_CODED__
   1.201 +
   1.202 +__NAKED__ GLDEF_C void AllocAnotherRect( TRegion * /*aRegion*/ )
   1.203 +	{
   1.204 +	// Returns with Z flag set to indicate error
   1.205 +	
   1.206 +	asm("ldr r1, [r0, #4] ");			// r1=iError
   1.207 +	asm("cmp r1, #0 ");
   1.208 +	asm("bne return_error ");
   1.209 +	asm("ldr r1, [r0, #8] ");			// r1=iAllocedRects
   1.210 +	asm("ldr r12, [r0] ");				// r12=iCount
   1.211 +	asm("tst r1, #0x40000000 ");		// test ERRegionBuf
   1.212 +	asm("beq allocanother1 ");			// don't branch if TRegionFix
   1.213 +	asm("cmn r1, r12 ");				// test if iCount==-iAllocedRects
   1.214 +	__JUMP(ne,lr);
   1.215 +	asm("b  " CSM_ZN7TRegion10ForceErrorEv);		// if so, ForceError()
   1.216 +	asm("allocanother1: ");
   1.217 +	asm("cmp r1, #0 ");
   1.218 +	asm("bpl allocanother3 ");			// branch if RRegion, continue if RRegionBuf
   1.219 +	asm("orr r2, r1, #0x40000000 ");	// r2=iAllocedRects|ERRegionBuf
   1.220 +	asm("cmn r2, r12 ");				// check if iCount==(-(iAllocedRects|ERRegionBuf))
   1.221 +	__JUMP(ne,lr);
   1.222 +	asm("ldr r2, [r0, #12] ");			// r2=iGranularity
   1.223 +	asm("add r1, r12, r2 ");			// iAllocedRects=iCount+iGranularity - change into RRegion
   1.224 +	asm("str r1, [r0, #8] ");
   1.225 +	asm("stmfd sp!, {r0,r1,r12,lr} ");	// save registers used in function call
   1.226 +	asm("mov r0, r1, lsl #4 ");			// number of bytes to allocate
   1.227 +	asm("bl  " CSM_ZN4User5AllocEi);			// User::Alloc
   1.228 +	asm("movs r2, r0 ");				// returned pointer into r2
   1.229 +	asm("ldmfd sp!, {r0,r1,r12,lr} ");	// restore registers
   1.230 +	asm("add r3, r0, #20 ");			// r3=address of first rectangle
   1.231 +	asm("str r2, [r0, #16] ");			// iRectangleList=returned pointer
   1.232 +	asm("beq  " CSM_ZN7TRegion10ForceErrorEv);	// if pointer null, ForceError()
   1.233 +	asm("cmp r12, #0 ");
   1.234 +	asm("beq return_success ");
   1.235 +	asm("stmfd sp!, {r4,r5} ");
   1.236 +	asm("allocanother2: ");
   1.237 +	asm("ldmia r3!, {r0,r1,r4,r5} ");	// copy data to new area
   1.238 +	asm("subs r12, r12, #1 ");
   1.239 +	asm("stmia r2!, {r0,r1,r4,r5} ");
   1.240 +	asm("bne allocanother2 ");
   1.241 +	asm("ldmfd sp!, {r4,r5} ");
   1.242 +	asm("return_success: ");
   1.243 +	asm("movs r0, #1 ");				// clear Z flag to indicate success
   1.244 +	__JUMP(,lr);
   1.245 +	asm("allocanother3: ");				// come here if RRegion
   1.246 +	asm("cmp r1, r12 ");				// check if iCount==iAllocedRects
   1.247 +	__JUMP(ne,lr);
   1.248 +	asm("ldr r2, [r0, #12] ");			// r2 = iGranularity
   1.249 +	asm("add r1, r1, r2 ");				// iAllocedRects+=iGranularity
   1.250 +	asm("str r1, [r0, #8] ");
   1.251 +	asm("stmfd sp!, {r0,lr} ");			// preserve r0,lr across function call
   1.252 +	asm("ldr r0, [r0, #16] ");			// r0=address of current cell
   1.253 +	asm("mov r1, r1, lsl #4 ");			// r1=number of bytes to allocate
   1.254 +	asm("mov r2, #0 ");
   1.255 +	asm("bl  " CSM_ZN4User7ReAllocEPvii);		// User::ReAlloc
   1.256 +	asm("movs r2, r0 ");				// returned pointer into r2
   1.257 +	asm("ldmfd sp!, {r0,lr} ");			// restore r0,lr
   1.258 +	asm("strne r2, [r0, #16] ");		// if returned ptr not null, iRectangleList=returned ptr
   1.259 +	__JUMP(ne,lr);
   1.260 +	asm("b  " CSM_ZN7TRegion10ForceErrorEv);		// else ForceError()
   1.261 +	}
   1.262 +
   1.263 +
   1.264 +__NAKED__ EXPORT_C void TRegion::ForceError()
   1.265 +	{
   1.266 +	// Returns with Z flag set to indicate error
   1.267 +	
   1.268 +	asm("stmfd sp!, {r0,lr} ");
   1.269 +	asm("bl " CSM_ZN7TRegion5ClearEv);	// Clear()
   1.270 +	asm("ldmfd sp!, {r0,lr} ");			// restore r0,lr
   1.271 +	asm("mov r1, #1 ");
   1.272 +	asm("str r1, [r0, #4] ");			// iError=ETrue
   1.273 +	asm("return_error: ");
   1.274 +	asm("movs r0, #0 ");				// set Z flag to indicate error
   1.275 +	__JUMP(,lr);
   1.276 +	}
   1.277 +
   1.278 +
   1.279 +
   1.280 +__NAKED__ EXPORT_C TRect TRegion::BoundingRect() const
   1.281 +/**
   1.282 +Gets the minimal rectangle that bounds the entire region.
   1.283 +
   1.284 +@return The region's minimal bounding rectangle.
   1.285 +*/
   1.286 +	{
   1.287 +	asm("ldr r2, [r1] ");			// r2=iCount
   1.288 +	asm("cmp r2, #0 ");				// list empty?
   1.289 +	asm("beq boundingrect0 ");		// branch if empty
   1.290 +	asm("ldr r3, [r1, #8] ");			// if not empty, r3 points to first rectangle
   1.291 +	asm("stmfd sp!, {r4-r8,lr} ");
   1.292 +	asm("cmn r3, r3 ");
   1.293 +	asm("ldrcc r3, [r1, #16] ");		// if RRegion
   1.294 +	asm("addcs r3, r1, #20 ");			// RRegionBuf
   1.295 +	asm("submi r3, r3, #8 ");			// TRegionFix
   1.296 +	asm("ldmia r3!, {r4-r7} ");			// if not empty bounds = first rectangle
   1.297 +	asm("b boundingrect2 ");			// if not empty go and check rest of list
   1.298 +	asm("boundingrect1: ");
   1.299 +	asm("ldmia r3!, {r1,r8,r12,lr} ");	// fetch next rectangle
   1.300 +	asm("cmp r1, r4 ");					// if next.iTl.iX<bounds.iTl.iX
   1.301 +	asm("movlt r4, r1 ");				//		bounds.iTl.iX=next.iTl.iX
   1.302 +	asm("cmp r8, r5 ");					// if next.iTl.iY<bounds.iTl.iY
   1.303 +	asm("movlt r5, r8 ");				//		bounds.iTl.iY=next.iTl.iY
   1.304 +	asm("cmp r12, r6 ");				// if next.iBr.iX>bounds.iBr.iX
   1.305 +	asm("movgt r6, r12 ");				//		bounds.iBr.iX=next.iBr.iX
   1.306 +	asm("cmp lr, r7 ");					// if next.iBr.iY>bounds.iBr.iY
   1.307 +	asm("movgt r7, lr ");				//		bounds.iBr.iY=next.iBr.iY
   1.308 +	asm("boundingrect2: ");
   1.309 +	asm("subs r2, r2, #1 ");			// decrement count
   1.310 +	asm("bne boundingrect1 ");			// repeat for all rectangles
   1.311 +	asm("stmia r0, {r4-r7} ");			// store result
   1.312 +	__POPRET("r4-r8,");
   1.313 +
   1.314 +	asm("boundingrect0: ");
   1.315 +	asm("mov r1, #0 ");					// if list empty, bounds = 0,0,0,0
   1.316 +	asm("mov r3, #0 ");
   1.317 +	asm("mov r12, #0 ");
   1.318 +	asm("stmia r0, {r1,r2,r3,r12} ");	// store result
   1.319 +	__JUMP(,lr);
   1.320 +	}
   1.321 +
   1.322 +
   1.323 +
   1.324 +
   1.325 +__NAKED__ EXPORT_C TBool TRegion::IsContainedBy(const TRect & /*aRect*/) const
   1.326 +/**
   1.327 +Tests whether the region is fully enclosed within the specified rectangle.
   1.328 +
   1.329 +@param aRect The specified rectangle.
   1.330 + 
   1.331 +@return True, if the region is fully enclosed within the rectangle (their sides 
   1.332 +        may touch); false, otherwise.
   1.333 +*/
   1.334 +	{
   1.335 +	asm("ldr r12, [r0, #8] ");			// r12 points to first rectangle
   1.336 +	asm("stmfd sp!, {r4-r7,lr} ");	
   1.337 +	asm("cmn r12, r12 ");
   1.338 +	asm("ldrcc r12, [r0, #16] ");		// if RRegion
   1.339 +	asm("addcs r12, r0, #20 ");			// RRegionBuf
   1.340 +	asm("submi r12, r12, #8 ");			// TRegionFix
   1.341 +
   1.342 +	asm("ldr r0, [r0] ");				// r0=iCount
   1.343 +	asm("ldmia r1, {r4-r7} ");			// aRect coordinates into r4-r7
   1.344 +	
   1.345 +	asm("subs r0, r0, #1 ");			// decrement it
   1.346 +	asm("bmi iscontainedby2 ");			// if iCount was zero, return TRUE
   1.347 +	
   1.348 +	asm("iscontainedby1: ");
   1.349 +	asm("ldmia r12!, {r1,r2,r3,lr} ");	// coordinates of next rectangle
   1.350 +	asm("cmp r1, r4 ");					// compare next.iTl.iX with aRect.iTl.iX
   1.351 +	asm("cmpge r2, r5 ");				// if >=, compare next.iTl.iY with aRect.iTl.iY
   1.352 +	asm("cmpge r6, r3 ");				// if >=, compare aRect.Br.iX with next.iBr.iX
   1.353 +	asm("cmpge r7, lr ");				// if >=, compare aRect.Br.iY with next.iBr.iY
   1.354 +	asm("subges r0, r0, #1 ");			// if >=, next is contained in aRect, so iterate
   1.355 +	asm("bge iscontainedby1 ");			// will drop through if r0<0 or if next exceeds aRect
   1.356 +	asm("iscontainedby2: ");
   1.357 +	asm("mov r0, r0, lsr #31 ");		// return 1 if r0<0, 0 if r0>=0
   1.358 +	__POPRET("r4-r7,");
   1.359 +	}
   1.360 +
   1.361 +
   1.362 +
   1.363 +
   1.364 +__NAKED__ EXPORT_C void TRegion::Copy(const TRegion & /*aRegion*/)
   1.365 +/**
   1.366 +Copies another region to this region.
   1.367 +
   1.368 +The state of the specified region's error flag is also copied.
   1.369 +
   1.370 +@param aRegion The region to be copied.
   1.371 +*/
   1.372 +	{
   1.373 +	asm("ldr r2, [r1, #4] ");					// r2 = aRegion.iError
   1.374 +	asm("cmp r2, #0 ");
   1.375 +	asm("bne  " CSM_ZN7TRegion10ForceErrorEv);	// if (aRegion.iError) ForceError();
   1.376 +	asm("ldr r2, [r1] ");						// r1 = aRegion.iCount
   1.377 +	asm("cmp r2, #0 ");
   1.378 +	asm("beq " CSM_ZN7TRegion5ClearEv);			// region to copy is empty so simply clear our buffer
   1.379 +	asm("stmfd sp!, {r0,r1,r4,r5,r6,lr} ");		// preserve r0,r1,lr across function calls
   1.380 +	asm("mov r4, r1 ");
   1.381 +	asm("mov r5, r0 ");
   1.382 +	asm("ldr r2, [r0, #4] ");					// r2 = iError
   1.383 +	asm("cmp r2, #0 ");
   1.384 +	asm("blne  " CSM_ZN7TRegion5ClearEv);		// if (iError) Clear();
   1.385 +	asm("mov r0, r5 ");
   1.386 +	asm("ldr r1, [r4] ");						// r1 = aRegion.iCount, r0 = this
   1.387 +	asm("bl	 " CSM_ZN7TRegion11SetListSizeEi);	// SetListSize(aRegion.iCount);
   1.388 +	asm("cmp r0, #0 ");
   1.389 +	asm("beq copyregion_end ");
   1.390 +	asm("ldr r3, [r4] ");						// r3 = aRegion.iCount
   1.391 +	asm("cmp r3, #0 ");
   1.392 +	asm("str r3, [r5] ");						// iCount=aRegion.iCount
   1.393 +	asm("beq copyregion_end ");
   1.394 +	asm("ldr r0, [r5, #8] ");					// r0 points to first rectangle
   1.395 +	asm("cmn r0, r0 ");
   1.396 +	asm("ldrcc r0, [r5, #16] ");				// if RRegion
   1.397 +	asm("addcs r0, r5, #20 ");					// RRegionBuf
   1.398 +	asm("submi r0, r0, #8 ");					// TRegionFix
   1.399 +	asm("ldr r1, [r4, #8] ");					// r1 points to first rectangle
   1.400 +	asm("cmn r1, r1 ");
   1.401 +	asm("ldrcc r1, [r4, #16] ");				// if RRegion
   1.402 +	asm("addcs r1, r4, #20 ");					// RRegionBuf
   1.403 +	asm("submi r1, r1, #8 ");					// TRegionFix
   1.404 +	asm("copyregion1: ");
   1.405 +	asm("ldmia r1!, {r2,r4,r5,r12} ");			// copy aRegion.iRectangleList to iRectangleList
   1.406 +	asm("subs r3, r3, #1 ");
   1.407 +	asm("stmia r0!, {r2,r4,r5,r12} ");
   1.408 +	asm("bne copyregion1 ");
   1.409 +
   1.410 +	asm("copyregion_end: ");
   1.411 +	__POPRET("r0,r1,r4,r5,r6,");
   1.412 +	}
   1.413 +
   1.414 +
   1.415 +
   1.416 +
   1.417 +__NAKED__ EXPORT_C void TRegion::Offset(const TPoint & /*anOffset*/)
   1.418 +/**
   1.419 +Moves the region by adding a TPoint offset to the co-ordinates of its corners.
   1.420 +	
   1.421 +The size of the region is not changed.
   1.422 +	
   1.423 +@param aOffset The offset by which the region is moved. The region is moved 
   1.424 +               horizontally by aOffset.iX pixels and vertically by aOffset.iY pixels.
   1.425 +*/
   1.426 +	{
   1.427 +	asm("ldmia r1, {r1,r2} ");		// r1=anOffset.iX, r2=anOffset.iY
   1.428 +	// fall through...
   1.429 +	}
   1.430 +
   1.431 +
   1.432 +
   1.433 +
   1.434 +__NAKED__ EXPORT_C void TRegion::Offset(TInt /*xOffset*/,TInt /*yOffset*/)
   1.435 +/**
   1.436 +Moves the region by adding X and Y offsets to the co-ordinates of its corners.
   1.437 +	
   1.438 +The size of the region is not changed.
   1.439 +	
   1.440 +@param aXoffset The number of pixels by which to move the region horizontally. 
   1.441 +                If negative, the region moves leftwards. 
   1.442 +@param aYoffset The number of pixels by which to move the region vertically. 
   1.443 +                If negative, the region moves upwards.
   1.444 +*/
   1.445 +	{
   1.446 +	asm("ldr r12, [r0] ");			// r12=iCount
   1.447 +	asm("cmp r12, #0 ");
   1.448 +	__JUMP(eq,lr);
   1.449 +	asm("ldr r3, [r0, #8] ");		// r0 points to first rectangle
   1.450 +	asm("cmn r3, r3 ");
   1.451 +	asm("ldrcc r0, [r0, #16] ");	// if RRegion
   1.452 +	asm("addcs r0, r0, #20 ");		// RRegionBuf
   1.453 +	asm("submi r0, r0, #8 ");		// TRegionFix
   1.454 +	asm("stmfd sp!, {r4,r5,lr} ");
   1.455 +	asm("offsetregion2: ");
   1.456 +	asm("ldmia r0, {r3-r5,lr} ");	// r3-r5,lr = next rectangle coordinates
   1.457 +	asm("subs r12, r12, #1 ");
   1.458 +	asm("add r3, r3, r1 ");			// Tl.iX += anOffset.iX
   1.459 +	asm("add r4, r4, r2 ");			// Tl.iY += anOffset.iY
   1.460 +	asm("add r5, r5, r1 ");			// Br.iX += anOffset.iX
   1.461 +	asm("add lr, lr, r2 ");			// Br.iY += anOffset.iY
   1.462 +	asm("stmia r0!, {r3-r5,lr} ");	// store new coordinates
   1.463 +	asm("bne offsetregion2 ");
   1.464 +	__POPRET("r4,r5,");
   1.465 +	}
   1.466 +
   1.467 +
   1.468 +
   1.469 +
   1.470 +__NAKED__ EXPORT_C TBool TRegion::Contains(const TPoint & /*aPoint*/) const
   1.471 +/**
   1.472 +Tests whether a point is located within the region.
   1.473 +
   1.474 +If the point is located on the top or left hand side of any rectangle in the 
   1.475 +region, it is considered to be within that rectangle and within the region. 
   1.476 +
   1.477 +If the point is located on the right hand side or bottom of a rectangle, it 
   1.478 +is considered to be outside that rectangle, and may be outside the region.
   1.479 +
   1.480 +@param aPoint The specified point. 
   1.481 +
   1.482 +@return True, if the point is within the region; false, otherwise.
   1.483 +*/
   1.484 +	{
   1.485 +	asm("ldr r12, [r0] ");			// r12 = iCount
   1.486 +	asm("stmfd sp!, {r4,r5,lr} ");
   1.487 +	asm("cmp r12, #0 ");
   1.488 +	asm("beq contains0 ");			// if iCount=0, return FALSE
   1.489 +	asm("ldr r3, [r0, #8] ");		// r0 points to first rectangle
   1.490 +	asm("cmn r3, r3 ");
   1.491 +	asm("ldrcc r0, [r0, #16] ");	// if RRegion
   1.492 +	asm("addcs r0, r0, #20 ");		// RRegionBuf
   1.493 +	asm("submi r0, r0, #8 ");		// TRegionFix
   1.494 +	asm("ldmia r1, {r1, r2} ");		// r1=aPoint.iX, r2=aPoint.iY
   1.495 +	asm("contains1: ");
   1.496 +	asm("ldmia r0!, {r3-r5,lr} ");	// coordinates of next rectangle into r3-r5,lr
   1.497 +	asm("cmp r3, r1 ");				// compare next.iTl.iX with aPoint.iX
   1.498 +	asm("cmple r4, r2 ");			// if <=, compare next.iTl.iY with aPoint.iY
   1.499 +	asm("bgt contains2 ");			// if >, aPoint is not contained in rectangle, so iterate
   1.500 +	asm("cmp r1, r5 ");				// compare aPoint.iX with next.iBr.iX
   1.501 +	asm("cmplt r2, lr ");			// if <, compare aPoint.iY with next.iBr.iY
   1.502 +	asm("contains2: ");
   1.503 +	asm("subges r12, r12, #1 ");	// if >=, aPoint is not contained in rect, so iterate
   1.504 +	asm("bgt contains1 ");
   1.505 +	asm("cmp r12, #0 ");
   1.506 +	asm("movne r0, #1 ");			// if r12 non-zero, return TRUE else FALSE
   1.507 +	asm("contains0: ");
   1.508 +	asm("moveq r0, #0 ");
   1.509 +	__POPRET("r4,r5,");
   1.510 +	}
   1.511 +
   1.512 +
   1.513 +
   1.514 +
   1.515 +__NAKED__ EXPORT_C TBool TRegion::Intersects(const TRect &/*aRect*/) const
   1.516 +/**
   1.517 +Tests whether where there is any intersection between this region and the specified rectangle.
   1.518 +
   1.519 +@param aRect The specified rectangle.
   1.520 + 
   1.521 +@return True, if there is an intersection; false, otherwise.
   1.522 +*/
   1.523 +	{
   1.524 +	asm("ldr    r12, [r0] ");		// r12 = iCount
   1.525 +	asm("stmfd  sp!, {r4-r7,lr} ");
   1.526 +	asm("cmp    r12, #0 ");
   1.527 +	asm("beq    intersects0 ");		// if iCount=0, return FALSE
   1.528 +	asm("ldr    lr, [r0, #8] ");	// r0 points to first rectangle	
   1.529 +	asm("ldmia  r1, {r1-r4} ");		// (load aRect into r1 - r4)
   1.530 +	asm("cmn    lr, lr ");
   1.531 +	asm("ldrcc  r0, [r0, #16] ");	// if RRegion
   1.532 +	asm("addcs  r0, r0, #20 ");		// RRegionBuf
   1.533 +	asm("submi  r0, r0, #8 ");		// TRegionFix
   1.534 +	asm("cmp    r1, r3 ");			// check if aRect is empty
   1.535 +	asm("cmplt  r2, r4 ");
   1.536 +	asm("bge    intersects0 ");
   1.537 +	
   1.538 +	asm("intersects1: ");
   1.539 +	asm("ldmia  r0!, {r5-r7,lr} ");	// coordinates of next rectangle into r5-r7,lr	
   1.540 +	asm("cmp    r1, r7 ");			// check if they intersect
   1.541 +	asm("cmplt  r2, lr ");
   1.542 +	asm("cmplt  r5, r3 ");
   1.543 +	asm("cmplt  r6, r4 ");
   1.544 +	asm("subges r12, r12, #1 ");	// if not then decrement and loop
   1.545 +	asm("bgt    intersects1 ");
   1.546 +	
   1.547 +	asm("intersects0: ");
   1.548 +	asm("movge  r0, #0 ");
   1.549 +	asm("movlt  r0, #1 ");
   1.550 +	__POPRET("r4-r7,");
   1.551 +	}
   1.552 +
   1.553 +
   1.554 +
   1.555 +
   1.556 +__NAKED__ void TRegion::DeleteRect(TRect * /*aRect*/)
   1.557 +//
   1.558 +// Delete a specific rectangle in the list.
   1.559 +//
   1.560 +	{
   1.561 +	asm("ldr r12, [r0] ");			// r12=iCount
   1.562 +	asm("ldr r3, [r0, #8] ");		// r0 points to first rectangle
   1.563 +	asm("subs r12, r12, #1 ");		// decrement it
   1.564 +	asm("str r12, [r0] ");			// iCount--;
   1.565 +	asm("cmn r3, r3 ");
   1.566 +	asm("ldrcc r0, [r0, #16] ");	// if RRegion
   1.567 +	asm("addcs r0, r0, #20 ");		// RRegionBuf
   1.568 +	asm("submi r0, r0, #8 ");		// TRegionFix
   1.569 +	asm("sub r2, r1, r0 ");			// r2=offset of aRect from iRectangleList
   1.570 +	asm("subs r12, r12, r2, lsr #4 ");	// r12 now equals number of rectangles requiring moving
   1.571 +	__JUMP(eq,lr);
   1.572 +	asm("add r0, r1, #16 ");			// r0 = aRect+1
   1.573 +	asm("stmfd sp!, {r4,lr} ");
   1.574 +	asm("deleterect1: ");
   1.575 +	asm("ldmia r0!, {r2-r4,lr} ");		// move rectangles following aRect back by one place
   1.576 +	asm("subs r12, r12, #1 ");
   1.577 +	asm("stmia r1!, {r2-r4,lr} ");
   1.578 +	asm("bne deleterect1 ");
   1.579 +	__POPRET("r4,");
   1.580 +	}
   1.581 +
   1.582 +
   1.583 +
   1.584 +
   1.585 +__NAKED__ EXPORT_C void TRegion::ClipRect(const TRect & /*aRect*/)
   1.586 +/**
   1.587 +Clips the region to the specified rectangle.
   1.588 +
   1.589 +The resulting region is the area of overlap between the region and the rectangle. 
   1.590 +If there is no overlap, all rectangles within this region are deleted and 
   1.591 +the resulting region is empty.
   1.592 +
   1.593 +@param aRect The rectangle to which this region is to be clipped.
   1.594 +*/
   1.595 +// Can not fail.
   1.596 +	{
   1.597 +	asm("ldr r12, [r0] ");				// r12=iCount
   1.598 +	asm("cmp r12, #0 ");
   1.599 +	__JUMP(eq,lr);
   1.600 +	asm("stmfd sp!, {r4-r10,lr} ");
   1.601 +	asm("ldmia r1, {r2-r5} ");			// get coordinates of aRect into r2-r5
   1.602 +	asm("ldr r1, [r0, #8] ");			// r1 points to first rectangle
   1.603 +	asm("cmn r1, r1 ");
   1.604 +	asm("ldrcc r1, [r0, #16] ");		// if RRegion
   1.605 +	asm("addcs r1, r0, #20 ");			// RRegionBuf
   1.606 +	asm("submi r1, r1, #8 ");			// TRegionFix
   1.607 +
   1.608 +	asm("cliprect1: ");
   1.609 +	asm("ldmia r1!, {r6-r9} ");			// next rectangle coordinates into r6-r9
   1.610 +	asm("cmp r6, r2 ");					// clip the rectangle to aRect
   1.611 +	asm("movlt r6, r2 ");	
   1.612 +	asm("strlt r2, [r1, #-16] ");
   1.613 +	asm("cmp r7, r3 ");
   1.614 +	asm("movlt r7, r3 ");
   1.615 +	asm("strlt r3, [r1, #-12] ");
   1.616 +	asm("cmp r8, r4 ");
   1.617 +	asm("movgt r8, r4 ");
   1.618 +	asm("strgt r4, [r1, #-8] ");
   1.619 +	asm("cmp r9, r5 ");
   1.620 +	asm("movgt r9, r5 ");
   1.621 +	asm("strgt r5, [r1, #-4] ");
   1.622 +	asm("cmp r6, r8 ");					// check if clipped rect is empty
   1.623 +	asm("cmplt r7, r9 ");				// empty if r6>=r8 or r7>=r9
   1.624 +	asm("bge cliprect_delete ");		// if empty, branch to other loop to delete rect 
   1.625 +	asm("subs r12, r12, #1 ");			// decrement loop counter
   1.626 +	asm("bne cliprect1 ");				// loop if any more rectangles to do
   1.627 +	__POPRET("r4-r10,");
   1.628 +
   1.629 +	asm("cliprect_delete: ");			// (enter loop here)
   1.630 +	asm("ldr lr, [r0] ");				// lr=iCount, updateed if we delete rects
   1.631 +	asm("sub r10, r1, #16 ");			// r1 -> next rect, r10 -> previous deleted rect
   1.632 +	asm("subs r12, r12, #1 ");			// decrement loop counter
   1.633 +	asm("beq cliprect_move_end ");	
   1.634 +	asm("cliprect_move: ");
   1.635 +	asm("ldmia r1!, {r6-r9} ");			// next rectangle coordinates into r6-r9
   1.636 +	asm("cmp r6, r2 ");					// clip the rectangle to aRect
   1.637 +	asm("movlt r6, r2 ");
   1.638 +	asm("cmp r7, r3 ");
   1.639 +	asm("movlt r7, r3 ");
   1.640 +	asm("cmp r8, r4 ");
   1.641 +	asm("movgt r8, r4 ");
   1.642 +	asm("cmp r9, r5 ");
   1.643 +	asm("movgt r9, r5 ");
   1.644 +	asm("cmp r6, r8 ");					// check if clipped rect is empty
   1.645 +	asm("cmplt r7, r9 ");				// empty if r6>=r8 or r7>=r9
   1.646 +	asm("stmltia r10!, {r6-r9} ");		// if non-empty then store the rect
   1.647 +	asm("subge lr, lr, #1 ");			// else decrement rect count	
   1.648 +	asm("subs r12, r12, #1 ");			// decrement loop counter
   1.649 +	asm("bne cliprect_move ");			// loop if any more rectangles to do
   1.650 +	asm("cliprect_move_end: ");	
   1.651 +	asm("sub lr, lr, #1 ");				// decrement count for first deleted rect
   1.652 +	asm("str lr, [r0] ");				// store updated iCount
   1.653 +	__POPRET("r4-r10,");	
   1.654 +	}
   1.655 +
   1.656 +
   1.657 +
   1.658 +	
   1.659 +__NAKED__ EXPORT_C void TRegion::SubRect(const TRect& /*aRect*/,TRegion* /*aSubtractedRegion*/)
   1.660 +/**
   1.661 +Removes a rectangle from this region.
   1.662 +
   1.663 +If there is no intersection between the rectangle and this region, then this 
   1.664 +region is unaffected. 
   1.665 +
   1.666 +@param aRect             The rectangular area to be removed from this region. 
   1.667 +@param aSubtractedRegion A pointer to a region. If this is supplied, the
   1.668 +                         removed rectangle is added to it. By default this
   1.669 +                         pointer is NULL.
   1.670 +*/
   1.671 +	{
   1.672 +	asm("ldr r12, [r0] ");			// r12=iCount=limit
   1.673 +	asm("cmp r12, #0 ");
   1.674 +	__JUMP(eq,lr);
   1.675 +	asm("stmfd sp!, {r3-r11,lr} ");
   1.676 +	asm("ldmia r1, {r4-r7} ");		// r4-r7 = coordinates of aRect
   1.677 +	asm("cmp r4, r6 ");				// check if aRect is empty i.e. (r4>=r6 || r5>=r7)
   1.678 +	asm("cmplt r5, r7 ");
   1.679 +	asm("bge subrect_end ");		// if aRect is empty nothing to do
   1.680 +
   1.681 +	asm("mov r3, #0 ");				// r3=index
   1.682 +	asm("subrect1: ");
   1.683 +	asm("ldr lr, [r0, #8] ");		// lr points to first rectangle
   1.684 +	asm("cmn lr, lr ");
   1.685 +	asm("ldrcc lr, [r0, #16] ");	// if RRegion
   1.686 +	asm("addcs lr, r0, #20 ");		// RRegionBuf
   1.687 +	asm("submi lr, lr, #8 ");		// TRegionFix
   1.688 +	asm("add lr, lr, r3, lsl #4 ");	// lr=iRectangleList+index
   1.689 +//	asm("ldmia r1, {r4-r7} ");		// r4-r7 = coordinates of aRect
   1.690 +	asm("ldmia lr, {r8-r11} ");		// r8-r11 = coordinates of next rectangle in region
   1.691 +	asm("cmp r10, r4 ");			// compare next.iBr.iX with aRect.iTl.iX
   1.692 +	asm("cmpgt r11, r5 ");			// if >, compare next.iBr.iY with aRect.iTl.iY
   1.693 +	asm("cmpgt r6, r8 ");			// if >, compare aRect.iBr.iX with next.iTl.iX
   1.694 +	asm("cmpgt r7, r9 ");			// if >, compare aRect.iBr.iY with next.iTl.iY
   1.695 +	asm("addle r3, r3, #1 ");		// if empty intersection, increment index
   1.696 +	asm("ble subrect2 ");			// if <=, next and aRect have empty intersection, so skip
   1.697 +	asm("add r4, lr, #16 ");		// r4 = source pointer for copy, lr = dest
   1.698 +	asm("ldr r5, [r0] ");			// r5 = iCount
   1.699 +	asm("sub r5, r5, #1 ");			// decrement iCount
   1.700 +	asm("str r5, [r0] ");
   1.701 +	asm("sub r12, r12, #1 ");		// decrement limit
   1.702 +	asm("subs r5, r5, r3 ");		// loop count for copy = iCount-index
   1.703 +	asm("beq subrect4 ");			// if loop count zero, skip the copy
   1.704 +	asm("stmfd sp!, {r8,r9} ");		// preserve r8,r9
   1.705 +	asm("subrect3: ");
   1.706 +	asm("ldmia r4!, {r6-r9} ");		// remove the current rectangle
   1.707 +	asm("stmia lr!, {r6-r9} ");
   1.708 +	asm("subs r5, r5, #1 ");
   1.709 +	asm("bne subrect3 ");
   1.710 +	asm("ldmfd sp!, {r8-r9} ");		// restore r8,r9
   1.711 +	asm("subrect4: ");
   1.712 +	asm("ldmia r1, {r4-r7} ");		// restore coordinates of aRect into r4-r7
   1.713 +	asm("cmp r7, r11 ");			// compare aRect.iBr.iY with rect.iBr.iY
   1.714 +	asm("movgt r7, r11 ");			// r7=inter.iBr.iY
   1.715 +	asm("bllt subrectapp1 ");		// if <, append 1st subrectangle
   1.716 +	asm("cmp r5, r9 ");				// compare aRect.iTl.iY with rect.iTl.iY
   1.717 +	asm("movlt r5, r9 ");			// r5=inter.iTl.iY
   1.718 +	asm("blgt subrectapp2 ");		// if >, append 2nd subrectangle
   1.719 +	asm("cmp r6, r10 ");			// compare aRect.iBr.iX with rect.iBr.iX
   1.720 +	asm("movgt r6, r10 ");			// r6=inter.iBr.iX
   1.721 +	asm("bllt subrectapp3 ");		// if <, append 3rd subrectangle
   1.722 +	asm("cmp r4, r8 ");				// compare aRect.iTl.iX with rect.iTl.iX
   1.723 +	asm("movlt r4, r8 ");			// r4=inter.iTl.iX
   1.724 +	asm("blgt subrectapp4 ");		// if >, append 4th subrectangle
   1.725 +	asm("ldr lr, [r0, #4] ");		// lr=iError
   1.726 +	asm("cmp lr, #0 ");				// check for an error
   1.727 +	asm("bne subrect_end ");
   1.728 +	asm("cmp r2, #0 ");				// check if aSubtractedRegion!=NULL
   1.729 +	asm("blne subrectadd ");		// if non-null, add inter to aSubtractedRegion
   1.730 +	asm("subrect2: ");
   1.731 +	asm("cmp r3, r12 ");			// compare index to limit
   1.732 +	asm("ldmltia r1, {r4-r7} ");	// if index<limit, r4-r7 = coordinates of aRect
   1.733 +	asm("blt subrect1 ");			// if index<limit, loop again
   1.734 +
   1.735 +	asm("subrect_end: ");
   1.736 +	__POPRET("r3-r11,");
   1.737 +
   1.738 +	// AppendRect(TRect(rect.iTl.iX,inter.iBr.iY,rect.iBr.iX,rect.iBr.iY))
   1.739 +	asm("subrectapp1: ");
   1.740 +	asm("stmfd sp!, {r0-r3,r12,lr} ");			// preserve registers across function call
   1.741 +	asm("bl  " CSM_Z16AllocAnotherRectP7TRegion);
   1.742 +	asm("ldmfd sp!, {r0-r3} ");
   1.743 +	asm("beq subrectapp1_end ");		// exit if error
   1.744 +
   1.745 +	asm("ldr r12, [r0] ");				// r12=iCount
   1.746 +	asm("ldr lr, [r0, #8] ");		// lr points to first rectangle
   1.747 +	asm("cmn lr, lr ");
   1.748 +	asm("ldrcc lr, [r0, #16] ");	// if RRegion
   1.749 +	asm("addcs lr, r0, #20 ");		// RRegionBuf
   1.750 +	asm("submi lr, lr, #8 ");		// TRegionFix
   1.751 +	asm("add lr, lr, r12, lsl #4 ");	// lr=&(iRectangleList[iCount])
   1.752 +	asm("add r12, r12, #1 ");			// increment iCount
   1.753 +	asm("str r12, [r0] ");				//
   1.754 +	asm("stmia lr!, {r8} ");			// append rectangle - rect.iTl.iX
   1.755 +	asm("stmia lr!, {r7,r10,r11} ");	// inter.iBr.iY, rect.iBr.iX, rect.iBr.iY
   1.756 +	asm("subrectapp1_end: ");
   1.757 +	__POPRET("r12,");
   1.758 +
   1.759 +	// AppendRect(TRect(rect.iTl.iX,rect.iTl.iY,rect.iBr.iX,inter.iTl.iY))
   1.760 +	asm("subrectapp2: ");
   1.761 +	asm("stmfd sp!, {r0-r3,r12,lr} ");			// preserve registers across function call
   1.762 +	asm("bl  " CSM_Z16AllocAnotherRectP7TRegion);
   1.763 +	asm("ldmfd sp!, {r0-r3} ");
   1.764 +	asm("beq subrectapp1_end ");		// exit if error
   1.765 +
   1.766 +	asm("ldr r12, [r0] ");				// r12=iCount
   1.767 +	asm("ldr lr, [r0, #8] ");		// lr points to first rectangle
   1.768 +	asm("cmn lr, lr ");
   1.769 +	asm("ldrcc lr, [r0, #16] ");	// if RRegion
   1.770 +	asm("addcs lr, r0, #20 ");		// RRegionBuf
   1.771 +	asm("submi lr, lr, #8 ");		// TRegionFix
   1.772 +	asm("add lr, lr, r12, lsl #4 ");	// lr=&(iRectangleList[iCount])
   1.773 +	asm("add r12, r12, #1 ");			// increment iCount
   1.774 +	asm("str r12, [r0] ");				//
   1.775 +	asm("stmia lr!, {r8,r9,r10} ");		// append rectangle - rect.iTl.iX,rect.iTl.iY,rect.iBr.iX
   1.776 +	asm("stmia lr!, {r5} ");			// inter.iTl.iY
   1.777 +	__POPRET("r12,");
   1.778 +
   1.779 +	// AppendRect(TRect(inter.iBr.iX,inter.iTl.iY,rect.iBr.iX,inter.iBr.iY))
   1.780 +	asm("subrectapp3: ");
   1.781 +	asm("stmfd sp!, {r0-r3,r12,lr} ");			// preserve registers across function call
   1.782 +	asm("bl  " CSM_Z16AllocAnotherRectP7TRegion);
   1.783 +	asm("ldmfd sp!, {r0-r3} ");
   1.784 +	asm("beq subrectapp1_end ");		// exit if error
   1.785 +	asm("ldr r12, [r0] ");				// r12=iCount
   1.786 +	asm("ldr lr, [r0, #8] ");		// lr points to first rectangle
   1.787 +	asm("cmn lr, lr ");
   1.788 +	asm("ldrcc lr, [r0, #16] ");	// if RRegion
   1.789 +	asm("addcs lr, r0, #20 ");		// RRegionBuf
   1.790 +	asm("submi lr, lr, #8 ");		// TRegionFix
   1.791 +	asm("add lr, lr, r12, lsl #4 ");	// lr=&(iRectangleList[iCount])
   1.792 +	asm("add r12, r12, #1 ");			// increment iCount
   1.793 +	asm("str r12, [r0] ");				//
   1.794 +	asm("stmia lr!, {r6} ");			// append rectangle - inter.iBr.iX
   1.795 +	asm("stmia lr!, {r5,r10} ");		// inter.iTl.iY, rect.iBr.iX
   1.796 +	asm("stmia lr!, {r7} ");			// inter.iBr.iY
   1.797 +	__POPRET("r12,");
   1.798 +
   1.799 +	// AppendRect(TRect(rect.iTl.iX,inter.iTl.iY,inter.iTl.iX,inter.iBr.iY))
   1.800 +	asm("subrectapp4: ");
   1.801 +	asm("stmfd sp!, {r0-r3,r12,lr} ");			// preserve registers across function call
   1.802 +	asm("bl  " CSM_Z16AllocAnotherRectP7TRegion);
   1.803 +	asm("ldmfd sp!, {r0-r3} ");
   1.804 +	asm("beq subrectapp1_end ");		// exit if error
   1.805 +	asm("ldr r12, [r0] ");				// r12=iCount
   1.806 +	asm("ldr lr, [r0, #8] ");		// lr points to first rectangle
   1.807 +	asm("cmn lr, lr ");
   1.808 +	asm("ldrcc lr, [r0, #16] ");	// if RRegion
   1.809 +	asm("addcs lr, r0, #20 ");		// RRegionBuf
   1.810 +	asm("submi lr, lr, #8 ");		// TRegionFix
   1.811 +	asm("add lr, lr, r12, lsl #4 ");	// lr=&(iRectangleList[iCount])
   1.812 +	asm("add r12, r12, #1 ");			// increment iCount
   1.813 +	asm("str r12, [r0] ");				//
   1.814 +	asm("stmia lr!, {r8} ");			// append rectangle - rect.iTl.iX
   1.815 +	asm("stmia lr!, {r5} ");			// inter.iTl.iY
   1.816 +	asm("stmia lr!, {r4,r7} ");			// inter.iTl.iX, inter.iBr.iY
   1.817 +	__POPRET("r12,");
   1.818 +
   1.819 +	// aSubtractedRegion->AddRect(inter)
   1.820 +	asm("subrectadd: ");
   1.821 +	asm("stmfd sp!, {r0-r7,r12,lr} ");	// preserve registers and put inter onto stack
   1.822 +	asm("mov r0, r2 ");					// this = aSubtractedRegion
   1.823 +	asm("add r1, sp, #16 ");			// inter is 16 bytes above sp
   1.824 +	asm("bl  " CSM_ZN7TRegion7AddRectERK5TRect);	// call TRegion::AddRect
   1.825 +	__POPRET("r0-r7,r12,");
   1.826 +	}
   1.827 +
   1.828 +
   1.829 +
   1.830 +
   1.831 +__NAKED__ EXPORT_C void TRegion::Intersection(const TRegion& /*aRegion1*/,const TRegion& /*aRegion2*/)
   1.832 +/**
   1.833 +Replaces this region with the area of intersection between two specified regions.
   1.834 +	
   1.835 +Notes:
   1.836 +	
   1.837 +1. If the error flag of either of the two specified regions is set, then this 
   1.838 +   region is cleared and its error flag is set. This frees up allocated memory.
   1.839 +	
   1.840 +2. If this region's error flag is already set, then the function has no effect.
   1.841 +	
   1.842 +@param aRegion1 The first region. 
   1.843 +@param aRegion2 The second region.
   1.844 +*/
   1.845 +	{
   1.846 +	// r0=this, r1=&aRegion1, r2=&aRegion2
   1.847 +	asm("ldr r3, [r1, #4] ");			// r3=aRegion1.iError
   1.848 +	asm("ldr r12, [r2, #4] ");			// r12=aRegion2.iError
   1.849 +	asm("orrs r3, r3, r12 ");
   1.850 +	asm("bne  " CSM_ZN7TRegion10ForceErrorEv);	// if either set, ForceError()
   1.851 +	asm("str r3, [r0] ");				// iCount=0
   1.852 +	asm("ldr r3, [r1] ");				// r3=aRegion1.iCount
   1.853 +	asm("ldr r12, [r2] ");				// r12=aRegion2.iCount
   1.854 +	asm("cmp r3, #0 ");
   1.855 +	asm("cmpne r12, #0 ");
   1.856 +	__JUMP(eq,lr);
   1.857 +	asm("stmfd sp!, {r3-r11,lr} ");
   1.858 +	asm("ldr lr, [r1, #8] ");			// r1 points to first rectangle of aRegion1 = pRect1
   1.859 +	asm("cmn lr, lr ");
   1.860 +	asm("ldrcc r1, [r1, #16] ");		// if RRegion
   1.861 +	asm("addcs r1, r1, #20 ");			// RRegionBuf
   1.862 +	asm("submi r1, r1, #8 ");			// TRegionFix
   1.863 +	asm("intersection1: ");
   1.864 +	asm("ldr lr, [r2, #8] ");			// lr points to first rectangle of aRegion2
   1.865 +	asm("cmn lr, lr ");
   1.866 +	asm("ldrcc lr, [r2, #16] ");		// if RRegion
   1.867 +	asm("addcs lr, r2, #20 ");			// RRegionBuf
   1.868 +	asm("submi lr, lr, #8 ");			// TRegionFix
   1.869 +	asm("ldr r12, [r2] ");				// r12=aRegion2.iCount
   1.870 +	asm("intersection2: ");
   1.871 +	asm("ldmia r1, {r4-r7} ");			// r4-r7 = *pRect1
   1.872 +	asm("ldmia lr!, {r8-r11} ");		// r8-r11 = *pRect2++
   1.873 +	asm("cmp r6, r8 ");					// compare pRect1->iBr.iX with pRect2->iTl.iX
   1.874 +	asm("cmpgt r7, r9 ");				// if >, compare pRect1->iBr.iY with pRect2->iTl.iY
   1.875 +	asm("cmpgt r10, r4 ");				// if >, compare pRect2->iBr.iX with pRect1->iTl.iX
   1.876 +	asm("cmpgt r11, r5 ");				// if >, compare pRect2->iBr.iY with pRect1->iTl.iY
   1.877 +	asm("ble intersection3 ");			// if <=, rectangles have empty intersection, so iterate
   1.878 +	asm("cmp r4, r8 ");					// compute intersection and place in r8-r11
   1.879 +	asm("movgt r8, r4 ");
   1.880 +	asm("cmp r5, r9 ");
   1.881 +	asm("movgt r9, r5 ");
   1.882 +	asm("cmp r6, r10 ");
   1.883 +	asm("movlt r10, r6 ");
   1.884 +	asm("cmp r7, r11 ");
   1.885 +	asm("movlt r11, r7 ");
   1.886 +	asm("stmfd sp!, {r0-r3,r12,lr} ");	// preserve registers across function call
   1.887 +	asm("bl  " CSM_Z16AllocAnotherRectP7TRegion);
   1.888 +	asm("ldmfd sp!, {r0-r3} ");
   1.889 +	asm("ldmeqfd sp!, {r12,lr} ");		// exit if error
   1.890 +	asm("beq intersection_end ");
   1.891 +
   1.892 +	asm("ldr r12, [r0] ");				// r12=iCount
   1.893 +	asm("ldr lr, [r0, #8] ");			// lr points to first rectangle
   1.894 +	asm("cmn lr, lr ");
   1.895 +	asm("ldrcc lr, [r0, #16] ");		// if RRegion
   1.896 +	asm("addcs lr, r0, #20 ");			// RRegionBuf
   1.897 +	asm("submi lr, lr, #8 ");			// TRegionFix
   1.898 +	asm("add lr, lr, r12, lsl #4 ");	// lr=&(iRectangleList[iCount])
   1.899 +	asm("add r12, r12, #1 ");			// increment iCount
   1.900 +	asm("str r12, [r0] ");				//
   1.901 +	asm("stmia lr!, {r8-r11} ");		// append intersection of rectangles
   1.902 +	asm("ldmfd sp!, {r12,lr} ");		// restore registers
   1.903 +	asm("intersection3: ");
   1.904 +	asm("subs r12, r12, #1 ");
   1.905 +	asm("bne intersection2 ");			// loop for all values of pRect2
   1.906 +	asm("add r1, r1, #16 ");			// increment pRect1
   1.907 +	asm("subs r3, r3, #1 ");
   1.908 +	asm("bne intersection1 ");			// loop for all values of pRect1
   1.909 +
   1.910 +	asm("intersection_end: ");
   1.911 +	__POPRET("r3-r11,");
   1.912 +	}
   1.913 +	
   1.914 +#endif
   1.915 +
   1.916 +
   1.917 +
   1.918 +
   1.919 +#ifdef __COBJECT_MACHINE_CODED__
   1.920 +__NAKED__ EXPORT_C CObject *CObjectIx::At(TInt /*aHandle*/,TInt /*aUniqueID*/)
   1.921 +/**
   1.922 +Gets a pointer to the reference counting object with the specified handle
   1.923 +number and matching unique ID.
   1.924 +
   1.925 +@param aHandle   The handle number of the reference counting object.
   1.926 +@param aUniqueID The unique ID.
   1.927 +
   1.928 +@return A pointer to the reference counting object. If there is no matching 
   1.929 +        object, then this is NULL.
   1.930 +*/
   1.931 +	{
   1.932 +	// r0=this, r1=aHandle, r2=aUniqueID
   1.933 +	asm("ldr r3, [r0, #%a0]" : : "i" _FOFF(CObjectIx,iHighWaterMark));	// r3=iHighWaterMark
   1.934 +	asm("ldr r0, [r0, #%a0]" : : "i" _FOFF(CObjectIx,iObjects));	// r0=iObjects
   1.935 +	asm("mov r12, r1, lsl #17 ");		// r12=r1<<17 = index(aHandle)<<17
   1.936 +	asm("cmp r3, r12, lsr #17 ");		// compare iHighWaterMark with index(aHandle)
   1.937 +	asm("movle r0, #0 ");				// if hwm<=index, return NULL
   1.938 +	__JUMP(le,lr);
   1.939 +	asm("add r0, r0, r12, lsr #14 ");	// r0=iObjects+index(Handle)=pS
   1.940 +	asm("ldr r3, [r0] ");				// r3=pS->uniqueID:pS->instance
   1.941 +	asm("mov r1, r1, lsl #2 ");			// r1=instance(Handle)<<18
   1.942 +	asm("mov r1, r1, lsr #18 ");		// r1=instance(Handle)
   1.943 +	asm("orr r1, r1, r2, lsl #16 ");	// r1=aUniqueID:instance(Handle)
   1.944 +	asm("cmp r1, r3 ");					// check uniqueID and instance
   1.945 +	asm("movne r0, #0 ");				// if wrong, return 0
   1.946 +	asm("ldreq r0, [r0, #4] ");			// else return pointer to CObject
   1.947 +	__JUMP(,lr);
   1.948 +	}
   1.949 +
   1.950 +
   1.951 +
   1.952 +
   1.953 +__NAKED__ EXPORT_C CObject *CObjectIx::At(TInt aHandle)
   1.954 +/**
   1.955 +Gets a pointer to the reference counting object with the specified
   1.956 +handle number.
   1.957 +
   1.958 +@param aHandle The handle number of the reference counting object.
   1.959 +
   1.960 +@return A pointer to the reference counting object. If there is no matching 
   1.961 +        object, then this is NULL.
   1.962 +*/
   1.963 +	{
   1.964 +	// r0=this, r1=aHandle
   1.965 +	asm("ldr r3, [r0, #%a0]" : : "i" _FOFF(CObjectIx,iHighWaterMark));	// r3=iHighWaterMark
   1.966 +	asm("ldr r0, [r0, #%a0]" : : "i" _FOFF(CObjectIx,iObjects));	// r0=iObjects
   1.967 +	asm("mov r12, r1, lsl #17 ");		// r12=r1<<17 = index(aHandle)<<17
   1.968 +	asm("cmp r3, r12, lsr #17 ");		// compare iHighWaterMark with index(aHandle)
   1.969 +	asm("movle r0, #0 ");				// if hwm<=index, return NULL
   1.970 +	__JUMP(le,lr);
   1.971 +	asm("add r0, r0, r12, lsr #14 ");	// r0=iObjects+index(Handle)=pS
   1.972 +	asm("ldr r3, [r0] ");				// r3=pS->uniqueID:pS->instance
   1.973 +	asm("ldr r2, __instanceMask ");
   1.974 +	asm("and r1, r1, r2 ");				// r1=instance(Handle)<<16
   1.975 +	asm("cmp r1, r3, lsl #16 ");		// check instance
   1.976 +	asm("movne r0, #0 ");				// if wrong, return 0
   1.977 +	asm("ldreq r0, [r0, #4] ");			// else return pointer to CObject
   1.978 +	__JUMP(,lr);
   1.979 +	asm("__instanceMask: ");
   1.980 +	asm(".word 0x3FFF0000 ");
   1.981 +	}
   1.982 +
   1.983 +
   1.984 +
   1.985 +
   1.986 +GLREF_C void PanicCObjectIxIndexOutOfRange(void);
   1.987 +
   1.988 +
   1.989 +
   1.990 +
   1.991 +__NAKED__ EXPORT_C CObject* CObjectIx::operator[](TInt /*anIndex*/)
   1.992 +/**
   1.993 +Gets a pointer to a reference counting object located at the specified offset 
   1.994 +within the object index.
   1.995 +
   1.996 +@param anIndex The offset of the reference counting object within the object 
   1.997 +               index. Offset is relative to zero. 
   1.998 +               
   1.999 +@return A pointer to the reference counting object.
  1.1000 +
  1.1001 +@panic E32USER-CBase 21 if the value of anIndex is negative or is greater than
  1.1002 +                        or equal to the total number of objects held by
  1.1003 +                        the index.
  1.1004 +*/
  1.1005 +	{
  1.1006 +	// r0=this, r1=anIndex
  1.1007 +	asm("cmp r1, #0 ");								// check anIndex>=0
  1.1008 +	asm("ldrge r3, [r0, #%a0]" : : "i" _FOFF(CObjectIx,iHighWaterMark));	// if so, r3=iHighWaterMark
  1.1009 +	asm("cmpge r3, r1 ");							// and compare iHighWaterMark to anIndex
  1.1010 +	asm("ldrgt r0, [r0, #%a0]" : : "i" _FOFF(CObjectIx,iObjects));	// if OK, r0=iObjects
  1.1011 +	asm("addgt r0, r0, r1, lsl #3 ");				// r0=iObjects+anIndex
  1.1012 +	asm("ldrgt r0, [r0, #4] ");						// r0=pointer to CObject
  1.1013 +#ifdef __CPU_ARMV6
  1.1014 +	asm("ble 1f ");
  1.1015 +	__JUMP(,lr);
  1.1016 +#else
  1.1017 +	__JUMP(gt,lr);
  1.1018 +#endif
  1.1019 +	asm("1: ");
  1.1020 +	asm("b  " CSM_Z29PanicCObjectIxIndexOutOfRangev);	// if anIndex<0 or iCount<=anIndex, panic
  1.1021 +	}
  1.1022 +
  1.1023 +
  1.1024 +
  1.1025 +
  1.1026 +GLREF_C void PanicCObjectConIndexOutOfRange(void);
  1.1027 +GLREF_C void PanicCObjectConFindBadHandle(void);
  1.1028 +GLREF_C void PanicCObjectConFindIndexOutOfRange(void);
  1.1029 +
  1.1030 +
  1.1031 +
  1.1032 +
  1.1033 +__NAKED__ EXPORT_C CObject *CObjectCon::operator[](TInt /*anIndex*/)
  1.1034 +/**
  1.1035 +Gets a pointer to the reference counting object located at the specified offset 
  1.1036 +within the object container.
  1.1037 +
  1.1038 +@param anIndex The offset of the reference counting object within the object 
  1.1039 +               container. Offset is relative to zero.
  1.1040 +
  1.1041 +@return A pointer to the owning reference counting object.
  1.1042 +
  1.1043 +@panic E32USER-CBase 21 if anIndex is negative or is greater than or equal to
  1.1044 +                        the total number of objects held by the container.
  1.1045 +*/
  1.1046 +	{
  1.1047 +	// r0=this, r1=anIndex
  1.1048 +	asm("cmp r1, #0 ");
  1.1049 +	asm("ldrge r2, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iCount));
  1.1050 +	asm("cmpge r2, r1 ");
  1.1051 +	asm("ldrgt r0, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iObjects));
  1.1052 +	asm("ldrgt r0, [r0, r1, lsl #2] ");
  1.1053 +#ifdef __CPU_ARMV6
  1.1054 +	asm("ble 1f ");
  1.1055 +	__JUMP(,lr);
  1.1056 +#else
  1.1057 +	__JUMP(gt,lr);
  1.1058 +#endif
  1.1059 +	asm("1: ");
  1.1060 +	asm("b  " CSM_Z30PanicCObjectConIndexOutOfRangev);
  1.1061 +	}
  1.1062 +
  1.1063 +
  1.1064 +
  1.1065 +
  1.1066 +__NAKED__ EXPORT_C CObject *CObjectCon::At(TInt /*aFindHandle*/) const
  1.1067 +/**
  1.1068 +Gets a pointer to the reference counting object with the specified find-handle 
  1.1069 +number.
  1.1070 +
  1.1071 +A find-handle number is an integer which uniquely identifies a reference
  1.1072 +counting object with respect to its object container.
  1.1073 +
  1.1074 +@param aFindHandle The find-handle number of the reference counting object. 
  1.1075 +                   The unique Id part of this number must be the same as the
  1.1076 +                   unique Id of this container.
  1.1077 +                   The index part of the find-handle number must be
  1.1078 +                   a valid index. 
  1.1079 +
  1.1080 +@return A pointer to the reference counting object.
  1.1081 +
  1.1082 +@panic E32User-CBase 38 if the unique Id part of aFindHandle is not the same as
  1.1083 +                        the unique Id of this container.
  1.1084 +@panic E32User-CBase 39 if the index part of aFindHandle is negative or greater
  1.1085 +                        than or equal to the total number of reference counting
  1.1086 +                        objects held by this object container.
  1.1087 +*/
  1.1088 +	{
  1.1089 +	// r0=this, r1=aFindHandle
  1.1090 +	asm("ldr r2, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iUniqueID));
  1.1091 +	asm("cmp r2, r1, lsr #16 ");
  1.1092 +	asm("ldreq r2, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iCount));
  1.1093 +	asm("bne  " CSM_Z28PanicCObjectConFindBadHandlev);
  1.1094 +	asm("mov r1, r1, lsl #17 ");
  1.1095 +	asm("cmp r2, r1, lsr #17 ");
  1.1096 +	asm("ldrgt r0, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iObjects));
  1.1097 +	asm("ble  " CSM_Z34PanicCObjectConFindIndexOutOfRangev);
  1.1098 +	asm("ldr r0, [r0, r1, lsr #15] ");
  1.1099 +	__JUMP(,lr);
  1.1100 +	}
  1.1101 +
  1.1102 +
  1.1103 +
  1.1104 +
  1.1105 +__NAKED__ EXPORT_C CObject *CObjectCon::AtL(TInt /*aFindHandle*/) const
  1.1106 +/**
  1.1107 +Gets a pointer to the reference counting object with the specified find-handle 
  1.1108 +number, and leaves on error.
  1.1109 +
  1.1110 +A find-handle number is an integer which uniquely identifies a reference
  1.1111 +counting object with respect to its object container.
  1.1112 +
  1.1113 +@param aFindHandle The find-handle number of the reference counting object. 
  1.1114 +                   The unique Id part of this number must be the same as
  1.1115 +                   the unique Id of this container.
  1.1116 +                   The index part of the find-handle number must be
  1.1117 +                   a valid index. 
  1.1118 +
  1.1119 +@return A pointer to the reference counting object.
  1.1120 +
  1.1121 +@leave KErrBadHandle if the unique Id part of aFindHandle is not the same as
  1.1122 +                     the unique Id of this container.
  1.1123 +@leave KErrArgument if the index part of aFindHandle is negative or greater
  1.1124 +                    than or equal to the total number of reference counting
  1.1125 +                    objects held by this object container.
  1.1126 +*/
  1.1127 +	{
  1.1128 +	// r0=this, r1=aFindHandle
  1.1129 +	asm("ldr r2, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iUniqueID));
  1.1130 +	asm("cmp r2, r1, lsr #16 ");
  1.1131 +	asm("ldreq r2, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iCount));
  1.1132 +	asm("bne 1f ");
  1.1133 +	asm("mov r1, r1, lsl #17 ");
  1.1134 +	asm("cmp r2, r1, lsr #17 ");
  1.1135 +	asm("ldrgt r0, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iObjects));
  1.1136 +	asm("ble 2f ");
  1.1137 +	asm("ldr r0, [r0, r1, lsr #15] ");
  1.1138 +	__JUMP(,lr);
  1.1139 +	// User::Leave tail called, so no annotations required since
  1.1140 +	// current frame is reused by User::Leave
  1.1141 +	asm("1: ");
  1.1142 +	asm("mvn r0, #7 "); // KErrBadHandle
  1.1143 +	asm("b  " CSM_ZN4User5LeaveEi);
  1.1144 +	asm("2: ");
  1.1145 +	asm("mvn r0, #5 "); // KErrArgument
  1.1146 +	asm("b  " CSM_ZN4User5LeaveEi);
  1.1147 +	}
  1.1148 +#endif
  1.1149 +
  1.1150 +#ifdef __CACTIVESCHEDULER_MACHINE_CODED__
  1.1151 +extern "C" void PanicStrayEvent();
  1.1152 +
  1.1153 +/**
  1.1154 +@internalComponent
  1.1155 +
  1.1156 +The inner active scheduler loop. This repeatedly waits for a signal and then
  1.1157 +dispatches the highest priority ready active object. The loop terminates either
  1.1158 +if one of the RunL()s stops the current active scheduler level or leaves.
  1.1159 +
  1.1160 +Stop when aLoop becomes 'Inactive'
  1.1161 +*/
  1.1162 +__NAKED__ void CActiveScheduler::DoRunL(TLoopOwner* const volatile& aLoop, CActive* volatile & aCurrentObj, TCleanupBundle* aCleanupBundlePtr)
  1.1163 +	{
  1.1164 +	asm("stmfd sp!, {r4-r8,lr} ");
  1.1165 +	__EH_FRAME_PUSH2(r4-r8,lr)
  1.1166 +	
  1.1167 +#ifdef _DEBUG
  1.1168 +	// need to copy aCleanupBundlePtr to somewhere else before it's clobbered by the next line.
  1.1169 +	asm("mov r8, r3 ");														// r8 = &aCleanupBundlePtr
  1.1170 +#endif
  1.1171 +	
  1.1172 +	asm("ldr r3, [r0, #%a0]" : : "i" (_CBASE_VPTR_OFFSET_));				// r3 = vptr
  1.1173 +	asm("add r4, r0, #%a0" : : "i" _FOFF(CActiveScheduler,iActiveQ));		// r4 = &iActiveQ
  1.1174 +	asm("mov r5, r1 ");														// r5 = &aLoop
  1.1175 +	asm("mov r7, r2 ");														// r7 = &aCurrentObj
  1.1176 +	asm("ldr r6, [r3, #%a0]" : : "i" (_CACTIVESCHEDULER_WAIT_OFFSET_));		// r6 = &WaitForAnyRequest()
  1.1177 +
  1.1178 +	asm("active_scheduler_loop: ");
  1.1179 +	asm("ldr r1, [r5] ");													// r1 = aLoop
  1.1180 +	asm("adr lr, 1f ");														// return address
  1.1181 +	asm("sub r0, r4, #%a0 " : : "i" _FOFF(CActiveScheduler,iActiveQ));		// this
  1.1182 +	asm("cmp r1, #0 ");
  1.1183 +	__JUMP(ne, r6);															// call WaitForAnyRequest() if still active
  1.1184 +	__POPRET("r4-r8,");														// else return
  1.1185 +
  1.1186 +	// get here when WaitForAnyRequest() returns
  1.1187 +	asm("1: ");
  1.1188 +	asm("ldr r14, [r4, #0] ");												// r14->first active object
  1.1189 +
  1.1190 +	asm("2: ");
  1.1191 +	asm("cmp r14, r4 ");													// end of queue?
  1.1192 +	asm("sub r0, r14, #%a0" : : "i" _FOFF(CActive,iLink));					// r0->CActive
  1.1193 +	asm("ldmneda r14, {r2, r12, r14} ");									// r2=iStatus, r12=iStatus.iFlags (old iActive), r14 = next object
  1.1194 +	asm("beq PanicStrayEvent ");											// if end of queue, panic
  1.1195 +#ifdef _DEBUG
  1.1196 +	asm("ands r3, r12, #%a0" : : "i" ((TInt)(TRequestStatus::EActive|TRequestStatus::ERequestPending)));	// only active bit and request-pending bit
  1.1197 +	asm("cmpne r3, #%a0" : : "i" ((TInt)(TRequestStatus::EActive|TRequestStatus::ERequestPending)));		// active bit == request pending bit
  1.1198 +	asm("bne PanicStrayEvent ");											// if active bit != request pending bit, panic
  1.1199 +#endif
  1.1200 +	asm("cmp r2, #%a0" : : "i" ((TInt)KRequestPending));					// test if iStatus!=KRequestPending
  1.1201 +	asm("andnes r3, r12, #%a0" : : "i" ((TInt)TRequestStatus::EActive));	// if so, test iActive
  1.1202 +	asm("beq 2b ");															// if not active or still pending, do next CActive
  1.1203 +
  1.1204 +	// have an active object to run
  1.1205 +#ifdef __SMP__
  1.1206 +	__DATA_MEMORY_BARRIER_Z__(r3);											// acquire semantics
  1.1207 +#endif
  1.1208 +	asm("ldr r3, [r0, #%a0]" : : "i" (_CBASE_VPTR_OFFSET_));				// r3=CActive->vptr
  1.1209 +	asm("bic r12, r12, #%a0" : : "i" ((TInt)(TRequestStatus::EActive|TRequestStatus::ERequestPending)));
  1.1210 +	asm("ldr r3, [r3, #%a0]" : : "i" (_CACTIVE_RUNL_OFFSET_));				// r3 = &CActive::RunL()
  1.1211 +	asm("str r12, [r0, #%a0]" : : "i" (_FOFF(CActive,iStatus)+_FOFF(TRequestStatus,iFlags)));	// iActive=EFalse
  1.1212 +	asm("str r0, [r7] ");													// save active object in aCurrentObj in case RunL leaves
  1.1213 +#ifdef _DEBUG
  1.1214 +	__JUMPL(3);															// call RunL() (and continue)
  1.1215 +#else
  1.1216 +	asm("adr lr, active_scheduler_loop ");								// set lr (return address) to label, active_scheduler_loop
  1.1217 +	__JUMP(,r3);														// call RunL() (and loop)
  1.1218 +#endif
  1.1219 +	
  1.1220 +	
  1.1221 +#ifdef _DEBUG
  1.1222 +	//check whether there's a cleanup stack installed:
  1.1223 +
  1.1224 +	asm("cmp r8, #0");															// check CleanupBundle* == NULL
  1.1225 +	asm("beq active_scheduler_loop ");											// If r8 == NULL, branch to label, active_scheduler_loop
  1.1226 +	asm("ldr r0, [r8, #%a0]" : : "i" _FOFF(TCleanupBundle,iCleanupPtr)); 		// r0 = CCleanup* (load the CCleanup*)
  1.1227 +
  1.1228 +	//there is a cleanupstack installed:
  1.1229 +	asm("add r1, r8, #%a0" : : "i" _FOFF(TCleanupBundle,iDummyInt)); 			// r1 = iDummyInt* (load the TInt*)
  1.1230 +	asm("adr lr, active_scheduler_loop ");										// set lr (return address) to label, active_scheduler_loop
  1.1231 +	asm("b  " CSM_ZN8CCleanup5CheckEPv); 										// call CCleanup::Check(iDummyInt*)
  1.1232 +#endif
  1.1233 +	
  1.1234 +	}
  1.1235 +#endif
  1.1236 +
  1.1237 +
  1.1238 +#ifdef __CSERVER_MACHINE_CODED__
  1.1239 +__NAKED__ EXPORT_C void CServer2::RunL()
  1.1240 +	{
  1.1241 +	asm("ldr r2, [r0, #%a0]" : : "i" _FOFF(CServer2,iMessage.iFunction)); // r2=Message().Function()
  1.1242 +	asm("stmfd sp!, {r4, lr}");			// save regs
  1.1243 +	__EH_FRAME_PUSH2(r4,lr)
  1.1244 +	asm("cmp r2, #0");					// check for Connect/Disconnect message
  1.1245 +	asm("bmi server2_con_dis");
  1.1246 +
  1.1247 +	// Service the message
  1.1248 +	asm("mov r4, r0 ");						// r4=this
  1.1249 +	asm("ldr r0, [r4, #%a0]" : : "i" _FOFF(CServer2,iMessage.iSessionPtr)); // r0=session
  1.1250 +	asm("add r1, r4, #%a0" : : "i" (_FOFF(CServer2,iMessage)));	// r1=&iServer.Message()
  1.1251 +	asm("cmp r0, #0");  // Check for NULL session
  1.1252 +	asm("ldrne r12, [r0, #%a0]" : : "i" (_CBASE_VPTR_OFFSET_));			// r12=CSession2::vptr
  1.1253 +#ifdef __SUPPORT_THUMB_INTERWORKING
  1.1254 +	asm("ldrne r3, [r12, #%a0]" : : "i" (_CSESSION2_SERVICEL_OFFSET_));	// call CSession2::ServiceL(iMessage)
  1.1255 +	asm("adr lr, server2_run_postamble ");
  1.1256 +	asm("bxne r3 ");
  1.1257 +#else
  1.1258 +	asm("adr lr, server2_run_postamble ");
  1.1259 +	asm("ldrne pc, [r12, #%a0]" : : "i" (_CSESSION2_SERVICEL_OFFSET_));	// call CSession2::ServiceL(iMessage)
  1.1260 +#endif
  1.1261 +	asm("mov r0, r1");
  1.1262 +	asm("b  " CSM_ZN8CServer212NotConnectedERK9RMessage2); // NULL session ptr means not connected
  1.1263 +
  1.1264 +	// Do this after processing any message
  1.1265 +	asm("server2_run_postamble: ");
  1.1266 +	asm("ldr r2, [r4, #%a0]" : : "i" (_FOFF(CServer2,iStatus)+_FOFF(TRequestStatus,iFlags)));	// r2=iStatus.iFlags (old iActive)
  1.1267 +	asm("mov r0, #0x80000001 ");								// r0=KRequestPending
  1.1268 +	asm("ands r1, r2, #%a0" : : "i" ((TInt)TRequestStatus::EActive));
  1.1269 +	asm("bne server2_run_end ");							// if already active, finished
  1.1270 +	asm("orr r2, r2, #%a0" : : "i" ((TInt)(TRequestStatus::EActive|TRequestStatus::ERequestPending)));
  1.1271 +	asm("add r1, r4, #%a0" : : "i" _FOFF(CActive,iStatus));		// r1->iStatus
  1.1272 +	asm("stmia r1, {r0,r2} "); // set iStatus=KRequestPending, set active bit, set request pending bit
  1.1273 +	asm("add r2, r4, #%a0" : : "i" _FOFF(CServer2,iMessage));	// r2->iServer.Message()
  1.1274 +	asm("ldr r0, [r4, #%a0]" : : "i" _FOFF(CServer2,iServer));	// r0=iServer.iHandle
  1.1275 +	asm("bl  " CSM_ZN4Exec13ServerReceiveEiR14TRequestStatusPv);// call Exec::ServerReceive
  1.1276 +	asm("server2_run_end: ");
  1.1277 +	__POPRET("r4,");
  1.1278 +
  1.1279 +	// Deal with Connect and Disconnect messages
  1.1280 +	asm("server2_con_dis:");	
  1.1281 +	asm("mov r4, r0 ");					// r4=this
  1.1282 +	asm("add r1, r0, #%a0" : : "i" _FOFF(CServer2,iMessage)); // r1=&iServer.Message()
  1.1283 +	asm("adr lr, server2_run_postamble "); // return address for after any processing
  1.1284 +	asm("cmp r2, #%a0" : : "i" (RMessage2::EConnect));
  1.1285 +	asm("beq  " CSM_ZN8CServer27ConnectERK9RMessage2); // Do Connect()
  1.1286 +	asm("cmp r2, #%a0" : : "i" (RMessage2::EDisConnect));
  1.1287 +	asm("beq  " CSM_ZN8CServer210DisconnectERK9RMessage2); // Do Disconnect()
  1.1288 +	asm("mov r0, r1");
  1.1289 +	asm("b  " CSM_ZN8CServer210BadMessageERK9RMessage2); // Bad message
  1.1290 +	}
  1.1291 +#endif
  1.1292 +
  1.1293 +EXPORT_C __NAKED__ void RFastLock::Wait()
  1.1294 +	{
  1.1295 +	asm("1: ");
  1.1296 +	asm("add	r0, r0, #4 ");					// point to iCount
  1.1297 +
  1.1298 +#ifdef __CPU_ARM_HAS_LDREX_STREX
  1.1299 +	asm("2:		");
  1.1300 +	LDREX(		2, 0);							// read
  1.1301 +	asm("subs	r1, r2, #1 ");					// decrement
  1.1302 +	STREX(		3, 1, 0);						// write
  1.1303 +	asm("teq	r3, #0 ");						// success?
  1.1304 +	asm("bne	2b ");							// no!
  1.1305 +	asm("sub	r0, r0, #4 ");					// r0 = this
  1.1306 +	asm("bcs "	CSM_ZN10RSemaphore4WaitEv);		// if no borrow from decrement wait on semaphore
  1.1307 +#ifdef __SMP__
  1.1308 +	__DATA_MEMORY_BARRIER__(r3);				// no need to wait, but still need acquire barrier
  1.1309 +#endif
  1.1310 +	__JUMP(,	lr );
  1.1311 +#else
  1.1312 +	asm("mov	r1, #1 ");						// 'looking' value
  1.1313 +	asm("swp	r1, r1, [r0] ");				// write looking value, read original
  1.1314 +	asm("subs	r1, r1, #1 ");					// decrement count
  1.1315 +	asm("strlt	r1, [r0] ");					// if it becomes negative, no-one was looking
  1.1316 +	__JUMP(cc,	lr);							// if borrow, was originally zero so we are finished
  1.1317 +	asm("sub	r0, r0, #4 ");					// r0=this
  1.1318 +	asm("blt "	CSM_ZN10RSemaphore4WaitEv);		// lock held so wait on semaphore
  1.1319 +	asm("stmfd	sp!, {r0,lr} ");				// otherwise save registers
  1.1320 +	asm("mov	r0, #1000 ");					// someone was looking, so wait 1ms and try again
  1.1321 +	asm("bl "	CSM_ZN4User12AfterHighResE27TTimeIntervalMicroSeconds32);
  1.1322 +	asm("ldmfd	sp!, {r0,lr} ");
  1.1323 +	asm("b		1b ");
  1.1324 +#endif
  1.1325 +	}
  1.1326 +
  1.1327 +EXPORT_C __NAKED__ void RFastLock::Signal()
  1.1328 +	{
  1.1329 +	asm("1: ");
  1.1330 +	asm("add	r0, r0, #4 ");					// point to iCount
  1.1331 +
  1.1332 +#ifdef __CPU_ARM_HAS_LDREX_STREX
  1.1333 +#ifdef __SMP__
  1.1334 +	__DATA_MEMORY_BARRIER_Z__(r3);				// need release barrier
  1.1335 +#endif
  1.1336 +	asm("2:		");
  1.1337 +	LDREX(		2, 0);							// read
  1.1338 +	asm("adds	r1, r2, #1 ");					// increment
  1.1339 +	STREX(		3, 1, 0);						// write
  1.1340 +	asm("teq	r3, #0 ");						// success?
  1.1341 +	asm("bne	2b ");							// no!
  1.1342 +	asm("sub	r0, r0, #4 ");					// r0 = this
  1.1343 +	asm("bcc "	CSM_ZN10RSemaphore6SignalEv);	// if no carry from increment, signal semaphore
  1.1344 +	__JUMP(,	lr );
  1.1345 +#else
  1.1346 +	asm("mov	r1, #1 ");						// 'looking' value
  1.1347 +	asm("swp	r1, r1, [r0] ");				// write looking value, read original
  1.1348 +	asm("adds	r1, r1, #1 ");					// increment count
  1.1349 +	asm("strle	r1, [r0] ");					// if still <=0, no-one was looking
  1.1350 +	__JUMP(eq,	lr);							// if it's now zero, no-one is waiting so we are finished
  1.1351 +	asm("sub	r0, r0, #4 ");					// r0=this
  1.1352 +	asm("blt "	CSM_ZN10RSemaphore6SignalEv);	// someone is waiting so signal semaphore
  1.1353 +	asm("stmfd	sp!, {r0,lr} ");				// otherwise save registers
  1.1354 +	asm("mov	r0, #1000 ");					// someone was looking, so wait 1ms and try again
  1.1355 +	asm("bl "	CSM_ZN4User12AfterHighResE27TTimeIntervalMicroSeconds32);
  1.1356 +	asm("ldmfd	sp!, {r0,lr} ");
  1.1357 +	asm("b		1b ");
  1.1358 +#endif
  1.1359 +	}
  1.1360 +
  1.1361 +
  1.1362 +// Entry point stub to allow EKA1 binaries to be executed under EKA2
  1.1363 +// Only called when process is first loaded
  1.1364 +
  1.1365 +extern "C" TLinAddr GetEka1ExeEntryPoint();
  1.1366 +
  1.1367 +__NAKED__ TInt E32Loader::V7ExeEntryStub()
  1.1368 +	{
  1.1369 +	// Process entry point
  1.1370 +	// R4 = entry reason
  1.1371 +	// SP points to information block
  1.1372 +	asm("cmp r4, #%a0" : : "i" ((TInt)KModuleEntryReasonProcessInit) );
  1.1373 +	asm("bne " CSM_ZN4User9InvariantEv );	// invalid entry reason
  1.1374 +	asm("bl GetEka1ExeEntryPoint ");		// load the entry stub and return its address
  1.1375 +	__JUMP(,r0);							// jump to the entry stub with R4, SP unchanged
  1.1376 +	}
  1.1377 +
  1.1378 +__NAKED__ TInt E32Loader::V7DllEntryStub(TInt)
  1.1379 +	{
  1.1380 +
  1.1381 +	__JUMP(,lr);
  1.1382 +	}
  1.1383 +
  1.1384 +
  1.1385 +// Hash an 8 bit string at aPtr, length aLen bytes.
  1.1386 +__NAKED__ TUint32 DefaultStringHash(const TUint8* /*aPtr*/, TInt /*aLen*/)
  1.1387 +	{
  1.1388 +	asm("ldr r3, one_over_phi ");
  1.1389 +	asm("subs r1, r1, #4 ");
  1.1390 +	asm("mov r2, r0 ");
  1.1391 +	asm("mov r0, #0 ");
  1.1392 +	asm("blo 1f ");
  1.1393 +	asm("ands r12, r2, #3 ");
  1.1394 +	asm("bne hash_unal ");
  1.1395 +	asm("2: ");
  1.1396 +	asm("ldr r12, [r2], #4 ");
  1.1397 +	asm("subs r1, r1, #4 ");
  1.1398 +	asm("eor r0, r0, r12 ");
  1.1399 +	asm("umull r0, r12, r3, r0 ");
  1.1400 +	asm("bcs 2b ");
  1.1401 +	asm("1: ");
  1.1402 +	asm("adds r1, r1, #4 ");
  1.1403 +	__JUMP(eq,lr);
  1.1404 +	asm("4: ");
  1.1405 +	asm("ldrb r12, [r2], #1 ");
  1.1406 +	asm("cmp r1, #2 ");
  1.1407 +	asm("eor r0, r0, r12 ");
  1.1408 +	asm("ldrcsb r12, [r2], #1 ");
  1.1409 +	asm("eorcs r0, r0, r12, lsl #8 ");
  1.1410 +	asm("ldrhib r12, [r2], #1 ");
  1.1411 +	asm("eorhi r0, r0, r12, lsl #16 ");
  1.1412 +	asm("umull r0, r12, r3, r0 ");
  1.1413 +	__JUMP(,lr);
  1.1414 +
  1.1415 +	asm("hash_unal: ");
  1.1416 +	asm("bic r2, r2, #3 ");
  1.1417 +	asm("stmfd sp!, {r4,r5,lr} ");
  1.1418 +	asm("mov r12, r12, lsl #3 ");
  1.1419 +	asm("rsb r14, r12, #32 ");
  1.1420 +	asm("ldr r4, [r2], #4 ");
  1.1421 +	asm("3: ");
  1.1422 +	asm("eor r0, r0, r4, lsr r12 ");
  1.1423 +	asm("ldr r4, [r2], #4 ");
  1.1424 +	asm("subs r1, r1, #4 ");
  1.1425 +	asm("eor r0, r0, r4, lsl r14 ");
  1.1426 +	asm("umull r0, r5, r3, r0 ");
  1.1427 +	asm("bcs 3b ");
  1.1428 +	asm("adds r1, r1, #4 ");
  1.1429 +	asm("ldmfd sp!, {r4,r5,lr} ");
  1.1430 +	asm("subne r2, r2, #4 ");
  1.1431 +	asm("addne r2, r2, r12, lsr #3 ");
  1.1432 +	asm("bne 4b ");
  1.1433 +	__JUMP(,lr);
  1.1434 +	}
  1.1435 +
  1.1436 +// Hash a 16 bit string at aPtr, length aLen bytes.
  1.1437 +__NAKED__ TUint32 DefaultWStringHash(const TUint16* /*aPtr*/, TInt /*aLen*/)
  1.1438 +	{
  1.1439 +	asm("str lr, [sp, #-4]! ");
  1.1440 +	asm("ldr r3, one_over_phi ");
  1.1441 +	asm("subs r1, r1, #8 ");
  1.1442 +	asm("mov r2, r0 ");
  1.1443 +	asm("mov r0, #0 ");
  1.1444 +	asm("blo 1f ");
  1.1445 +	asm("ands r12, r2, #3 ");
  1.1446 +	asm("bne whash_unal ");
  1.1447 +	asm("2: ");
  1.1448 +	asm("ldmia r2!, {r12,r14} ");
  1.1449 +	asm("subs r1, r1, #8 ");
  1.1450 +	asm("eor r0, r0, r12 ");
  1.1451 +	asm("eor r0, r0, r14, ror #24 ");
  1.1452 +	asm("umull r0, r12, r3, r0 ");
  1.1453 +	asm("bcs 2b ");
  1.1454 +	asm("1: ");
  1.1455 +	asm("adds r1, r1, #8 ");
  1.1456 +	asm("beq 8f ");
  1.1457 +	asm("4: ");
  1.1458 +	asm("ldrh r12, [r2], #2 ");
  1.1459 +	asm("cmp r1, #4 ");
  1.1460 +	asm("eor r0, r0, r12 ");
  1.1461 +	asm("ldrcsh r12, [r2], #2 ");
  1.1462 +	asm("eorcs r0, r0, r12, lsl #16 ");
  1.1463 +	asm("ldrhih r12, [r2], #2 ");
  1.1464 +	asm("eorhi r0, r0, r12, ror #24 ");
  1.1465 +	asm("umull r0, r12, r3, r0 ");
  1.1466 +	asm("8: ");
  1.1467 +	__POPRET("");
  1.1468 +
  1.1469 +	asm("whash_unal: ");
  1.1470 +	asm("add r2, r2, #2 ");				// r2 must be 2 mod 4
  1.1471 +	asm("ldr r14, [r2, #-4] ");
  1.1472 +	asm("3: ");
  1.1473 +	asm("eor r0, r0, r14, lsr #16 ");	// char 0 goes into bytes 0,1
  1.1474 +	asm("ldmia r2!, {r12,r14} ");
  1.1475 +	asm("subs r1, r1, #8 ");
  1.1476 +	asm("eor r0, r0, r12, lsl #16 ");	// char 1 goes into bytes 2,3
  1.1477 +	asm("mov r12, r12, lsr #16 ");
  1.1478 +	asm("orr r12, r12, r14, lsl #16 ");	// r12 = char3:char2
  1.1479 +	asm("eor r0, r0, r12, ror #24 ");	// char 2 into bytes 1,2 ; char 3 into bytes 3,0
  1.1480 +	asm("umull r0, r12, r3, r0 ");
  1.1481 +	asm("bcs 3b ");
  1.1482 +	asm("adds r1, r1, #8 ");
  1.1483 +	asm("subne r2, r2, #2 ");
  1.1484 +	asm("bne 4b ");
  1.1485 +	__POPRET("");
  1.1486 +	}
  1.1487 +
  1.1488 +
  1.1489 +/**
  1.1490 +@publishedAll
  1.1491 +@released
  1.1492 +
  1.1493 +Calculate a 32 bit hash from a 32 bit integer.
  1.1494 +
  1.1495 +@param	aInt	The integer to be hashed.
  1.1496 +@return			The calculated 32 bit hash value.
  1.1497 +*/
  1.1498 +EXPORT_C __NAKED__ TUint32 DefaultHash::Integer(const TInt& /*aInt*/)
  1.1499 +	{
  1.1500 +	asm("ldr r0, [r0] ");
  1.1501 +	asm("ldr r1, one_over_phi ");
  1.1502 +	asm("umull r0, r2, r1, r0 ");
  1.1503 +	__JUMP(,lr);
  1.1504 +	asm("one_over_phi: ");
  1.1505 +	asm(".word 0x9e3779b9 ");
  1.1506 +	}
  1.1507 +
  1.1508 +
  1.1509 +#ifdef __USERSIDE_THREAD_DATA__
  1.1510 +
  1.1511 +/**
  1.1512 +@internalComponent
  1.1513 +
  1.1514 +Get a pointer to the thread local user data stored in the thread ID register.
  1.1515 +*/
  1.1516 +__NAKED__ TLocalThreadData* LocalThreadData()
  1.1517 +	{
  1.1518 +	GET_RWRW_TID(,r0);
  1.1519 +	__JUMP(,lr);	
  1.1520 +	}
  1.1521 +
  1.1522 +#endif