kernel/eka/euser/epoc/arm/uc_utl.cia
changeset 0 a41df078684a
child 177 a232af6b0b1f
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\euser\epoc\arm\uc_utl.cia
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <e32cia.h>
       
    19 #include <u32std.h>
       
    20 #include <e32base.h>
       
    21 #include <e32rom.h>
       
    22 #include <e32svr.h>
       
    23 #include <e32hashtab.h>
       
    24 #include <u32exec.h>
       
    25 #include "uc_std.h"
       
    26 
       
    27 
       
    28 #if defined(__MEM_MACHINE_CODED__)
       
    29 EXPORT_C __NAKED__ void Mem::Swap(TAny* /*aPtr1*/, TAny* /*aPtr2*/, TInt /*aLength*/)
       
    30 /**
       
    31 Swaps a number of bytes of data between two specified locations.
       
    32 
       
    33 The source and target areas can overlap.
       
    34 
       
    35 @param aPtr1   A pointer to the first location taking part in the swap. 
       
    36 @param aPtr2   A pointer to second location taking part in the swap. 
       
    37 @param aLength The number of bytes to be swapped between the two locations. 
       
    38                This value must not be negative.
       
    39 
       
    40 @panic USER 94 In debug builds only, if aLength is negative.
       
    41 */
       
    42     {
       
    43 
       
    44     asm("   cmp      r0,r1");
       
    45     asm("   cmpne    r2,#0");
       
    46 	__JUMP(eq,lr);
       
    47 //
       
    48 // Test for same alignment, if more than 16 bytes to swap
       
    49 //
       
    50     asm("   and      r3,r0,#3");
       
    51     asm("   and      ip,r1,#3");
       
    52     asm("   cmp      r2,#16");
       
    53     asm("   addlt    r3,r3,#4");
       
    54     asm("   cmp      r3,ip");
       
    55     asm("   beq      same_aligned_swap");
       
    56 
       
    57     asm("   stmfd    sp!,{r4,lr}");
       
    58 
       
    59     asm("swap_loop:");
       
    60 
       
    61     asm("   ldrb     r3,[r0]");
       
    62     asm("   ldrb     r4,[r1]");
       
    63     asm("   strb     r3,[r1],#1");
       
    64     asm("   strb     r4,[r0],#1");
       
    65     asm("   subs     r2,r2,#1");
       
    66 	asm("beq swap_exit1 ");
       
    67 
       
    68     asm("   ldrb     r3,[r0]");
       
    69     asm("   ldrb     r4,[r1]");
       
    70     asm("   strb     r3,[r1],#1");
       
    71     asm("   strb     r4,[r0],#1");
       
    72     asm("   subs     r2,r2,#1");
       
    73 	asm("beq swap_exit1 ");
       
    74 
       
    75     asm("   ldrb     r3,[r0]");
       
    76     asm("   ldrb     r4,[r1]");
       
    77     asm("   strb     r3,[r1],#1");
       
    78     asm("   strb     r4,[r0],#1");
       
    79     asm("   subs     r2,r2,#1");
       
    80 	asm("beq swap_exit1 ");
       
    81 
       
    82     asm("   ldrb     r3,[r0]");
       
    83     asm("   ldrb     r4,[r1]");
       
    84     asm("   strb     r3,[r1],#1");
       
    85     asm("   strb     r4,[r0],#1");
       
    86     asm("   subs     r2,r2,#1");
       
    87     asm("   bne      swap_loop");
       
    88 	asm("swap_exit1: ");
       
    89 	__POPRET("r4,");
       
    90 
       
    91     asm("same_aligned_swap:");
       
    92 
       
    93     asm("   stmfd    sp!,{r4-r10,lr}");
       
    94 //
       
    95 // r3 contains the byte offset from word alignment, 0,1,2 or 3
       
    96 // subtract 1 to get -1,0,1 or 2, and if -1 make it 3
       
    97 // that gives us 0,1,2 or 3 if the alignment is 3,2,1 or 0 respectively
       
    98 // We can use that to jump directly to the appropriate place for
       
    99 // swapping the relevent number of bytes to achieve word alignment
       
   100 // r4 is set to 3-r3 to correct the length for the number of bytes
       
   101 // swapped
       
   102 //
       
   103     asm("   subs     r3,r3,#1");
       
   104     asm("   movmi    r3,#3");
       
   105     asm("   rsb      r4,r3,#3");
       
   106     asm("   sub      r2,r2,r4");
       
   107 	asm("   add      pc,pc,r3,asl #4");
       
   108 	asm("	nop ");	// never executed
       
   109 //
       
   110 // Jumps here if 3 bytes to swap before word aligned
       
   111 //
       
   112     asm("   ldrb     r4,[r0]");
       
   113     asm("   ldrb     ip,[r1]");
       
   114     asm("   strb     r4,[r1],#1");
       
   115     asm("   strb     ip,[r0],#1");
       
   116 //
       
   117 // Jumps here if 2 bytes to swap before word aligned
       
   118 //
       
   119     asm("   ldrb     r4,[r0]");
       
   120     asm("   ldrb     ip,[r1]");
       
   121     asm("   strb     r4,[r1],#1");
       
   122     asm("   strb     ip,[r0],#1");
       
   123 //
       
   124 // Jumps here if 1 byte to swap before word aligned
       
   125 //
       
   126     asm("   ldrb     r4,[r0]");
       
   127     asm("   ldrb     ip,[r1]");
       
   128     asm("   strb     r4,[r1],#1");
       
   129     asm("   strb     ip,[r0],#1");
       
   130 //
       
   131 // We are now word aligned. Fast swapping, here we come...
       
   132 //
       
   133     asm("word_aligned_swap:");
       
   134     asm("   movs     ip,r2,lsr #6"); // Number of 64 blocks to swap
       
   135     asm("   beq      its_smaller_swap");
       
   136 
       
   137     asm("swap_64_bytes:");
       
   138     asm("   ldmia    r1,{r3-r6}");
       
   139     asm("   ldmia    r0,{r7-r10}");
       
   140     asm("   stmia    r1!,{r7-r10}");
       
   141     asm("   stmia    r0!,{r3-r6}");
       
   142     asm("   ldmia    r1,{r3-r6}");
       
   143     asm("   ldmia    r0,{r7-r10}");
       
   144     asm("   stmia    r1!,{r7-r10}");
       
   145     asm("   stmia    r0!,{r3-r6}");
       
   146     asm("   ldmia    r1,{r3-r6}");
       
   147     asm("   ldmia    r0,{r7-r10}");
       
   148     asm("   stmia    r1!,{r7-r10}");
       
   149     asm("   stmia    r0!,{r3-r6}");
       
   150     asm("   ldmia    r1,{r3-r6}");
       
   151     asm("   ldmia    r0,{r7-r10}");
       
   152     asm("   stmia    r1!,{r7-r10}");
       
   153     asm("   stmia    r0!,{r3-r6}");
       
   154     asm("   subs     ip,ip,#1");
       
   155     asm("   bne      swap_64_bytes");
       
   156 //
       
   157 // Less than 64 bytes to go...
       
   158 //
       
   159     asm("its_smaller_swap:");
       
   160     asm("   ands     r2,r2,#63");
       
   161 	asm("beq swap_exit2 ");
       
   162     asm("   cmp      r2,#4");
       
   163     asm("   blt      finish_swap");
       
   164     asm("final_swap_loop:");
       
   165     asm("   ldr      r3,[r1]");
       
   166     asm("   ldr      ip,[r0]");
       
   167     asm("   str      r3,[r0],#4");
       
   168     asm("   str      ip,[r1],#4");
       
   169     asm("   subs     r2,r2,#4");
       
   170     asm("   cmp      r2,#4");
       
   171     asm("   bge      final_swap_loop");
       
   172 //
       
   173 // Less than 4 bytes to go...
       
   174 //
       
   175     asm("finish_swap:");
       
   176     asm("   tst      r2,#2");
       
   177     asm("   ldrneb   r3,[r0]");
       
   178     asm("   ldrneb   ip,[r1]");
       
   179     asm("   strneb   r3,[r1],#1");
       
   180     asm("   strneb   ip,[r0],#1");
       
   181     asm("   ldrneb   r3,[r0]");
       
   182     asm("   ldrneb   ip,[r1]");
       
   183     asm("   strneb   r3,[r1],#1");
       
   184     asm("   strneb   ip,[r0],#1");
       
   185 
       
   186     asm("   tst      r2,#1");
       
   187     asm("   ldrneb   r3,[r0]");
       
   188     asm("   ldrneb   ip,[r1]");
       
   189     asm("   strneb   r3,[r1],#1");
       
   190     asm("   strneb   ip,[r0],#1");
       
   191 
       
   192 	asm("swap_exit2: ");
       
   193 	__POPRET("r4-r10,");
       
   194     }
       
   195 #endif
       
   196 
       
   197 #ifdef __REGIONS_MACHINE_CODED__
       
   198 
       
   199 __NAKED__ GLDEF_C void AllocAnotherRect( TRegion * /*aRegion*/ )
       
   200 	{
       
   201 	// Returns with Z flag set to indicate error
       
   202 	
       
   203 	asm("ldr r1, [r0, #4] ");			// r1=iError
       
   204 	asm("cmp r1, #0 ");
       
   205 	asm("bne return_error ");
       
   206 	asm("ldr r1, [r0, #8] ");			// r1=iAllocedRects
       
   207 	asm("ldr r12, [r0] ");				// r12=iCount
       
   208 	asm("tst r1, #0x40000000 ");		// test ERRegionBuf
       
   209 	asm("beq allocanother1 ");			// don't branch if TRegionFix
       
   210 	asm("cmn r1, r12 ");				// test if iCount==-iAllocedRects
       
   211 	__JUMP(ne,lr);
       
   212 	asm("b  " CSM_ZN7TRegion10ForceErrorEv);		// if so, ForceError()
       
   213 	asm("allocanother1: ");
       
   214 	asm("cmp r1, #0 ");
       
   215 	asm("bpl allocanother3 ");			// branch if RRegion, continue if RRegionBuf
       
   216 	asm("orr r2, r1, #0x40000000 ");	// r2=iAllocedRects|ERRegionBuf
       
   217 	asm("cmn r2, r12 ");				// check if iCount==(-(iAllocedRects|ERRegionBuf))
       
   218 	__JUMP(ne,lr);
       
   219 	asm("ldr r2, [r0, #12] ");			// r2=iGranularity
       
   220 	asm("add r1, r12, r2 ");			// iAllocedRects=iCount+iGranularity - change into RRegion
       
   221 	asm("str r1, [r0, #8] ");
       
   222 	asm("stmfd sp!, {r0,r1,r12,lr} ");	// save registers used in function call
       
   223 	asm("mov r0, r1, lsl #4 ");			// number of bytes to allocate
       
   224 	asm("bl  " CSM_ZN4User5AllocEi);			// User::Alloc
       
   225 	asm("movs r2, r0 ");				// returned pointer into r2
       
   226 	asm("ldmfd sp!, {r0,r1,r12,lr} ");	// restore registers
       
   227 	asm("add r3, r0, #20 ");			// r3=address of first rectangle
       
   228 	asm("str r2, [r0, #16] ");			// iRectangleList=returned pointer
       
   229 	asm("beq  " CSM_ZN7TRegion10ForceErrorEv);	// if pointer null, ForceError()
       
   230 	asm("cmp r12, #0 ");
       
   231 	asm("beq return_success ");
       
   232 	asm("stmfd sp!, {r4,r5} ");
       
   233 	asm("allocanother2: ");
       
   234 	asm("ldmia r3!, {r0,r1,r4,r5} ");	// copy data to new area
       
   235 	asm("subs r12, r12, #1 ");
       
   236 	asm("stmia r2!, {r0,r1,r4,r5} ");
       
   237 	asm("bne allocanother2 ");
       
   238 	asm("ldmfd sp!, {r4,r5} ");
       
   239 	asm("return_success: ");
       
   240 	asm("movs r0, #1 ");				// clear Z flag to indicate success
       
   241 	__JUMP(,lr);
       
   242 	asm("allocanother3: ");				// come here if RRegion
       
   243 	asm("cmp r1, r12 ");				// check if iCount==iAllocedRects
       
   244 	__JUMP(ne,lr);
       
   245 	asm("ldr r2, [r0, #12] ");			// r2 = iGranularity
       
   246 	asm("add r1, r1, r2 ");				// iAllocedRects+=iGranularity
       
   247 	asm("str r1, [r0, #8] ");
       
   248 	asm("stmfd sp!, {r0,lr} ");			// preserve r0,lr across function call
       
   249 	asm("ldr r0, [r0, #16] ");			// r0=address of current cell
       
   250 	asm("mov r1, r1, lsl #4 ");			// r1=number of bytes to allocate
       
   251 	asm("mov r2, #0 ");
       
   252 	asm("bl  " CSM_ZN4User7ReAllocEPvii);		// User::ReAlloc
       
   253 	asm("movs r2, r0 ");				// returned pointer into r2
       
   254 	asm("ldmfd sp!, {r0,lr} ");			// restore r0,lr
       
   255 	asm("strne r2, [r0, #16] ");		// if returned ptr not null, iRectangleList=returned ptr
       
   256 	__JUMP(ne,lr);
       
   257 	asm("b  " CSM_ZN7TRegion10ForceErrorEv);		// else ForceError()
       
   258 	}
       
   259 
       
   260 
       
   261 __NAKED__ EXPORT_C void TRegion::ForceError()
       
   262 	{
       
   263 	// Returns with Z flag set to indicate error
       
   264 	
       
   265 	asm("stmfd sp!, {r0,lr} ");
       
   266 	asm("bl " CSM_ZN7TRegion5ClearEv);	// Clear()
       
   267 	asm("ldmfd sp!, {r0,lr} ");			// restore r0,lr
       
   268 	asm("mov r1, #1 ");
       
   269 	asm("str r1, [r0, #4] ");			// iError=ETrue
       
   270 	asm("return_error: ");
       
   271 	asm("movs r0, #0 ");				// set Z flag to indicate error
       
   272 	__JUMP(,lr);
       
   273 	}
       
   274 
       
   275 
       
   276 
       
   277 __NAKED__ EXPORT_C TRect TRegion::BoundingRect() const
       
   278 /**
       
   279 Gets the minimal rectangle that bounds the entire region.
       
   280 
       
   281 @return The region's minimal bounding rectangle.
       
   282 */
       
   283 	{
       
   284 	asm("ldr r2, [r1] ");			// r2=iCount
       
   285 	asm("cmp r2, #0 ");				// list empty?
       
   286 	asm("beq boundingrect0 ");		// branch if empty
       
   287 	asm("ldr r3, [r1, #8] ");			// if not empty, r3 points to first rectangle
       
   288 	asm("stmfd sp!, {r4-r8,lr} ");
       
   289 	asm("cmn r3, r3 ");
       
   290 	asm("ldrcc r3, [r1, #16] ");		// if RRegion
       
   291 	asm("addcs r3, r1, #20 ");			// RRegionBuf
       
   292 	asm("submi r3, r3, #8 ");			// TRegionFix
       
   293 	asm("ldmia r3!, {r4-r7} ");			// if not empty bounds = first rectangle
       
   294 	asm("b boundingrect2 ");			// if not empty go and check rest of list
       
   295 	asm("boundingrect1: ");
       
   296 	asm("ldmia r3!, {r1,r8,r12,lr} ");	// fetch next rectangle
       
   297 	asm("cmp r1, r4 ");					// if next.iTl.iX<bounds.iTl.iX
       
   298 	asm("movlt r4, r1 ");				//		bounds.iTl.iX=next.iTl.iX
       
   299 	asm("cmp r8, r5 ");					// if next.iTl.iY<bounds.iTl.iY
       
   300 	asm("movlt r5, r8 ");				//		bounds.iTl.iY=next.iTl.iY
       
   301 	asm("cmp r12, r6 ");				// if next.iBr.iX>bounds.iBr.iX
       
   302 	asm("movgt r6, r12 ");				//		bounds.iBr.iX=next.iBr.iX
       
   303 	asm("cmp lr, r7 ");					// if next.iBr.iY>bounds.iBr.iY
       
   304 	asm("movgt r7, lr ");				//		bounds.iBr.iY=next.iBr.iY
       
   305 	asm("boundingrect2: ");
       
   306 	asm("subs r2, r2, #1 ");			// decrement count
       
   307 	asm("bne boundingrect1 ");			// repeat for all rectangles
       
   308 	asm("stmia r0, {r4-r7} ");			// store result
       
   309 	__POPRET("r4-r8,");
       
   310 
       
   311 	asm("boundingrect0: ");
       
   312 	asm("mov r1, #0 ");					// if list empty, bounds = 0,0,0,0
       
   313 	asm("mov r3, #0 ");
       
   314 	asm("mov r12, #0 ");
       
   315 	asm("stmia r0, {r1,r2,r3,r12} ");	// store result
       
   316 	__JUMP(,lr);
       
   317 	}
       
   318 
       
   319 
       
   320 
       
   321 
       
   322 __NAKED__ EXPORT_C TBool TRegion::IsContainedBy(const TRect & /*aRect*/) const
       
   323 /**
       
   324 Tests whether the region is fully enclosed within the specified rectangle.
       
   325 
       
   326 @param aRect The specified rectangle.
       
   327  
       
   328 @return True, if the region is fully enclosed within the rectangle (their sides 
       
   329         may touch); false, otherwise.
       
   330 */
       
   331 	{
       
   332 	asm("ldr r12, [r0, #8] ");			// r12 points to first rectangle
       
   333 	asm("stmfd sp!, {r4-r7,lr} ");	
       
   334 	asm("cmn r12, r12 ");
       
   335 	asm("ldrcc r12, [r0, #16] ");		// if RRegion
       
   336 	asm("addcs r12, r0, #20 ");			// RRegionBuf
       
   337 	asm("submi r12, r12, #8 ");			// TRegionFix
       
   338 
       
   339 	asm("ldr r0, [r0] ");				// r0=iCount
       
   340 	asm("ldmia r1, {r4-r7} ");			// aRect coordinates into r4-r7
       
   341 	
       
   342 	asm("subs r0, r0, #1 ");			// decrement it
       
   343 	asm("bmi iscontainedby2 ");			// if iCount was zero, return TRUE
       
   344 	
       
   345 	asm("iscontainedby1: ");
       
   346 	asm("ldmia r12!, {r1,r2,r3,lr} ");	// coordinates of next rectangle
       
   347 	asm("cmp r1, r4 ");					// compare next.iTl.iX with aRect.iTl.iX
       
   348 	asm("cmpge r2, r5 ");				// if >=, compare next.iTl.iY with aRect.iTl.iY
       
   349 	asm("cmpge r6, r3 ");				// if >=, compare aRect.Br.iX with next.iBr.iX
       
   350 	asm("cmpge r7, lr ");				// if >=, compare aRect.Br.iY with next.iBr.iY
       
   351 	asm("subges r0, r0, #1 ");			// if >=, next is contained in aRect, so iterate
       
   352 	asm("bge iscontainedby1 ");			// will drop through if r0<0 or if next exceeds aRect
       
   353 	asm("iscontainedby2: ");
       
   354 	asm("mov r0, r0, lsr #31 ");		// return 1 if r0<0, 0 if r0>=0
       
   355 	__POPRET("r4-r7,");
       
   356 	}
       
   357 
       
   358 
       
   359 
       
   360 
       
   361 __NAKED__ EXPORT_C void TRegion::Copy(const TRegion & /*aRegion*/)
       
   362 /**
       
   363 Copies another region to this region.
       
   364 
       
   365 The state of the specified region's error flag is also copied.
       
   366 
       
   367 @param aRegion The region to be copied.
       
   368 */
       
   369 	{
       
   370 	asm("ldr r2, [r1, #4] ");					// r2 = aRegion.iError
       
   371 	asm("cmp r2, #0 ");
       
   372 	asm("bne  " CSM_ZN7TRegion10ForceErrorEv);	// if (aRegion.iError) ForceError();
       
   373 	asm("ldr r2, [r1] ");						// r1 = aRegion.iCount
       
   374 	asm("cmp r2, #0 ");
       
   375 	asm("beq " CSM_ZN7TRegion5ClearEv);			// region to copy is empty so simply clear our buffer
       
   376 	asm("stmfd sp!, {r0,r1,r4,r5,r6,lr} ");		// preserve r0,r1,lr across function calls
       
   377 	asm("mov r4, r1 ");
       
   378 	asm("mov r5, r0 ");
       
   379 	asm("ldr r2, [r0, #4] ");					// r2 = iError
       
   380 	asm("cmp r2, #0 ");
       
   381 	asm("blne  " CSM_ZN7TRegion5ClearEv);		// if (iError) Clear();
       
   382 	asm("mov r0, r5 ");
       
   383 	asm("ldr r1, [r4] ");						// r1 = aRegion.iCount, r0 = this
       
   384 	asm("bl	 " CSM_ZN7TRegion11SetListSizeEi);	// SetListSize(aRegion.iCount);
       
   385 	asm("cmp r0, #0 ");
       
   386 	asm("beq copyregion_end ");
       
   387 	asm("ldr r3, [r4] ");						// r3 = aRegion.iCount
       
   388 	asm("cmp r3, #0 ");
       
   389 	asm("str r3, [r5] ");						// iCount=aRegion.iCount
       
   390 	asm("beq copyregion_end ");
       
   391 	asm("ldr r0, [r5, #8] ");					// r0 points to first rectangle
       
   392 	asm("cmn r0, r0 ");
       
   393 	asm("ldrcc r0, [r5, #16] ");				// if RRegion
       
   394 	asm("addcs r0, r5, #20 ");					// RRegionBuf
       
   395 	asm("submi r0, r0, #8 ");					// TRegionFix
       
   396 	asm("ldr r1, [r4, #8] ");					// r1 points to first rectangle
       
   397 	asm("cmn r1, r1 ");
       
   398 	asm("ldrcc r1, [r4, #16] ");				// if RRegion
       
   399 	asm("addcs r1, r4, #20 ");					// RRegionBuf
       
   400 	asm("submi r1, r1, #8 ");					// TRegionFix
       
   401 	asm("copyregion1: ");
       
   402 	asm("ldmia r1!, {r2,r4,r5,r12} ");			// copy aRegion.iRectangleList to iRectangleList
       
   403 	asm("subs r3, r3, #1 ");
       
   404 	asm("stmia r0!, {r2,r4,r5,r12} ");
       
   405 	asm("bne copyregion1 ");
       
   406 
       
   407 	asm("copyregion_end: ");
       
   408 	__POPRET("r0,r1,r4,r5,r6,");
       
   409 	}
       
   410 
       
   411 
       
   412 
       
   413 
       
   414 __NAKED__ EXPORT_C void TRegion::Offset(const TPoint & /*anOffset*/)
       
   415 /**
       
   416 Moves the region by adding a TPoint offset to the co-ordinates of its corners.
       
   417 	
       
   418 The size of the region is not changed.
       
   419 	
       
   420 @param aOffset The offset by which the region is moved. The region is moved 
       
   421                horizontally by aOffset.iX pixels and vertically by aOffset.iY pixels.
       
   422 */
       
   423 	{
       
   424 	asm("ldmia r1, {r1,r2} ");		// r1=anOffset.iX, r2=anOffset.iY
       
   425 	// fall through...
       
   426 	}
       
   427 
       
   428 
       
   429 
       
   430 
       
   431 __NAKED__ EXPORT_C void TRegion::Offset(TInt /*xOffset*/,TInt /*yOffset*/)
       
   432 /**
       
   433 Moves the region by adding X and Y offsets to the co-ordinates of its corners.
       
   434 	
       
   435 The size of the region is not changed.
       
   436 	
       
   437 @param aXoffset The number of pixels by which to move the region horizontally. 
       
   438                 If negative, the region moves leftwards. 
       
   439 @param aYoffset The number of pixels by which to move the region vertically. 
       
   440                 If negative, the region moves upwards.
       
   441 */
       
   442 	{
       
   443 	asm("ldr r12, [r0] ");			// r12=iCount
       
   444 	asm("cmp r12, #0 ");
       
   445 	__JUMP(eq,lr);
       
   446 	asm("ldr r3, [r0, #8] ");		// r0 points to first rectangle
       
   447 	asm("cmn r3, r3 ");
       
   448 	asm("ldrcc r0, [r0, #16] ");	// if RRegion
       
   449 	asm("addcs r0, r0, #20 ");		// RRegionBuf
       
   450 	asm("submi r0, r0, #8 ");		// TRegionFix
       
   451 	asm("stmfd sp!, {r4,r5,lr} ");
       
   452 	asm("offsetregion2: ");
       
   453 	asm("ldmia r0, {r3-r5,lr} ");	// r3-r5,lr = next rectangle coordinates
       
   454 	asm("subs r12, r12, #1 ");
       
   455 	asm("add r3, r3, r1 ");			// Tl.iX += anOffset.iX
       
   456 	asm("add r4, r4, r2 ");			// Tl.iY += anOffset.iY
       
   457 	asm("add r5, r5, r1 ");			// Br.iX += anOffset.iX
       
   458 	asm("add lr, lr, r2 ");			// Br.iY += anOffset.iY
       
   459 	asm("stmia r0!, {r3-r5,lr} ");	// store new coordinates
       
   460 	asm("bne offsetregion2 ");
       
   461 	__POPRET("r4,r5,");
       
   462 	}
       
   463 
       
   464 
       
   465 
       
   466 
       
   467 __NAKED__ EXPORT_C TBool TRegion::Contains(const TPoint & /*aPoint*/) const
       
   468 /**
       
   469 Tests whether a point is located within the region.
       
   470 
       
   471 If the point is located on the top or left hand side of any rectangle in the 
       
   472 region, it is considered to be within that rectangle and within the region. 
       
   473 
       
   474 If the point is located on the right hand side or bottom of a rectangle, it 
       
   475 is considered to be outside that rectangle, and may be outside the region.
       
   476 
       
   477 @param aPoint The specified point. 
       
   478 
       
   479 @return True, if the point is within the region; false, otherwise.
       
   480 */
       
   481 	{
       
   482 	asm("ldr r12, [r0] ");			// r12 = iCount
       
   483 	asm("stmfd sp!, {r4,r5,lr} ");
       
   484 	asm("cmp r12, #0 ");
       
   485 	asm("beq contains0 ");			// if iCount=0, return FALSE
       
   486 	asm("ldr r3, [r0, #8] ");		// r0 points to first rectangle
       
   487 	asm("cmn r3, r3 ");
       
   488 	asm("ldrcc r0, [r0, #16] ");	// if RRegion
       
   489 	asm("addcs r0, r0, #20 ");		// RRegionBuf
       
   490 	asm("submi r0, r0, #8 ");		// TRegionFix
       
   491 	asm("ldmia r1, {r1, r2} ");		// r1=aPoint.iX, r2=aPoint.iY
       
   492 	asm("contains1: ");
       
   493 	asm("ldmia r0!, {r3-r5,lr} ");	// coordinates of next rectangle into r3-r5,lr
       
   494 	asm("cmp r3, r1 ");				// compare next.iTl.iX with aPoint.iX
       
   495 	asm("cmple r4, r2 ");			// if <=, compare next.iTl.iY with aPoint.iY
       
   496 	asm("bgt contains2 ");			// if >, aPoint is not contained in rectangle, so iterate
       
   497 	asm("cmp r1, r5 ");				// compare aPoint.iX with next.iBr.iX
       
   498 	asm("cmplt r2, lr ");			// if <, compare aPoint.iY with next.iBr.iY
       
   499 	asm("contains2: ");
       
   500 	asm("subges r12, r12, #1 ");	// if >=, aPoint is not contained in rect, so iterate
       
   501 	asm("bgt contains1 ");
       
   502 	asm("cmp r12, #0 ");
       
   503 	asm("movne r0, #1 ");			// if r12 non-zero, return TRUE else FALSE
       
   504 	asm("contains0: ");
       
   505 	asm("moveq r0, #0 ");
       
   506 	__POPRET("r4,r5,");
       
   507 	}
       
   508 
       
   509 
       
   510 
       
   511 
       
   512 __NAKED__ EXPORT_C TBool TRegion::Intersects(const TRect &/*aRect*/) const
       
   513 /**
       
   514 Tests whether where there is any intersection between this region and the specified rectangle.
       
   515 
       
   516 @param aRect The specified rectangle.
       
   517  
       
   518 @return True, if there is an intersection; false, otherwise.
       
   519 */
       
   520 	{
       
   521 	asm("ldr    r12, [r0] ");		// r12 = iCount
       
   522 	asm("stmfd  sp!, {r4-r7,lr} ");
       
   523 	asm("cmp    r12, #0 ");
       
   524 	asm("beq    intersects0 ");		// if iCount=0, return FALSE
       
   525 	asm("ldr    lr, [r0, #8] ");	// r0 points to first rectangle	
       
   526 	asm("ldmia  r1, {r1-r4} ");		// (load aRect into r1 - r4)
       
   527 	asm("cmn    lr, lr ");
       
   528 	asm("ldrcc  r0, [r0, #16] ");	// if RRegion
       
   529 	asm("addcs  r0, r0, #20 ");		// RRegionBuf
       
   530 	asm("submi  r0, r0, #8 ");		// TRegionFix
       
   531 	asm("cmp    r1, r3 ");			// check if aRect is empty
       
   532 	asm("cmplt  r2, r4 ");
       
   533 	asm("bge    intersects0 ");
       
   534 	
       
   535 	asm("intersects1: ");
       
   536 	asm("ldmia  r0!, {r5-r7,lr} ");	// coordinates of next rectangle into r5-r7,lr	
       
   537 	asm("cmp    r1, r7 ");			// check if they intersect
       
   538 	asm("cmplt  r2, lr ");
       
   539 	asm("cmplt  r5, r3 ");
       
   540 	asm("cmplt  r6, r4 ");
       
   541 	asm("subges r12, r12, #1 ");	// if not then decrement and loop
       
   542 	asm("bgt    intersects1 ");
       
   543 	
       
   544 	asm("intersects0: ");
       
   545 	asm("movge  r0, #0 ");
       
   546 	asm("movlt  r0, #1 ");
       
   547 	__POPRET("r4-r7,");
       
   548 	}
       
   549 
       
   550 
       
   551 
       
   552 
       
   553 __NAKED__ void TRegion::DeleteRect(TRect * /*aRect*/)
       
   554 //
       
   555 // Delete a specific rectangle in the list.
       
   556 //
       
   557 	{
       
   558 	asm("ldr r12, [r0] ");			// r12=iCount
       
   559 	asm("ldr r3, [r0, #8] ");		// r0 points to first rectangle
       
   560 	asm("subs r12, r12, #1 ");		// decrement it
       
   561 	asm("str r12, [r0] ");			// iCount--;
       
   562 	asm("cmn r3, r3 ");
       
   563 	asm("ldrcc r0, [r0, #16] ");	// if RRegion
       
   564 	asm("addcs r0, r0, #20 ");		// RRegionBuf
       
   565 	asm("submi r0, r0, #8 ");		// TRegionFix
       
   566 	asm("sub r2, r1, r0 ");			// r2=offset of aRect from iRectangleList
       
   567 	asm("subs r12, r12, r2, lsr #4 ");	// r12 now equals number of rectangles requiring moving
       
   568 	__JUMP(eq,lr);
       
   569 	asm("add r0, r1, #16 ");			// r0 = aRect+1
       
   570 	asm("stmfd sp!, {r4,lr} ");
       
   571 	asm("deleterect1: ");
       
   572 	asm("ldmia r0!, {r2-r4,lr} ");		// move rectangles following aRect back by one place
       
   573 	asm("subs r12, r12, #1 ");
       
   574 	asm("stmia r1!, {r2-r4,lr} ");
       
   575 	asm("bne deleterect1 ");
       
   576 	__POPRET("r4,");
       
   577 	}
       
   578 
       
   579 
       
   580 
       
   581 
       
   582 __NAKED__ EXPORT_C void TRegion::ClipRect(const TRect & /*aRect*/)
       
   583 /**
       
   584 Clips the region to the specified rectangle.
       
   585 
       
   586 The resulting region is the area of overlap between the region and the rectangle. 
       
   587 If there is no overlap, all rectangles within this region are deleted and 
       
   588 the resulting region is empty.
       
   589 
       
   590 @param aRect The rectangle to which this region is to be clipped.
       
   591 */
       
   592 // Can not fail.
       
   593 	{
       
   594 	asm("ldr r12, [r0] ");				// r12=iCount
       
   595 	asm("cmp r12, #0 ");
       
   596 	__JUMP(eq,lr);
       
   597 	asm("stmfd sp!, {r4-r10,lr} ");
       
   598 	asm("ldmia r1, {r2-r5} ");			// get coordinates of aRect into r2-r5
       
   599 	asm("ldr r1, [r0, #8] ");			// r1 points to first rectangle
       
   600 	asm("cmn r1, r1 ");
       
   601 	asm("ldrcc r1, [r0, #16] ");		// if RRegion
       
   602 	asm("addcs r1, r0, #20 ");			// RRegionBuf
       
   603 	asm("submi r1, r1, #8 ");			// TRegionFix
       
   604 
       
   605 	asm("cliprect1: ");
       
   606 	asm("ldmia r1!, {r6-r9} ");			// next rectangle coordinates into r6-r9
       
   607 	asm("cmp r6, r2 ");					// clip the rectangle to aRect
       
   608 	asm("movlt r6, r2 ");	
       
   609 	asm("strlt r2, [r1, #-16] ");
       
   610 	asm("cmp r7, r3 ");
       
   611 	asm("movlt r7, r3 ");
       
   612 	asm("strlt r3, [r1, #-12] ");
       
   613 	asm("cmp r8, r4 ");
       
   614 	asm("movgt r8, r4 ");
       
   615 	asm("strgt r4, [r1, #-8] ");
       
   616 	asm("cmp r9, r5 ");
       
   617 	asm("movgt r9, r5 ");
       
   618 	asm("strgt r5, [r1, #-4] ");
       
   619 	asm("cmp r6, r8 ");					// check if clipped rect is empty
       
   620 	asm("cmplt r7, r9 ");				// empty if r6>=r8 or r7>=r9
       
   621 	asm("bge cliprect_delete ");		// if empty, branch to other loop to delete rect 
       
   622 	asm("subs r12, r12, #1 ");			// decrement loop counter
       
   623 	asm("bne cliprect1 ");				// loop if any more rectangles to do
       
   624 	__POPRET("r4-r10,");
       
   625 
       
   626 	asm("cliprect_delete: ");			// (enter loop here)
       
   627 	asm("ldr lr, [r0] ");				// lr=iCount, updateed if we delete rects
       
   628 	asm("sub r10, r1, #16 ");			// r1 -> next rect, r10 -> previous deleted rect
       
   629 	asm("subs r12, r12, #1 ");			// decrement loop counter
       
   630 	asm("beq cliprect_move_end ");	
       
   631 	asm("cliprect_move: ");
       
   632 	asm("ldmia r1!, {r6-r9} ");			// next rectangle coordinates into r6-r9
       
   633 	asm("cmp r6, r2 ");					// clip the rectangle to aRect
       
   634 	asm("movlt r6, r2 ");
       
   635 	asm("cmp r7, r3 ");
       
   636 	asm("movlt r7, r3 ");
       
   637 	asm("cmp r8, r4 ");
       
   638 	asm("movgt r8, r4 ");
       
   639 	asm("cmp r9, r5 ");
       
   640 	asm("movgt r9, r5 ");
       
   641 	asm("cmp r6, r8 ");					// check if clipped rect is empty
       
   642 	asm("cmplt r7, r9 ");				// empty if r6>=r8 or r7>=r9
       
   643 	asm("stmltia r10!, {r6-r9} ");		// if non-empty then store the rect
       
   644 	asm("subge lr, lr, #1 ");			// else decrement rect count	
       
   645 	asm("subs r12, r12, #1 ");			// decrement loop counter
       
   646 	asm("bne cliprect_move ");			// loop if any more rectangles to do
       
   647 	asm("cliprect_move_end: ");	
       
   648 	asm("sub lr, lr, #1 ");				// decrement count for first deleted rect
       
   649 	asm("str lr, [r0] ");				// store updated iCount
       
   650 	__POPRET("r4-r10,");	
       
   651 	}
       
   652 
       
   653 
       
   654 
       
   655 	
       
   656 __NAKED__ EXPORT_C void TRegion::SubRect(const TRect& /*aRect*/,TRegion* /*aSubtractedRegion*/)
       
   657 /**
       
   658 Removes a rectangle from this region.
       
   659 
       
   660 If there is no intersection between the rectangle and this region, then this 
       
   661 region is unaffected. 
       
   662 
       
   663 @param aRect             The rectangular area to be removed from this region. 
       
   664 @param aSubtractedRegion A pointer to a region. If this is supplied, the
       
   665                          removed rectangle is added to it. By default this
       
   666                          pointer is NULL.
       
   667 */
       
   668 	{
       
   669 	asm("ldr r12, [r0] ");			// r12=iCount=limit
       
   670 	asm("cmp r12, #0 ");
       
   671 	__JUMP(eq,lr);
       
   672 	asm("stmfd sp!, {r3-r11,lr} ");
       
   673 	asm("ldmia r1, {r4-r7} ");		// r4-r7 = coordinates of aRect
       
   674 	asm("cmp r4, r6 ");				// check if aRect is empty i.e. (r4>=r6 || r5>=r7)
       
   675 	asm("cmplt r5, r7 ");
       
   676 	asm("bge subrect_end ");		// if aRect is empty nothing to do
       
   677 
       
   678 	asm("mov r3, #0 ");				// r3=index
       
   679 	asm("subrect1: ");
       
   680 	asm("ldr lr, [r0, #8] ");		// lr points to first rectangle
       
   681 	asm("cmn lr, lr ");
       
   682 	asm("ldrcc lr, [r0, #16] ");	// if RRegion
       
   683 	asm("addcs lr, r0, #20 ");		// RRegionBuf
       
   684 	asm("submi lr, lr, #8 ");		// TRegionFix
       
   685 	asm("add lr, lr, r3, lsl #4 ");	// lr=iRectangleList+index
       
   686 //	asm("ldmia r1, {r4-r7} ");		// r4-r7 = coordinates of aRect
       
   687 	asm("ldmia lr, {r8-r11} ");		// r8-r11 = coordinates of next rectangle in region
       
   688 	asm("cmp r10, r4 ");			// compare next.iBr.iX with aRect.iTl.iX
       
   689 	asm("cmpgt r11, r5 ");			// if >, compare next.iBr.iY with aRect.iTl.iY
       
   690 	asm("cmpgt r6, r8 ");			// if >, compare aRect.iBr.iX with next.iTl.iX
       
   691 	asm("cmpgt r7, r9 ");			// if >, compare aRect.iBr.iY with next.iTl.iY
       
   692 	asm("addle r3, r3, #1 ");		// if empty intersection, increment index
       
   693 	asm("ble subrect2 ");			// if <=, next and aRect have empty intersection, so skip
       
   694 	asm("add r4, lr, #16 ");		// r4 = source pointer for copy, lr = dest
       
   695 	asm("ldr r5, [r0] ");			// r5 = iCount
       
   696 	asm("sub r5, r5, #1 ");			// decrement iCount
       
   697 	asm("str r5, [r0] ");
       
   698 	asm("sub r12, r12, #1 ");		// decrement limit
       
   699 	asm("subs r5, r5, r3 ");		// loop count for copy = iCount-index
       
   700 	asm("beq subrect4 ");			// if loop count zero, skip the copy
       
   701 	asm("stmfd sp!, {r8,r9} ");		// preserve r8,r9
       
   702 	asm("subrect3: ");
       
   703 	asm("ldmia r4!, {r6-r9} ");		// remove the current rectangle
       
   704 	asm("stmia lr!, {r6-r9} ");
       
   705 	asm("subs r5, r5, #1 ");
       
   706 	asm("bne subrect3 ");
       
   707 	asm("ldmfd sp!, {r8-r9} ");		// restore r8,r9
       
   708 	asm("subrect4: ");
       
   709 	asm("ldmia r1, {r4-r7} ");		// restore coordinates of aRect into r4-r7
       
   710 	asm("cmp r7, r11 ");			// compare aRect.iBr.iY with rect.iBr.iY
       
   711 	asm("movgt r7, r11 ");			// r7=inter.iBr.iY
       
   712 	asm("bllt subrectapp1 ");		// if <, append 1st subrectangle
       
   713 	asm("cmp r5, r9 ");				// compare aRect.iTl.iY with rect.iTl.iY
       
   714 	asm("movlt r5, r9 ");			// r5=inter.iTl.iY
       
   715 	asm("blgt subrectapp2 ");		// if >, append 2nd subrectangle
       
   716 	asm("cmp r6, r10 ");			// compare aRect.iBr.iX with rect.iBr.iX
       
   717 	asm("movgt r6, r10 ");			// r6=inter.iBr.iX
       
   718 	asm("bllt subrectapp3 ");		// if <, append 3rd subrectangle
       
   719 	asm("cmp r4, r8 ");				// compare aRect.iTl.iX with rect.iTl.iX
       
   720 	asm("movlt r4, r8 ");			// r4=inter.iTl.iX
       
   721 	asm("blgt subrectapp4 ");		// if >, append 4th subrectangle
       
   722 	asm("ldr lr, [r0, #4] ");		// lr=iError
       
   723 	asm("cmp lr, #0 ");				// check for an error
       
   724 	asm("bne subrect_end ");
       
   725 	asm("cmp r2, #0 ");				// check if aSubtractedRegion!=NULL
       
   726 	asm("blne subrectadd ");		// if non-null, add inter to aSubtractedRegion
       
   727 	asm("subrect2: ");
       
   728 	asm("cmp r3, r12 ");			// compare index to limit
       
   729 	asm("ldmltia r1, {r4-r7} ");	// if index<limit, r4-r7 = coordinates of aRect
       
   730 	asm("blt subrect1 ");			// if index<limit, loop again
       
   731 
       
   732 	asm("subrect_end: ");
       
   733 	__POPRET("r3-r11,");
       
   734 
       
   735 	// AppendRect(TRect(rect.iTl.iX,inter.iBr.iY,rect.iBr.iX,rect.iBr.iY))
       
   736 	asm("subrectapp1: ");
       
   737 	asm("stmfd sp!, {r0-r3,r12,lr} ");			// preserve registers across function call
       
   738 	asm("bl  " CSM_Z16AllocAnotherRectP7TRegion);
       
   739 	asm("ldmfd sp!, {r0-r3} ");
       
   740 	asm("beq subrectapp1_end ");		// exit if error
       
   741 
       
   742 	asm("ldr r12, [r0] ");				// r12=iCount
       
   743 	asm("ldr lr, [r0, #8] ");		// lr points to first rectangle
       
   744 	asm("cmn lr, lr ");
       
   745 	asm("ldrcc lr, [r0, #16] ");	// if RRegion
       
   746 	asm("addcs lr, r0, #20 ");		// RRegionBuf
       
   747 	asm("submi lr, lr, #8 ");		// TRegionFix
       
   748 	asm("add lr, lr, r12, lsl #4 ");	// lr=&(iRectangleList[iCount])
       
   749 	asm("add r12, r12, #1 ");			// increment iCount
       
   750 	asm("str r12, [r0] ");				//
       
   751 	asm("stmia lr!, {r8} ");			// append rectangle - rect.iTl.iX
       
   752 	asm("stmia lr!, {r7,r10,r11} ");	// inter.iBr.iY, rect.iBr.iX, rect.iBr.iY
       
   753 	asm("subrectapp1_end: ");
       
   754 	__POPRET("r12,");
       
   755 
       
   756 	// AppendRect(TRect(rect.iTl.iX,rect.iTl.iY,rect.iBr.iX,inter.iTl.iY))
       
   757 	asm("subrectapp2: ");
       
   758 	asm("stmfd sp!, {r0-r3,r12,lr} ");			// preserve registers across function call
       
   759 	asm("bl  " CSM_Z16AllocAnotherRectP7TRegion);
       
   760 	asm("ldmfd sp!, {r0-r3} ");
       
   761 	asm("beq subrectapp1_end ");		// exit if error
       
   762 
       
   763 	asm("ldr r12, [r0] ");				// r12=iCount
       
   764 	asm("ldr lr, [r0, #8] ");		// lr points to first rectangle
       
   765 	asm("cmn lr, lr ");
       
   766 	asm("ldrcc lr, [r0, #16] ");	// if RRegion
       
   767 	asm("addcs lr, r0, #20 ");		// RRegionBuf
       
   768 	asm("submi lr, lr, #8 ");		// TRegionFix
       
   769 	asm("add lr, lr, r12, lsl #4 ");	// lr=&(iRectangleList[iCount])
       
   770 	asm("add r12, r12, #1 ");			// increment iCount
       
   771 	asm("str r12, [r0] ");				//
       
   772 	asm("stmia lr!, {r8,r9,r10} ");		// append rectangle - rect.iTl.iX,rect.iTl.iY,rect.iBr.iX
       
   773 	asm("stmia lr!, {r5} ");			// inter.iTl.iY
       
   774 	__POPRET("r12,");
       
   775 
       
   776 	// AppendRect(TRect(inter.iBr.iX,inter.iTl.iY,rect.iBr.iX,inter.iBr.iY))
       
   777 	asm("subrectapp3: ");
       
   778 	asm("stmfd sp!, {r0-r3,r12,lr} ");			// preserve registers across function call
       
   779 	asm("bl  " CSM_Z16AllocAnotherRectP7TRegion);
       
   780 	asm("ldmfd sp!, {r0-r3} ");
       
   781 	asm("beq subrectapp1_end ");		// exit if error
       
   782 	asm("ldr r12, [r0] ");				// r12=iCount
       
   783 	asm("ldr lr, [r0, #8] ");		// lr points to first rectangle
       
   784 	asm("cmn lr, lr ");
       
   785 	asm("ldrcc lr, [r0, #16] ");	// if RRegion
       
   786 	asm("addcs lr, r0, #20 ");		// RRegionBuf
       
   787 	asm("submi lr, lr, #8 ");		// TRegionFix
       
   788 	asm("add lr, lr, r12, lsl #4 ");	// lr=&(iRectangleList[iCount])
       
   789 	asm("add r12, r12, #1 ");			// increment iCount
       
   790 	asm("str r12, [r0] ");				//
       
   791 	asm("stmia lr!, {r6} ");			// append rectangle - inter.iBr.iX
       
   792 	asm("stmia lr!, {r5,r10} ");		// inter.iTl.iY, rect.iBr.iX
       
   793 	asm("stmia lr!, {r7} ");			// inter.iBr.iY
       
   794 	__POPRET("r12,");
       
   795 
       
   796 	// AppendRect(TRect(rect.iTl.iX,inter.iTl.iY,inter.iTl.iX,inter.iBr.iY))
       
   797 	asm("subrectapp4: ");
       
   798 	asm("stmfd sp!, {r0-r3,r12,lr} ");			// preserve registers across function call
       
   799 	asm("bl  " CSM_Z16AllocAnotherRectP7TRegion);
       
   800 	asm("ldmfd sp!, {r0-r3} ");
       
   801 	asm("beq subrectapp1_end ");		// exit if error
       
   802 	asm("ldr r12, [r0] ");				// r12=iCount
       
   803 	asm("ldr lr, [r0, #8] ");		// lr points to first rectangle
       
   804 	asm("cmn lr, lr ");
       
   805 	asm("ldrcc lr, [r0, #16] ");	// if RRegion
       
   806 	asm("addcs lr, r0, #20 ");		// RRegionBuf
       
   807 	asm("submi lr, lr, #8 ");		// TRegionFix
       
   808 	asm("add lr, lr, r12, lsl #4 ");	// lr=&(iRectangleList[iCount])
       
   809 	asm("add r12, r12, #1 ");			// increment iCount
       
   810 	asm("str r12, [r0] ");				//
       
   811 	asm("stmia lr!, {r8} ");			// append rectangle - rect.iTl.iX
       
   812 	asm("stmia lr!, {r5} ");			// inter.iTl.iY
       
   813 	asm("stmia lr!, {r4,r7} ");			// inter.iTl.iX, inter.iBr.iY
       
   814 	__POPRET("r12,");
       
   815 
       
   816 	// aSubtractedRegion->AddRect(inter)
       
   817 	asm("subrectadd: ");
       
   818 	asm("stmfd sp!, {r0-r7,r12,lr} ");	// preserve registers and put inter onto stack
       
   819 	asm("mov r0, r2 ");					// this = aSubtractedRegion
       
   820 	asm("add r1, sp, #16 ");			// inter is 16 bytes above sp
       
   821 	asm("bl  " CSM_ZN7TRegion7AddRectERK5TRect);	// call TRegion::AddRect
       
   822 	__POPRET("r0-r7,r12,");
       
   823 	}
       
   824 
       
   825 
       
   826 
       
   827 
       
   828 __NAKED__ EXPORT_C void TRegion::Intersection(const TRegion& /*aRegion1*/,const TRegion& /*aRegion2*/)
       
   829 /**
       
   830 Replaces this region with the area of intersection between two specified regions.
       
   831 	
       
   832 Notes:
       
   833 	
       
   834 1. If the error flag of either of the two specified regions is set, then this 
       
   835    region is cleared and its error flag is set. This frees up allocated memory.
       
   836 	
       
   837 2. If this region's error flag is already set, then the function has no effect.
       
   838 	
       
   839 @param aRegion1 The first region. 
       
   840 @param aRegion2 The second region.
       
   841 */
       
   842 	{
       
   843 	// r0=this, r1=&aRegion1, r2=&aRegion2
       
   844 	asm("ldr r3, [r1, #4] ");			// r3=aRegion1.iError
       
   845 	asm("ldr r12, [r2, #4] ");			// r12=aRegion2.iError
       
   846 	asm("orrs r3, r3, r12 ");
       
   847 	asm("bne  " CSM_ZN7TRegion10ForceErrorEv);	// if either set, ForceError()
       
   848 	asm("str r3, [r0] ");				// iCount=0
       
   849 	asm("ldr r3, [r1] ");				// r3=aRegion1.iCount
       
   850 	asm("ldr r12, [r2] ");				// r12=aRegion2.iCount
       
   851 	asm("cmp r3, #0 ");
       
   852 	asm("cmpne r12, #0 ");
       
   853 	__JUMP(eq,lr);
       
   854 	asm("stmfd sp!, {r3-r11,lr} ");
       
   855 	asm("ldr lr, [r1, #8] ");			// r1 points to first rectangle of aRegion1 = pRect1
       
   856 	asm("cmn lr, lr ");
       
   857 	asm("ldrcc r1, [r1, #16] ");		// if RRegion
       
   858 	asm("addcs r1, r1, #20 ");			// RRegionBuf
       
   859 	asm("submi r1, r1, #8 ");			// TRegionFix
       
   860 	asm("intersection1: ");
       
   861 	asm("ldr lr, [r2, #8] ");			// lr points to first rectangle of aRegion2
       
   862 	asm("cmn lr, lr ");
       
   863 	asm("ldrcc lr, [r2, #16] ");		// if RRegion
       
   864 	asm("addcs lr, r2, #20 ");			// RRegionBuf
       
   865 	asm("submi lr, lr, #8 ");			// TRegionFix
       
   866 	asm("ldr r12, [r2] ");				// r12=aRegion2.iCount
       
   867 	asm("intersection2: ");
       
   868 	asm("ldmia r1, {r4-r7} ");			// r4-r7 = *pRect1
       
   869 	asm("ldmia lr!, {r8-r11} ");		// r8-r11 = *pRect2++
       
   870 	asm("cmp r6, r8 ");					// compare pRect1->iBr.iX with pRect2->iTl.iX
       
   871 	asm("cmpgt r7, r9 ");				// if >, compare pRect1->iBr.iY with pRect2->iTl.iY
       
   872 	asm("cmpgt r10, r4 ");				// if >, compare pRect2->iBr.iX with pRect1->iTl.iX
       
   873 	asm("cmpgt r11, r5 ");				// if >, compare pRect2->iBr.iY with pRect1->iTl.iY
       
   874 	asm("ble intersection3 ");			// if <=, rectangles have empty intersection, so iterate
       
   875 	asm("cmp r4, r8 ");					// compute intersection and place in r8-r11
       
   876 	asm("movgt r8, r4 ");
       
   877 	asm("cmp r5, r9 ");
       
   878 	asm("movgt r9, r5 ");
       
   879 	asm("cmp r6, r10 ");
       
   880 	asm("movlt r10, r6 ");
       
   881 	asm("cmp r7, r11 ");
       
   882 	asm("movlt r11, r7 ");
       
   883 	asm("stmfd sp!, {r0-r3,r12,lr} ");	// preserve registers across function call
       
   884 	asm("bl  " CSM_Z16AllocAnotherRectP7TRegion);
       
   885 	asm("ldmfd sp!, {r0-r3} ");
       
   886 	asm("ldmeqfd sp!, {r12,lr} ");		// exit if error
       
   887 	asm("beq intersection_end ");
       
   888 
       
   889 	asm("ldr r12, [r0] ");				// r12=iCount
       
   890 	asm("ldr lr, [r0, #8] ");			// lr points to first rectangle
       
   891 	asm("cmn lr, lr ");
       
   892 	asm("ldrcc lr, [r0, #16] ");		// if RRegion
       
   893 	asm("addcs lr, r0, #20 ");			// RRegionBuf
       
   894 	asm("submi lr, lr, #8 ");			// TRegionFix
       
   895 	asm("add lr, lr, r12, lsl #4 ");	// lr=&(iRectangleList[iCount])
       
   896 	asm("add r12, r12, #1 ");			// increment iCount
       
   897 	asm("str r12, [r0] ");				//
       
   898 	asm("stmia lr!, {r8-r11} ");		// append intersection of rectangles
       
   899 	asm("ldmfd sp!, {r12,lr} ");		// restore registers
       
   900 	asm("intersection3: ");
       
   901 	asm("subs r12, r12, #1 ");
       
   902 	asm("bne intersection2 ");			// loop for all values of pRect2
       
   903 	asm("add r1, r1, #16 ");			// increment pRect1
       
   904 	asm("subs r3, r3, #1 ");
       
   905 	asm("bne intersection1 ");			// loop for all values of pRect1
       
   906 
       
   907 	asm("intersection_end: ");
       
   908 	__POPRET("r3-r11,");
       
   909 	}
       
   910 	
       
   911 #endif
       
   912 
       
   913 
       
   914 
       
   915 
       
   916 #ifdef __COBJECT_MACHINE_CODED__
       
   917 __NAKED__ EXPORT_C CObject *CObjectIx::At(TInt /*aHandle*/,TInt /*aUniqueID*/)
       
   918 /**
       
   919 Gets a pointer to the reference counting object with the specified handle
       
   920 number and matching unique ID.
       
   921 
       
   922 @param aHandle   The handle number of the reference counting object.
       
   923 @param aUniqueID The unique ID.
       
   924 
       
   925 @return A pointer to the reference counting object. If there is no matching 
       
   926         object, then this is NULL.
       
   927 */
       
   928 	{
       
   929 	// r0=this, r1=aHandle, r2=aUniqueID
       
   930 	asm("ldr r3, [r0, #%a0]" : : "i" _FOFF(CObjectIx,iHighWaterMark));	// r3=iHighWaterMark
       
   931 	asm("ldr r0, [r0, #%a0]" : : "i" _FOFF(CObjectIx,iObjects));	// r0=iObjects
       
   932 	asm("mov r12, r1, lsl #17 ");		// r12=r1<<17 = index(aHandle)<<17
       
   933 	asm("cmp r3, r12, lsr #17 ");		// compare iHighWaterMark with index(aHandle)
       
   934 	asm("movle r0, #0 ");				// if hwm<=index, return NULL
       
   935 	__JUMP(le,lr);
       
   936 	asm("add r0, r0, r12, lsr #14 ");	// r0=iObjects+index(Handle)=pS
       
   937 	asm("ldr r3, [r0] ");				// r3=pS->uniqueID:pS->instance
       
   938 	asm("mov r1, r1, lsl #2 ");			// r1=instance(Handle)<<18
       
   939 	asm("mov r1, r1, lsr #18 ");		// r1=instance(Handle)
       
   940 	asm("orr r1, r1, r2, lsl #16 ");	// r1=aUniqueID:instance(Handle)
       
   941 	asm("cmp r1, r3 ");					// check uniqueID and instance
       
   942 	asm("movne r0, #0 ");				// if wrong, return 0
       
   943 	asm("ldreq r0, [r0, #4] ");			// else return pointer to CObject
       
   944 	__JUMP(,lr);
       
   945 	}
       
   946 
       
   947 
       
   948 
       
   949 
       
   950 __NAKED__ EXPORT_C CObject *CObjectIx::At(TInt aHandle)
       
   951 /**
       
   952 Gets a pointer to the reference counting object with the specified
       
   953 handle number.
       
   954 
       
   955 @param aHandle The handle number of the reference counting object.
       
   956 
       
   957 @return A pointer to the reference counting object. If there is no matching 
       
   958         object, then this is NULL.
       
   959 */
       
   960 	{
       
   961 	// r0=this, r1=aHandle
       
   962 	asm("ldr r3, [r0, #%a0]" : : "i" _FOFF(CObjectIx,iHighWaterMark));	// r3=iHighWaterMark
       
   963 	asm("ldr r0, [r0, #%a0]" : : "i" _FOFF(CObjectIx,iObjects));	// r0=iObjects
       
   964 	asm("mov r12, r1, lsl #17 ");		// r12=r1<<17 = index(aHandle)<<17
       
   965 	asm("cmp r3, r12, lsr #17 ");		// compare iHighWaterMark with index(aHandle)
       
   966 	asm("movle r0, #0 ");				// if hwm<=index, return NULL
       
   967 	__JUMP(le,lr);
       
   968 	asm("add r0, r0, r12, lsr #14 ");	// r0=iObjects+index(Handle)=pS
       
   969 	asm("ldr r3, [r0] ");				// r3=pS->uniqueID:pS->instance
       
   970 	asm("ldr r2, __instanceMask ");
       
   971 	asm("and r1, r1, r2 ");				// r1=instance(Handle)<<16
       
   972 	asm("cmp r1, r3, lsl #16 ");		// check instance
       
   973 	asm("movne r0, #0 ");				// if wrong, return 0
       
   974 	asm("ldreq r0, [r0, #4] ");			// else return pointer to CObject
       
   975 	__JUMP(,lr);
       
   976 	asm("__instanceMask: ");
       
   977 	asm(".word 0x3FFF0000 ");
       
   978 	}
       
   979 
       
   980 
       
   981 
       
   982 
       
   983 GLREF_C void PanicCObjectIxIndexOutOfRange(void);
       
   984 
       
   985 
       
   986 
       
   987 
       
   988 __NAKED__ EXPORT_C CObject* CObjectIx::operator[](TInt /*anIndex*/)
       
   989 /**
       
   990 Gets a pointer to a reference counting object located at the specified offset 
       
   991 within the object index.
       
   992 
       
   993 @param anIndex The offset of the reference counting object within the object 
       
   994                index. Offset is relative to zero. 
       
   995                
       
   996 @return A pointer to the reference counting object.
       
   997 
       
   998 @panic E32USER-CBase 21 if the value of anIndex is negative or is greater than
       
   999                         or equal to the total number of objects held by
       
  1000                         the index.
       
  1001 */
       
  1002 	{
       
  1003 	// r0=this, r1=anIndex
       
  1004 	asm("cmp r1, #0 ");								// check anIndex>=0
       
  1005 	asm("ldrge r3, [r0, #%a0]" : : "i" _FOFF(CObjectIx,iHighWaterMark));	// if so, r3=iHighWaterMark
       
  1006 	asm("cmpge r3, r1 ");							// and compare iHighWaterMark to anIndex
       
  1007 	asm("ldrgt r0, [r0, #%a0]" : : "i" _FOFF(CObjectIx,iObjects));	// if OK, r0=iObjects
       
  1008 	asm("addgt r0, r0, r1, lsl #3 ");				// r0=iObjects+anIndex
       
  1009 	asm("ldrgt r0, [r0, #4] ");						// r0=pointer to CObject
       
  1010 #ifdef __CPU_ARMV6
       
  1011 	asm("ble 1f ");
       
  1012 	__JUMP(,lr);
       
  1013 #else
       
  1014 	__JUMP(gt,lr);
       
  1015 #endif
       
  1016 	asm("1: ");
       
  1017 	asm("b  " CSM_Z29PanicCObjectIxIndexOutOfRangev);	// if anIndex<0 or iCount<=anIndex, panic
       
  1018 	}
       
  1019 
       
  1020 
       
  1021 
       
  1022 
       
  1023 GLREF_C void PanicCObjectConIndexOutOfRange(void);
       
  1024 GLREF_C void PanicCObjectConFindBadHandle(void);
       
  1025 GLREF_C void PanicCObjectConFindIndexOutOfRange(void);
       
  1026 
       
  1027 
       
  1028 
       
  1029 
       
  1030 __NAKED__ EXPORT_C CObject *CObjectCon::operator[](TInt /*anIndex*/)
       
  1031 /**
       
  1032 Gets a pointer to the reference counting object located at the specified offset 
       
  1033 within the object container.
       
  1034 
       
  1035 @param anIndex The offset of the reference counting object within the object 
       
  1036                container. Offset is relative to zero.
       
  1037 
       
  1038 @return A pointer to the owning reference counting object.
       
  1039 
       
  1040 @panic E32USER-CBase 21 if anIndex is negative or is greater than or equal to
       
  1041                         the total number of objects held by the container.
       
  1042 */
       
  1043 	{
       
  1044 	// r0=this, r1=anIndex
       
  1045 	asm("cmp r1, #0 ");
       
  1046 	asm("ldrge r2, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iCount));
       
  1047 	asm("cmpge r2, r1 ");
       
  1048 	asm("ldrgt r0, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iObjects));
       
  1049 	asm("ldrgt r0, [r0, r1, lsl #2] ");
       
  1050 #ifdef __CPU_ARMV6
       
  1051 	asm("ble 1f ");
       
  1052 	__JUMP(,lr);
       
  1053 #else
       
  1054 	__JUMP(gt,lr);
       
  1055 #endif
       
  1056 	asm("1: ");
       
  1057 	asm("b  " CSM_Z30PanicCObjectConIndexOutOfRangev);
       
  1058 	}
       
  1059 
       
  1060 
       
  1061 
       
  1062 
       
  1063 __NAKED__ EXPORT_C CObject *CObjectCon::At(TInt /*aFindHandle*/) const
       
  1064 /**
       
  1065 Gets a pointer to the reference counting object with the specified find-handle 
       
  1066 number.
       
  1067 
       
  1068 A find-handle number is an integer which uniquely identifies a reference
       
  1069 counting object with respect to its object container.
       
  1070 
       
  1071 @param aFindHandle The find-handle number of the reference counting object. 
       
  1072                    The unique Id part of this number must be the same as the
       
  1073                    unique Id of this container.
       
  1074                    The index part of the find-handle number must be
       
  1075                    a valid index. 
       
  1076 
       
  1077 @return A pointer to the reference counting object.
       
  1078 
       
  1079 @panic E32User-CBase 38 if the unique Id part of aFindHandle is not the same as
       
  1080                         the unique Id of this container.
       
  1081 @panic E32User-CBase 39 if the index part of aFindHandle is negative or greater
       
  1082                         than or equal to the total number of reference counting
       
  1083                         objects held by this object container.
       
  1084 */
       
  1085 	{
       
  1086 	// r0=this, r1=aFindHandle
       
  1087 	asm("ldr r2, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iUniqueID));
       
  1088 	asm("cmp r2, r1, lsr #16 ");
       
  1089 	asm("ldreq r2, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iCount));
       
  1090 	asm("bne  " CSM_Z28PanicCObjectConFindBadHandlev);
       
  1091 	asm("mov r1, r1, lsl #17 ");
       
  1092 	asm("cmp r2, r1, lsr #17 ");
       
  1093 	asm("ldrgt r0, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iObjects));
       
  1094 	asm("ble  " CSM_Z34PanicCObjectConFindIndexOutOfRangev);
       
  1095 	asm("ldr r0, [r0, r1, lsr #15] ");
       
  1096 	__JUMP(,lr);
       
  1097 	}
       
  1098 
       
  1099 
       
  1100 
       
  1101 
       
  1102 __NAKED__ EXPORT_C CObject *CObjectCon::AtL(TInt /*aFindHandle*/) const
       
  1103 /**
       
  1104 Gets a pointer to the reference counting object with the specified find-handle 
       
  1105 number, and leaves on error.
       
  1106 
       
  1107 A find-handle number is an integer which uniquely identifies a reference
       
  1108 counting object with respect to its object container.
       
  1109 
       
  1110 @param aFindHandle The find-handle number of the reference counting object. 
       
  1111                    The unique Id part of this number must be the same as
       
  1112                    the unique Id of this container.
       
  1113                    The index part of the find-handle number must be
       
  1114                    a valid index. 
       
  1115 
       
  1116 @return A pointer to the reference counting object.
       
  1117 
       
  1118 @leave KErrBadHandle if the unique Id part of aFindHandle is not the same as
       
  1119                      the unique Id of this container.
       
  1120 @leave KErrArgument if the index part of aFindHandle is negative or greater
       
  1121                     than or equal to the total number of reference counting
       
  1122                     objects held by this object container.
       
  1123 */
       
  1124 	{
       
  1125 	// r0=this, r1=aFindHandle
       
  1126 	asm("ldr r2, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iUniqueID));
       
  1127 	asm("cmp r2, r1, lsr #16 ");
       
  1128 	asm("ldreq r2, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iCount));
       
  1129 	asm("bne 1f ");
       
  1130 	asm("mov r1, r1, lsl #17 ");
       
  1131 	asm("cmp r2, r1, lsr #17 ");
       
  1132 	asm("ldrgt r0, [r0, #%a0]" : : "i" _FOFF(CObjectCon,iObjects));
       
  1133 	asm("ble 2f ");
       
  1134 	asm("ldr r0, [r0, r1, lsr #15] ");
       
  1135 	__JUMP(,lr);
       
  1136 	// User::Leave tail called, so no annotations required since
       
  1137 	// current frame is reused by User::Leave
       
  1138 	asm("1: ");
       
  1139 	asm("mvn r0, #7 "); // KErrBadHandle
       
  1140 	asm("b  " CSM_ZN4User5LeaveEi);
       
  1141 	asm("2: ");
       
  1142 	asm("mvn r0, #5 "); // KErrArgument
       
  1143 	asm("b  " CSM_ZN4User5LeaveEi);
       
  1144 	}
       
  1145 #endif
       
  1146 
       
  1147 #ifdef __CACTIVESCHEDULER_MACHINE_CODED__
       
  1148 extern "C" void PanicStrayEvent();
       
  1149 
       
  1150 /**
       
  1151 @internalComponent
       
  1152 
       
  1153 The inner active scheduler loop. This repeatedly waits for a signal and then
       
  1154 dispatches the highest priority ready active object. The loop terminates either
       
  1155 if one of the RunL()s stops the current active scheduler level or leaves.
       
  1156 
       
  1157 Stop when aLoop becomes 'Inactive'
       
  1158 */
       
  1159 __NAKED__ void CActiveScheduler::DoRunL(TLoopOwner* const volatile& aLoop, CActive* volatile & aCurrentObj, TCleanupBundle* aCleanupBundlePtr)
       
  1160 	{
       
  1161 	asm("stmfd sp!, {r4-r8,lr} ");
       
  1162 	__EH_FRAME_PUSH2(r4-r8,lr)
       
  1163 	
       
  1164 #ifdef _DEBUG
       
  1165 	// need to copy aCleanupBundlePtr to somewhere else before it's clobbered by the next line.
       
  1166 	asm("mov r8, r3 ");														// r8 = &aCleanupBundlePtr
       
  1167 #endif
       
  1168 	
       
  1169 	asm("ldr r3, [r0, #%a0]" : : "i" (_CBASE_VPTR_OFFSET_));				// r3 = vptr
       
  1170 	asm("add r4, r0, #%a0" : : "i" _FOFF(CActiveScheduler,iActiveQ));		// r4 = &iActiveQ
       
  1171 	asm("mov r5, r1 ");														// r5 = &aLoop
       
  1172 	asm("mov r7, r2 ");														// r7 = &aCurrentObj
       
  1173 	asm("ldr r6, [r3, #%a0]" : : "i" (_CACTIVESCHEDULER_WAIT_OFFSET_));		// r6 = &WaitForAnyRequest()
       
  1174 
       
  1175 	asm("active_scheduler_loop: ");
       
  1176 	asm("ldr r1, [r5] ");													// r1 = aLoop
       
  1177 	asm("adr lr, 1f ");														// return address
       
  1178 	asm("sub r0, r4, #%a0 " : : "i" _FOFF(CActiveScheduler,iActiveQ));		// this
       
  1179 	asm("cmp r1, #0 ");
       
  1180 	__JUMP(ne, r6);															// call WaitForAnyRequest() if still active
       
  1181 	__POPRET("r4-r8,");														// else return
       
  1182 
       
  1183 	// get here when WaitForAnyRequest() returns
       
  1184 	asm("1: ");
       
  1185 	asm("ldr r14, [r4, #0] ");												// r14->first active object
       
  1186 
       
  1187 	asm("2: ");
       
  1188 	asm("cmp r14, r4 ");													// end of queue?
       
  1189 	asm("sub r0, r14, #%a0" : : "i" _FOFF(CActive,iLink));					// r0->CActive
       
  1190 	asm("ldmneda r14, {r2, r12, r14} ");									// r2=iStatus, r12=iStatus.iFlags (old iActive), r14 = next object
       
  1191 	asm("beq PanicStrayEvent ");											// if end of queue, panic
       
  1192 #ifdef _DEBUG
       
  1193 	asm("ands r3, r12, #%a0" : : "i" ((TInt)(TRequestStatus::EActive|TRequestStatus::ERequestPending)));	// only active bit and request-pending bit
       
  1194 	asm("cmpne r3, #%a0" : : "i" ((TInt)(TRequestStatus::EActive|TRequestStatus::ERequestPending)));		// active bit == request pending bit
       
  1195 	asm("bne PanicStrayEvent ");											// if active bit != request pending bit, panic
       
  1196 #endif
       
  1197 	asm("cmp r2, #%a0" : : "i" ((TInt)KRequestPending));					// test if iStatus!=KRequestPending
       
  1198 	asm("andnes r3, r12, #%a0" : : "i" ((TInt)TRequestStatus::EActive));	// if so, test iActive
       
  1199 	asm("beq 2b ");															// if not active or still pending, do next CActive
       
  1200 
       
  1201 	// have an active object to run
       
  1202 #ifdef __SMP__
       
  1203 	__DATA_MEMORY_BARRIER_Z__(r3);											// acquire semantics
       
  1204 #endif
       
  1205 	asm("ldr r3, [r0, #%a0]" : : "i" (_CBASE_VPTR_OFFSET_));				// r3=CActive->vptr
       
  1206 	asm("bic r12, r12, #%a0" : : "i" ((TInt)(TRequestStatus::EActive|TRequestStatus::ERequestPending)));
       
  1207 	asm("ldr r3, [r3, #%a0]" : : "i" (_CACTIVE_RUNL_OFFSET_));				// r3 = &CActive::RunL()
       
  1208 	asm("str r12, [r0, #%a0]" : : "i" (_FOFF(CActive,iStatus)+_FOFF(TRequestStatus,iFlags)));	// iActive=EFalse
       
  1209 	asm("str r0, [r7] ");													// save active object in aCurrentObj in case RunL leaves
       
  1210 #ifdef _DEBUG
       
  1211 	__JUMPL(3);															// call RunL() (and continue)
       
  1212 #else
       
  1213 	asm("adr lr, active_scheduler_loop ");								// set lr (return address) to label, active_scheduler_loop
       
  1214 	__JUMP(,r3);														// call RunL() (and loop)
       
  1215 #endif
       
  1216 	
       
  1217 	
       
  1218 #ifdef _DEBUG
       
  1219 	//check whether there's a cleanup stack installed:
       
  1220 
       
  1221 	asm("cmp r8, #0");															// check CleanupBundle* == NULL
       
  1222 	asm("beq active_scheduler_loop ");											// If r8 == NULL, branch to label, active_scheduler_loop
       
  1223 	asm("ldr r0, [r8, #%a0]" : : "i" _FOFF(TCleanupBundle,iCleanupPtr)); 		// r0 = CCleanup* (load the CCleanup*)
       
  1224 
       
  1225 	//there is a cleanupstack installed:
       
  1226 	asm("add r1, r8, #%a0" : : "i" _FOFF(TCleanupBundle,iDummyInt)); 			// r1 = iDummyInt* (load the TInt*)
       
  1227 	asm("adr lr, active_scheduler_loop ");										// set lr (return address) to label, active_scheduler_loop
       
  1228 	asm("b  " CSM_ZN8CCleanup5CheckEPv); 										// call CCleanup::Check(iDummyInt*)
       
  1229 #endif
       
  1230 	
       
  1231 	}
       
  1232 #endif
       
  1233 
       
  1234 
       
  1235 #ifdef __CSERVER_MACHINE_CODED__
       
  1236 __NAKED__ EXPORT_C void CServer2::RunL()
       
  1237 	{
       
  1238 	asm("ldr r2, [r0, #%a0]" : : "i" _FOFF(CServer2,iMessage.iFunction)); // r2=Message().Function()
       
  1239 	asm("stmfd sp!, {r4, lr}");			// save regs
       
  1240 	__EH_FRAME_PUSH2(r4,lr)
       
  1241 	asm("cmp r2, #0");					// check for Connect/Disconnect message
       
  1242 	asm("bmi server2_con_dis");
       
  1243 
       
  1244 	// Service the message
       
  1245 	asm("mov r4, r0 ");						// r4=this
       
  1246 	asm("ldr r0, [r4, #%a0]" : : "i" _FOFF(CServer2,iMessage.iSessionPtr)); // r0=session
       
  1247 	asm("add r1, r4, #%a0" : : "i" (_FOFF(CServer2,iMessage)));	// r1=&iServer.Message()
       
  1248 	asm("cmp r0, #0");  // Check for NULL session
       
  1249 	asm("ldrne r12, [r0, #%a0]" : : "i" (_CBASE_VPTR_OFFSET_));			// r12=CSession2::vptr
       
  1250 #ifdef __SUPPORT_THUMB_INTERWORKING
       
  1251 	asm("ldrne r3, [r12, #%a0]" : : "i" (_CSESSION2_SERVICEL_OFFSET_));	// call CSession2::ServiceL(iMessage)
       
  1252 	asm("adr lr, server2_run_postamble ");
       
  1253 	asm("bxne r3 ");
       
  1254 #else
       
  1255 	asm("adr lr, server2_run_postamble ");
       
  1256 	asm("ldrne pc, [r12, #%a0]" : : "i" (_CSESSION2_SERVICEL_OFFSET_));	// call CSession2::ServiceL(iMessage)
       
  1257 #endif
       
  1258 	asm("mov r0, r1");
       
  1259 	asm("b  " CSM_ZN8CServer212NotConnectedERK9RMessage2); // NULL session ptr means not connected
       
  1260 
       
  1261 	// Do this after processing any message
       
  1262 	asm("server2_run_postamble: ");
       
  1263 	asm("ldr r2, [r4, #%a0]" : : "i" (_FOFF(CServer2,iStatus)+_FOFF(TRequestStatus,iFlags)));	// r2=iStatus.iFlags (old iActive)
       
  1264 	asm("mov r0, #0x80000001 ");								// r0=KRequestPending
       
  1265 	asm("ands r1, r2, #%a0" : : "i" ((TInt)TRequestStatus::EActive));
       
  1266 	asm("bne server2_run_end ");							// if already active, finished
       
  1267 	asm("orr r2, r2, #%a0" : : "i" ((TInt)(TRequestStatus::EActive|TRequestStatus::ERequestPending)));
       
  1268 	asm("add r1, r4, #%a0" : : "i" _FOFF(CActive,iStatus));		// r1->iStatus
       
  1269 	asm("stmia r1, {r0,r2} "); // set iStatus=KRequestPending, set active bit, set request pending bit
       
  1270 	asm("add r2, r4, #%a0" : : "i" _FOFF(CServer2,iMessage));	// r2->iServer.Message()
       
  1271 	asm("ldr r0, [r4, #%a0]" : : "i" _FOFF(CServer2,iServer));	// r0=iServer.iHandle
       
  1272 	asm("bl  " CSM_ZN4Exec13ServerReceiveEiR14TRequestStatusPv);// call Exec::ServerReceive
       
  1273 	asm("server2_run_end: ");
       
  1274 	__POPRET("r4,");
       
  1275 
       
  1276 	// Deal with Connect and Disconnect messages
       
  1277 	asm("server2_con_dis:");	
       
  1278 	asm("mov r4, r0 ");					// r4=this
       
  1279 	asm("add r1, r0, #%a0" : : "i" _FOFF(CServer2,iMessage)); // r1=&iServer.Message()
       
  1280 	asm("adr lr, server2_run_postamble "); // return address for after any processing
       
  1281 	asm("cmp r2, #%a0" : : "i" (RMessage2::EConnect));
       
  1282 	asm("beq  " CSM_ZN8CServer27ConnectERK9RMessage2); // Do Connect()
       
  1283 	asm("cmp r2, #%a0" : : "i" (RMessage2::EDisConnect));
       
  1284 	asm("beq  " CSM_ZN8CServer210DisconnectERK9RMessage2); // Do Disconnect()
       
  1285 	asm("mov r0, r1");
       
  1286 	asm("b  " CSM_ZN8CServer210BadMessageERK9RMessage2); // Bad message
       
  1287 	}
       
  1288 #endif
       
  1289 
       
  1290 EXPORT_C __NAKED__ void RFastLock::Wait()
       
  1291 	{
       
  1292 	asm("1: ");
       
  1293 	asm("add	r0, r0, #4 ");					// point to iCount
       
  1294 
       
  1295 #ifdef __CPU_ARM_HAS_LDREX_STREX
       
  1296 	asm("2:		");
       
  1297 	LDREX(		2, 0);							// read
       
  1298 	asm("subs	r1, r2, #1 ");					// decrement
       
  1299 	STREX(		3, 1, 0);						// write
       
  1300 	asm("teq	r3, #0 ");						// success?
       
  1301 	asm("bne	2b ");							// no!
       
  1302 	asm("sub	r0, r0, #4 ");					// r0 = this
       
  1303 	asm("bcs "	CSM_ZN10RSemaphore4WaitEv);		// if no borrow from decrement wait on semaphore
       
  1304 #ifdef __SMP__
       
  1305 	__DATA_MEMORY_BARRIER__(r3);				// no need to wait, but still need acquire barrier
       
  1306 #endif
       
  1307 	__JUMP(,	lr );
       
  1308 #else
       
  1309 	asm("mov	r1, #1 ");						// 'looking' value
       
  1310 	asm("swp	r1, r1, [r0] ");				// write looking value, read original
       
  1311 	asm("subs	r1, r1, #1 ");					// decrement count
       
  1312 	asm("strlt	r1, [r0] ");					// if it becomes negative, no-one was looking
       
  1313 	__JUMP(cc,	lr);							// if borrow, was originally zero so we are finished
       
  1314 	asm("sub	r0, r0, #4 ");					// r0=this
       
  1315 	asm("blt "	CSM_ZN10RSemaphore4WaitEv);		// lock held so wait on semaphore
       
  1316 	asm("stmfd	sp!, {r0,lr} ");				// otherwise save registers
       
  1317 	asm("mov	r0, #1000 ");					// someone was looking, so wait 1ms and try again
       
  1318 	asm("bl "	CSM_ZN4User12AfterHighResE27TTimeIntervalMicroSeconds32);
       
  1319 	asm("ldmfd	sp!, {r0,lr} ");
       
  1320 	asm("b		1b ");
       
  1321 #endif
       
  1322 	}
       
  1323 
       
  1324 EXPORT_C __NAKED__ void RFastLock::Signal()
       
  1325 	{
       
  1326 	asm("1: ");
       
  1327 	asm("add	r0, r0, #4 ");					// point to iCount
       
  1328 
       
  1329 #ifdef __CPU_ARM_HAS_LDREX_STREX
       
  1330 #ifdef __SMP__
       
  1331 	__DATA_MEMORY_BARRIER_Z__(r3);				// need release barrier
       
  1332 #endif
       
  1333 	asm("2:		");
       
  1334 	LDREX(		2, 0);							// read
       
  1335 	asm("adds	r1, r2, #1 ");					// increment
       
  1336 	STREX(		3, 1, 0);						// write
       
  1337 	asm("teq	r3, #0 ");						// success?
       
  1338 	asm("bne	2b ");							// no!
       
  1339 	asm("sub	r0, r0, #4 ");					// r0 = this
       
  1340 	asm("bcc "	CSM_ZN10RSemaphore6SignalEv);	// if no carry from increment, signal semaphore
       
  1341 	__JUMP(,	lr );
       
  1342 #else
       
  1343 	asm("mov	r1, #1 ");						// 'looking' value
       
  1344 	asm("swp	r1, r1, [r0] ");				// write looking value, read original
       
  1345 	asm("adds	r1, r1, #1 ");					// increment count
       
  1346 	asm("strle	r1, [r0] ");					// if still <=0, no-one was looking
       
  1347 	__JUMP(eq,	lr);							// if it's now zero, no-one is waiting so we are finished
       
  1348 	asm("sub	r0, r0, #4 ");					// r0=this
       
  1349 	asm("blt "	CSM_ZN10RSemaphore6SignalEv);	// someone is waiting so signal semaphore
       
  1350 	asm("stmfd	sp!, {r0,lr} ");				// otherwise save registers
       
  1351 	asm("mov	r0, #1000 ");					// someone was looking, so wait 1ms and try again
       
  1352 	asm("bl "	CSM_ZN4User12AfterHighResE27TTimeIntervalMicroSeconds32);
       
  1353 	asm("ldmfd	sp!, {r0,lr} ");
       
  1354 	asm("b		1b ");
       
  1355 #endif
       
  1356 	}
       
  1357 
       
  1358 
       
  1359 // Entry point stub to allow EKA1 binaries to be executed under EKA2
       
  1360 // Only called when process is first loaded
       
  1361 
       
  1362 extern "C" TLinAddr GetEka1ExeEntryPoint();
       
  1363 
       
  1364 __NAKED__ TInt E32Loader::V7ExeEntryStub()
       
  1365 	{
       
  1366 	// Process entry point
       
  1367 	// R4 = entry reason
       
  1368 	// SP points to information block
       
  1369 	asm("cmp r4, #%a0" : : "i" ((TInt)KModuleEntryReasonProcessInit) );
       
  1370 	asm("bne " CSM_ZN4User9InvariantEv );	// invalid entry reason
       
  1371 	asm("bl GetEka1ExeEntryPoint ");		// load the entry stub and return its address
       
  1372 	__JUMP(,r0);							// jump to the entry stub with R4, SP unchanged
       
  1373 	}
       
  1374 
       
  1375 __NAKED__ TInt E32Loader::V7DllEntryStub(TInt)
       
  1376 	{
       
  1377 
       
  1378 	__JUMP(,lr);
       
  1379 	}
       
  1380 
       
  1381 
       
  1382 // Hash an 8 bit string at aPtr, length aLen bytes.
       
  1383 __NAKED__ TUint32 DefaultStringHash(const TUint8* /*aPtr*/, TInt /*aLen*/)
       
  1384 	{
       
  1385 	asm("ldr r3, one_over_phi ");
       
  1386 	asm("subs r1, r1, #4 ");
       
  1387 	asm("mov r2, r0 ");
       
  1388 	asm("mov r0, #0 ");
       
  1389 	asm("blo 1f ");
       
  1390 	asm("ands r12, r2, #3 ");
       
  1391 	asm("bne hash_unal ");
       
  1392 	asm("2: ");
       
  1393 	asm("ldr r12, [r2], #4 ");
       
  1394 	asm("subs r1, r1, #4 ");
       
  1395 	asm("eor r0, r0, r12 ");
       
  1396 	asm("umull r0, r12, r3, r0 ");
       
  1397 	asm("bcs 2b ");
       
  1398 	asm("1: ");
       
  1399 	asm("adds r1, r1, #4 ");
       
  1400 	__JUMP(eq,lr);
       
  1401 	asm("4: ");
       
  1402 	asm("ldrb r12, [r2], #1 ");
       
  1403 	asm("cmp r1, #2 ");
       
  1404 	asm("eor r0, r0, r12 ");
       
  1405 	asm("ldrcsb r12, [r2], #1 ");
       
  1406 	asm("eorcs r0, r0, r12, lsl #8 ");
       
  1407 	asm("ldrhib r12, [r2], #1 ");
       
  1408 	asm("eorhi r0, r0, r12, lsl #16 ");
       
  1409 	asm("umull r0, r12, r3, r0 ");
       
  1410 	__JUMP(,lr);
       
  1411 
       
  1412 	asm("hash_unal: ");
       
  1413 	asm("bic r2, r2, #3 ");
       
  1414 	asm("stmfd sp!, {r4,r5,lr} ");
       
  1415 	asm("mov r12, r12, lsl #3 ");
       
  1416 	asm("rsb r14, r12, #32 ");
       
  1417 	asm("ldr r4, [r2], #4 ");
       
  1418 	asm("3: ");
       
  1419 	asm("eor r0, r0, r4, lsr r12 ");
       
  1420 	asm("ldr r4, [r2], #4 ");
       
  1421 	asm("subs r1, r1, #4 ");
       
  1422 	asm("eor r0, r0, r4, lsl r14 ");
       
  1423 	asm("umull r0, r5, r3, r0 ");
       
  1424 	asm("bcs 3b ");
       
  1425 	asm("adds r1, r1, #4 ");
       
  1426 	asm("ldmfd sp!, {r4,r5,lr} ");
       
  1427 	asm("subne r2, r2, #4 ");
       
  1428 	asm("addne r2, r2, r12, lsr #3 ");
       
  1429 	asm("bne 4b ");
       
  1430 	__JUMP(,lr);
       
  1431 	}
       
  1432 
       
  1433 // Hash a 16 bit string at aPtr, length aLen bytes.
       
  1434 __NAKED__ TUint32 DefaultWStringHash(const TUint16* /*aPtr*/, TInt /*aLen*/)
       
  1435 	{
       
  1436 	asm("str lr, [sp, #-4]! ");
       
  1437 	asm("ldr r3, one_over_phi ");
       
  1438 	asm("subs r1, r1, #8 ");
       
  1439 	asm("mov r2, r0 ");
       
  1440 	asm("mov r0, #0 ");
       
  1441 	asm("blo 1f ");
       
  1442 	asm("ands r12, r2, #3 ");
       
  1443 	asm("bne whash_unal ");
       
  1444 	asm("2: ");
       
  1445 	asm("ldmia r2!, {r12,r14} ");
       
  1446 	asm("subs r1, r1, #8 ");
       
  1447 	asm("eor r0, r0, r12 ");
       
  1448 	asm("eor r0, r0, r14, ror #24 ");
       
  1449 	asm("umull r0, r12, r3, r0 ");
       
  1450 	asm("bcs 2b ");
       
  1451 	asm("1: ");
       
  1452 	asm("adds r1, r1, #8 ");
       
  1453 	asm("beq 8f ");
       
  1454 	asm("4: ");
       
  1455 	asm("ldrh r12, [r2], #2 ");
       
  1456 	asm("cmp r1, #4 ");
       
  1457 	asm("eor r0, r0, r12 ");
       
  1458 	asm("ldrcsh r12, [r2], #2 ");
       
  1459 	asm("eorcs r0, r0, r12, lsl #16 ");
       
  1460 	asm("ldrhih r12, [r2], #2 ");
       
  1461 	asm("eorhi r0, r0, r12, ror #24 ");
       
  1462 	asm("umull r0, r12, r3, r0 ");
       
  1463 	asm("8: ");
       
  1464 	__POPRET("");
       
  1465 
       
  1466 	asm("whash_unal: ");
       
  1467 	asm("add r2, r2, #2 ");				// r2 must be 2 mod 4
       
  1468 	asm("ldr r14, [r2, #-4] ");
       
  1469 	asm("3: ");
       
  1470 	asm("eor r0, r0, r14, lsr #16 ");	// char 0 goes into bytes 0,1
       
  1471 	asm("ldmia r2!, {r12,r14} ");
       
  1472 	asm("subs r1, r1, #8 ");
       
  1473 	asm("eor r0, r0, r12, lsl #16 ");	// char 1 goes into bytes 2,3
       
  1474 	asm("mov r12, r12, lsr #16 ");
       
  1475 	asm("orr r12, r12, r14, lsl #16 ");	// r12 = char3:char2
       
  1476 	asm("eor r0, r0, r12, ror #24 ");	// char 2 into bytes 1,2 ; char 3 into bytes 3,0
       
  1477 	asm("umull r0, r12, r3, r0 ");
       
  1478 	asm("bcs 3b ");
       
  1479 	asm("adds r1, r1, #8 ");
       
  1480 	asm("subne r2, r2, #2 ");
       
  1481 	asm("bne 4b ");
       
  1482 	__POPRET("");
       
  1483 	}
       
  1484 
       
  1485 
       
  1486 /**
       
  1487 @publishedAll
       
  1488 @released
       
  1489 
       
  1490 Calculate a 32 bit hash from a 32 bit integer.
       
  1491 
       
  1492 @param	aInt	The integer to be hashed.
       
  1493 @return			The calculated 32 bit hash value.
       
  1494 */
       
  1495 EXPORT_C __NAKED__ TUint32 DefaultHash::Integer(const TInt& /*aInt*/)
       
  1496 	{
       
  1497 	asm("ldr r0, [r0] ");
       
  1498 	asm("ldr r1, one_over_phi ");
       
  1499 	asm("umull r0, r2, r1, r0 ");
       
  1500 	__JUMP(,lr);
       
  1501 	asm("one_over_phi: ");
       
  1502 	asm(".word 0x9e3779b9 ");
       
  1503 	}
       
  1504 
       
  1505 
       
  1506 #ifdef __USERSIDE_THREAD_DATA__
       
  1507 
       
  1508 /**
       
  1509 @internalComponent
       
  1510 
       
  1511 Get a pointer to the thread local user data stored in the thread ID register.
       
  1512 */
       
  1513 __NAKED__ TLocalThreadData* LocalThreadData()
       
  1514 	{
       
  1515 	GET_RWRW_TID(,r0);
       
  1516 	__JUMP(,lr);	
       
  1517 	}
       
  1518 
       
  1519 #endif