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