os/kernelhwsrv/kernel/eka/klib/arm/cbma.cia
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1998-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\klib\arm\cbma.cia
    15 // Machine coded bitmap allocator for ARM
    16 // This file is directly included in the test harness t_tbma
    17 // 
    18 //
    19 
    20 #include <kernel/kbma.h>
    21 #include <cpudefs.h>
    22 #include <e32cia.h>
    23 
    24 #ifdef TBMA_TEST_CODE
    25 
    26 #include <e32atomics.h>
    27 
    28 #ifdef __MARM__
    29 #define __TBMA_MACHINE_CODED__
    30 #endif
    31 
    32 #else
    33 
    34 #include <kernel/kern_priv.h>
    35 
    36 #endif
    37 
    38 #ifdef __TBMA_MACHINE_CODED__
    39 
    40 extern void TBmaFault(TInt aLine);
    41 #define	ASM_FAULT_LINE(x)	asm("ldr r0, [pc] "); asm("b " CSM_Z9TBmaFaulti ); asm(".word %a0" : : "i" (x));
    42 #define	ASM_FAULT()		ASM_FAULT_LINE(__LINE__)
    43 
    44 #ifndef __EABI_CTORS__
    45 /**	Construct a new TBitMapAllocator object
    46 
    47 	@param	aSize The number of bit positions required
    48 	@param	aState	TRUE if all bit positions initially free
    49 					FALSE if all bit positions initially allocated
    50  */
    51 EXPORT_C __NAKED__ TBitMapAllocator::TBitMapAllocator(TInt /*aSize*/, TBool /*aState*/)
    52 	{
    53 	asm("cmp r1, #0 ");
    54 	asm("ble 0f ");
    55 	asm("cmp r2, #0 ");
    56 	asm("movne r2, r1 ");				// if aState r2=aSize else r2=0
    57 	asm("str r2, [r0, #0] ");			// iAvail=aState?aSize:0
    58 	asm("add r12, r0, #12 ");			// r12=&iMap[0]
    59 	asm("str r1, [r0, #8] ");			// iSize=r1
    60 	asm("add r3, r1, #31 ");
    61 	asm("bic r3, r3, #31 ");			// r3=aSize rounded up to multiple of 32
    62 	asm("sub r3, r3, #32 ");			// r3=32*(number of map words-1)
    63 	asm("addeq r12, r12, r3, lsr #3 ");	// if !aState r12=&iMap[nmapw-1]
    64 	asm("str r12, [r0, #4] ");			// iCheckFirst=aState?&iMap[0]:&iMap[nmapw-1]
    65 	asm("mvnne r2, #0 ");				// if aState r2=0xffffffff else r2=0
    66 	asm("add r12, r0, #12 ");			// r12=&iMap[0]
    67 	asm("1: ");
    68 	asm("str r2, [r12], #4 ");			// fill map
    69 	asm("subs r1, r1, #32 ");
    70 	asm("bhi 1b ");
    71 	asm("rsbne r1, r1, #0 ");			// if aSize not a multiple of 32, r1=number of tail bits to clear
    72 	asm("movne r2, r2, lsl r1 ");		// clear unused bits
    73 	asm("strne r2, [r12, #-4] ");
    74 	__JUMP(,lr);
    75 	asm("0: ");
    76 	ASM_FAULT();
    77 	}
    78 #endif
    79 
    80 
    81 /**	Allocate the next available bit position
    82 
    83 	@return	Number of position allocated, -1 if all positions occupied
    84  */
    85 EXPORT_C __NAKED__ TInt TBitMapAllocator::Alloc()
    86 	{
    87 	asm("ldmia r0, {r1,r2} ");			// r1=available, r2=check first address
    88 	asm("subs r1, r1, #1 ");			// decrement free count
    89 	asm("mvnmi r0, #0 ");				// if none free, return with r0=-1
    90 	__JUMP(mi,lr);
    91 	asm("str r1, [r0] ");				// store decremented free count
    92 	asm("alloc_1: ");
    93 	asm("ldr r3, [r2], #4 ");			// check word
    94 	asm("cmp r3, #0 ");					// any free entries?
    95 	asm("beq alloc_1 ");				// if not, check next word
    96 #ifdef __CPU_ARM_HAS_CLZ
    97 	CLZ(12, 3);
    98 #else
    99 	asm("mov ip, #0 ");
   100 	asm("cmp r3, #0x00010000 ");		// ip=number of leading zeros in r3
   101 	asm("movlo r3, r3, lsl #16 ");
   102 	asm("addlo ip, ip, #16 ");
   103 	asm("cmp r3, #0x01000000 ");
   104 	asm("movlo r3, r3, lsl #8 ");
   105 	asm("addlo ip, ip, #8 ");
   106 	asm("cmp r3, #0x10000000 ");
   107 	asm("movlo r3, r3, lsl #4 ");
   108 	asm("addlo ip, ip, #4 ");
   109 	asm("cmp r3, #0x40000000 ");
   110 	asm("movlo r3, r3, lsl #2 ");
   111 	asm("addlo ip, ip, #2 ");
   112 	asm("cmp r3, #0x80000000 ");
   113 	asm("addlo ip, ip, #1 ");
   114 #endif
   115 	asm("ldr r3, [r2, #-4]! ");
   116 	asm("mov r1, #0x80000000 ");
   117 	asm("bic r3, r3, r1, lsr ip ");		// clear bit in allocator word
   118 	asm("str r3, [r2] ");
   119 	asm("str r2, [r0, #4] ");			// update check first address
   120 	asm("sub r0, r2, r0 ");
   121 	asm("sub r0, r0, #12 ");			// r0=offset of word from iMap[0]
   122 	asm("adds r0, ip, r0, lsl #3 ");	// multiply by 8 and add bit position
   123 	__JUMP(,lr);
   124 	}
   125 
   126 
   127 /**	Free the specified bit position
   128 
   129 	@param	aPos Number of bit position to be freed; must be currently allocated.
   130  */
   131 EXPORT_C __NAKED__ void TBitMapAllocator::Free(TInt /*aPos*/)
   132 	{
   133 	asm("ldr r3, [r0, #8] ");			// r3=iSize
   134 	asm("mov r2, r1, lsr #5 ");			// r2=word index
   135 	asm("add r2, r0, r2, lsl #2 ");		// r2=address of word-12
   136 	asm("cmp r1, r3 ");
   137 	asm("bhs free_error ");
   138 	asm("and ip, r1, #0x1f ");			// ip=bit number in word
   139 	asm("ldr r3, [r2, #12]! ");			// r3=allocator word
   140 	asm("mov r1, #0x80000000 ");
   141 	asm("tst r3, r1, lsr ip ");			// test bit
   142 	asm("bne free_error ");				// if already free, error
   143 	asm("orr r3, r3, r1, lsr ip ");		// set free bit
   144 	asm("str r3, [r2] ");
   145 	asm("ldmia r0, {r1,r3} ");			// r1=available count, r3=first free address
   146 	asm("cmp r1, #1 ");					// check original free count
   147 	asm("add r1, r1, #1 ");				// increment available count
   148 	asm("str r1, [r0, #0] ");
   149 	asm("cmpcs r2, r3 ");				// compare word address with first free
   150 	asm("strcc r2, [r0, #4] ");			// if lower, update first free
   151 	__JUMP(,lr);
   152 
   153 	asm("free_error: ");
   154 	ASM_FAULT();
   155 	}
   156 
   157 
   158 /**	Allocate a specific range of bit positions
   159 	Specified range must lie within the total range for this allocator and all
   160 	the positions must currently be free.
   161 
   162 	@param	aStart	First position to allocate
   163 	@param	aLength	Number of consecutive positions to allocate, must be >0
   164  */
   165 EXPORT_C __NAKED__ void TBitMapAllocator::Alloc(TInt /*aStart*/, TInt /*aLength*/)
   166 	{
   167 	asm("ldr ip, [r0, #8] ");
   168 	asm("str lr, [sp, #-4]! ");
   169 	asm("adds lr, r1, r2 ");
   170 	asm("bcs 0f ");
   171 	asm("cmp lr, ip ");
   172 	asm("bhi 0f ");
   173 	asm("mov r3, r1, lsr #5 ");
   174 	asm("ldr ip, [r0] ");
   175 	asm("and r1, r1, #0x1f ");
   176 	asm("add r3, r0, r3, lsl #2 ");
   177 	asm("sub ip, ip, r2 ");				// reduce free count
   178 	asm("str ip, [r0] ");
   179 	asm("add ip, r2, r1 ");
   180 	asm("cmp ip, #32 ");
   181 	asm("bhi 1f ");
   182 	asm("mvn ip, #0 ");
   183 	asm("ldr r0, [r3, #12]! ");
   184 	asm("mvn ip, ip, lsr r2 ");
   185 	asm("mov ip, ip, lsr r1 ");
   186 	asm("orr lr, r0, ip ");
   187 	asm("cmp lr, r0 ");
   188 	asm("bne 0f ");
   189 	asm("bic r0, r0, ip ");
   190 	asm("str r0, [r3] ");
   191 	asm("ldr pc, [sp], #4 ");
   192 	asm("1: ");
   193 	asm("add r3, r3, #12 ");
   194 	asm("mvn r2, #0 ");
   195 	asm("mov r2, r2, lsr r1 ");
   196 	asm("2: ");
   197 	asm("ldr r1, [r3] ");
   198 	asm("orr lr, r1, r2 ");
   199 	asm("cmp lr, r1 ");
   200 	asm("bne 0f ");
   201 	asm("bic r1, r1, r2 ");
   202 	asm("str r1, [r3], #4 ");
   203 	asm("mvn r2, #0 ");
   204 	asm("subs ip, ip, #32 ");
   205 	asm("ldrls pc, [sp], #4 ");
   206 	asm("cmp ip, #32 ");
   207 	asm("mvncc r2, r2, lsr ip ");
   208 	asm("b 2b ");
   209 
   210 	asm("0: ");
   211 	ASM_FAULT();
   212 	}
   213 
   214 
   215 /**	Free a specific range of bit positions
   216 	Specified range must lie within the total range for this allocator and all
   217 	the positions must currently be allocated.
   218 
   219 	@param	aStart	First position to free
   220 	@param	aLength	Number of consecutive positions to free, must be >0
   221  */
   222 EXPORT_C __NAKED__ void TBitMapAllocator::Free(TInt /*aStart*/, TInt /*aLength*/)
   223 	{
   224 	asm("ldr ip, [r0, #8] ");
   225 	asm("str lr, [sp, #-4]! ");
   226 	asm("adds lr, r1, r2 ");
   227 	asm("bcs 0f ");
   228 	asm("cmp lr, ip ");
   229 	asm("bhi 0f ");
   230 	asm("mov r3, r1, lsr #5 ");
   231 	asm("and r1, r1, #0x1f ");
   232 	asm("add r3, r0, r3, lsl #2 ");
   233 	asm("ldmia r0, {ip,lr} ");			// ip=free count, lr=first check addr
   234 	asm("add r3, r3, #12 ");
   235 	asm("cmp ip, #1 ");					// check original free count
   236 	asm("add ip, ip, r2 ");				// increase free count
   237 	asm("cmpcs r3, lr ");				// if none free originally, always update address
   238 	asm("str ip, [r0] ");
   239 	asm("strcc r3, [r0, #4] ");			// update first check addr if necessary
   240 	asm("add lr, r2, r1 ");
   241 	asm("cmp lr, #32 ");
   242 	asm("bhi 1f ");
   243 	asm("mvn lr, #0 ");
   244 	asm("ldr r0, [r3] ");
   245 	asm("mvn lr, lr, lsr r2 ");
   246 	asm("mov lr, lr, lsr r1 ");
   247 	asm("tst r0, lr ");
   248 	asm("bne 0f ");
   249 	asm("orr r0, r0, lr ");
   250 	asm("str r0, [r3] ");
   251 	asm("ldr pc, [sp], #4 ");
   252 	asm("1: ");
   253 	asm("mvn r2, #0 ");
   254 	asm("mov r2, r2, lsr r1 ");
   255 	asm("2: ");
   256 	asm("ldr r1, [r3] ");
   257 	asm("tst r1, r2 ");
   258 	asm("bne 0f ");
   259 	asm("orr r1, r1, r2 ");
   260 	asm("str r1, [r3], #4 ");
   261 	asm("mvn r2, #0 ");
   262 	asm("subs lr, lr, #32 ");
   263 	asm("ldrls pc, [sp], #4 ");
   264 	asm("cmp lr, #32 ");
   265 	asm("mvncc r2, r2, lsr lr ");
   266 	asm("b 2b ");
   267 
   268 	asm("0: ");
   269 	ASM_FAULT();
   270 	}
   271 
   272 
   273 /**	Free a specific range of bit positions
   274 	Specified range must lie within the total range for this allocator but it is
   275 	not necessary that all the positions are currently allocated.
   276 
   277 	@param	aStart	First position to free
   278 	@param	aLength	Number of consecutive positions to free, must be >0
   279  */
   280 EXPORT_C __NAKED__ void TBitMapAllocator::SelectiveFree(TInt /*aStart*/, TInt /*aLength*/)
   281 	{
   282 	asm("ldr r3, [r0, #8] ");
   283 	asm("stmfd sp!, {r4-r8,lr} ");
   284 	asm("adds lr, r1, r2 ");
   285 	asm("bcs 0f ");
   286 	asm("cmp lr, r3 ");
   287 	asm("bhi 0f ");
   288 	asm("mov r7, r0 ");					// r7 -> this
   289 	asm("mov r4, r1, lsr #5 ");
   290 	asm("and r1, r1, #0x1f ");
   291 	asm("ldmia r7, {r6,r8} ");			// r6=free count, r8=first check addr
   292 	asm("add r4, r7, r4, lsl #2 ");
   293 	asm("add r4, r4, #12 ");
   294 	asm("cmp r6, #1 ");					// check original free count
   295 	asm("add r6, r6, r2 ");				// r6=new free count assuming no positions already free
   296 	asm("cmpcs r4, r8 ");				// if none free originally, always update address
   297 	asm("strcc r4, [r7, #4] ");			// update first check addr if necessary
   298 	asm("add r8, r2, r1 ");
   299 	asm("cmp r8, #32 ");
   300 	asm("bhi sfree_cross_bdry ");
   301 	asm("mvn r8, #0 ");
   302 	asm("mvn r8, r8, lsr r2 ");
   303 	asm("mov r8, r8, lsr r1 ");
   304 	asm("ldr r1, [r4] ");
   305 	asm("ands r0, r1, r8 ");			// r0 has 1's in positions which are already free
   306 	asm("orr r1, r1, r8 ");
   307 	asm("str r1, [r4] ");				// store new bit mask
   308 	asm("beq sfree_0 ");				// if none were already free, finished
   309 	asm("bl " CSM_CFUNC(__e32_bit_count_32));
   310 	asm("sub r6, r6, r0 ");
   311 	asm("sfree_0: ");
   312 	asm("str r6, [r7] ");				// store free count
   313 	asm("ldmfd sp!, {r4-r8,pc} ");			// return
   314 	
   315 	asm("sfree_cross_bdry: ");
   316 	asm("mvn r5, #0 ");
   317 	asm("mov r5, r5, lsr r1 ");
   318 	asm("sfree_cross_bdry_1: ");
   319 	asm("ldr r1, [r4] ");				// original bit mask
   320 	asm("ands r0, r1, r5 ");			// r0 has 1's in bit positions which are already free
   321 	asm("orr r1, r1, r5 ");
   322 	asm("str r1, [r4], #4 ");			// store new bit mask
   323 	asm("beq sfree_2 ");				// skip if none were already free
   324 	asm("bl " CSM_CFUNC(__e32_bit_count_32));
   325 	asm("sub r6, r6, r0 ");
   326 	asm("sfree_2: ");
   327 	asm("mvn r5, #0 ");
   328 	asm("subs r8, r8, #32 ");
   329 	asm("bls sfree_0 ");
   330 	asm("cmp r8, #32 ");
   331 	asm("mvncc r5, r5, lsr r8 ");
   332 	asm("b sfree_cross_bdry_1 ");
   333 
   334 	asm("0: ");
   335 	ASM_FAULT();
   336 	}
   337 
   338 
   339 /**	Tests if a specific range of bit positions are all free
   340 	Specified range must lie within the total range for this allocator.
   341 
   342 	@param	aStart	First position to check
   343 	@param	aLength	Number of consecutive positions to check, must be >0
   344 	@return	FALSE if all positions free, TRUE if at least one is occupied.
   345  */
   346 EXPORT_C __NAKED__ TBool TBitMapAllocator::NotFree(TInt /*aStart*/, TInt /*aLength*/) const
   347 	{
   348 	// Inverse logic - returns 0 if all positions free, nonzero otherwise
   349 	asm("ldr r3, [r0, #8] ");
   350 	asm("adds ip, r1, r2 ");
   351 	asm("bcs 0f ");
   352 	asm("cmp ip, r3 ");
   353 	asm("bhi 0f ");
   354 	asm("mov r3, r1, lsr #5 ");
   355 	asm("and r1, r1, #0x1f ");
   356 	asm("add r3, r0, r3, lsl #2 ");
   357 	asm("add ip, r2, r1 ");
   358 	asm("add r3, r3, #12 ");
   359 	asm("cmp ip, #32 ");
   360 	asm("bhi 1f ");
   361 	asm("mvn ip, #0 ");
   362 	asm("ldr r0, [r3] ");
   363 	asm("mvn ip, ip, lsr r2 ");
   364 	asm("mov ip, ip, lsr r1 ");
   365 	asm("eor r0, r0, ip ");
   366 	asm("ands r0, r0, ip ");
   367 	__JUMP(,lr);
   368 	asm("1: ");
   369 	asm("mvn r2, #0 ");
   370 	asm("mov r2, r2, lsr r1 ");
   371 	asm("2: ");
   372 	asm("ldr r1, [r3], #4 ");
   373 	asm("eor r0, r1, r2 ");
   374 	asm("ands r0, r0, r2 ");
   375 	__JUMP(ne,lr);
   376 	asm("mvn r2, #0 ");
   377 	asm("subs ip, ip, #32 ");
   378 	__JUMP(ls,lr);
   379 	asm("cmp ip, #32 ");
   380 	asm("mvncc r2, r2, lsr ip ");
   381 	asm("b 2b ");
   382 
   383 	asm("0: ");
   384 	ASM_FAULT();
   385 	}
   386 
   387 
   388 /**	Tests if a specific range of bit positions are all occupied
   389 	Specified range must lie within the total range for this allocator.
   390 
   391 	@param	aStart	First position to check
   392 	@param	aLength	Number of consecutive positions to check, must be >0
   393 	@return	FALSE if all positions occupied, TRUE if at least one is free.
   394  */
   395 EXPORT_C __NAKED__ TBool TBitMapAllocator::NotAllocated(TInt /*aStart*/, TInt /*aLength*/) const
   396 	{
   397 	// Inverse logic - returns 0 if all positions allocated, nonzero otherwise
   398 	asm("ldr r3, [r0, #8] ");
   399 	asm("adds ip, r1, r2 ");
   400 	asm("bcs 0f ");
   401 	asm("cmp ip, r3 ");
   402 	asm("bhi 0f ");
   403 	asm("mov r3, r1, lsr #5 ");
   404 	asm("and r1, r1, #0x1f ");
   405 	asm("add r3, r0, r3, lsl #2 ");
   406 	asm("add ip, r2, r1 ");
   407 	asm("add r3, r3, #12 ");
   408 	asm("cmp ip, #32 ");
   409 	asm("bhi 1f ");
   410 	asm("mvn ip, #0 ");
   411 	asm("ldr r0, [r3] ");
   412 	asm("mvn ip, ip, lsr r2 ");
   413 	asm("ands r0, r0, ip, lsr r1 ");
   414 	__JUMP(,lr);
   415 	asm("1: ");
   416 	asm("mvn r2, #0 ");
   417 	asm("mov r2, r2, lsr r1 ");
   418 	asm("2: ");
   419 	asm("ldr r1, [r3], #4 ");
   420 	asm("ands r0, r1, r2 ");
   421 	__JUMP(ne,lr);
   422 	asm("mvn r2, #0 ");
   423 	asm("subs ip, ip, #32 ");
   424 	__JUMP(ls,lr);
   425 	asm("cmp ip, #32 ");
   426 	asm("mvncc r2, r2, lsr ip ");
   427 	asm("b 2b ");
   428 
   429 	asm("0: ");
   430 	ASM_FAULT();
   431 	}
   432 
   433 
   434 /**	Allocate up to a specified number of available bit positions
   435 	The allocated positions are not required to bear any relationship to
   436 	each other.
   437 	If the number of free positions is less than the number requested,
   438 	allocate all currently free positions.
   439 
   440 	@param	aLength	Maximum number of positions to allocate.
   441 	@param	aList	Pointer to memory area where allocated bit numbers should be stored.
   442 	@return	The number of positions allocated
   443  */
   444 EXPORT_C __NAKED__ TInt TBitMapAllocator::AllocList(TInt /*aLength*/, TInt* /*aList*/)
   445 	{
   446 	asm("ldmia r0, {r3,ip} ");				// r3=iAvail, ip=first check word
   447 	asm("stmfd sp!, {r4-r5,lr} ");
   448 	asm("cmp r1, r3 ");
   449 	asm("movgt r1, r3 ");					// if aLength>iAvail, aLength=iAvail
   450 	asm("movs r5, r1 ");					// r5 counts allocations
   451 	asm("beq 0f ");							// if length 0, exit
   452 	asm("sub r3, r3, r1 ");					// reduce available count
   453 	asm("sub r4, ip, r0 ");
   454 	asm("sub r4, r4, #12 ");				// r4=offset of first check word from iMap[0];
   455 	asm("str r3, [r0] ");
   456 	asm("mov r4, r4, lsl #3 ");				// r4=bit number of MSB of first check word
   457 	asm("1: ");
   458 	asm("ldr lr, [ip], #4 ");				// lr=next word
   459 	asm("cmp lr, #0 ");
   460 	asm("addeq r4, r4, #32 ");				// if word=0, increment bit number by 32 and check next word
   461 	asm("beq 1b ");
   462 	asm("mov r3, #1 ");
   463 	asm("sub r4, r4, #1 ");
   464 	asm("2: ");
   465 	asm("mov r3, r3, ror #1 ");				// shift mask right one
   466 	asm("add r4, r4, #1 ");					// and increment bit number
   467 	asm("tst lr, r3 ");						// check next bit
   468 	asm("beq 2b ");
   469 	asm("str r4, [r2], #4 ");				// bit=1, so store bit number in list
   470 	asm("subs r5, r5, #1 ");				// check if we are finished
   471 	asm("beq 4f ");							// branch if we are
   472 	asm("bics lr, lr, r3 ");				// clear bit and see if word now empty
   473 	asm("bne 2b ");							// if word not empty, get next bit
   474 	asm("str lr, [ip, #-4] ");				// word empty - clear word
   475 	asm("add r4, r4, #32 ");				// word empty - step bit number on to next word
   476 	asm("bic r4, r4, #31 ");
   477 	asm("b 1b ");							// and go to check next word
   478 	asm("4: ");
   479 	asm("bics lr, lr, r3 ");				// clear bit
   480 	asm("str lr, [ip, #-4] ");				// we are finished - store modified word
   481 	asm("subne ip, ip, #4 ");				// if word not empty, first check=last read word
   482 	asm("str ip, [r0, #4] ");				// update first check word
   483 	asm("0: ");
   484 	asm("mov r0, r1 ");						// return number of positions allocated
   485 	asm("ldmfd sp!, {r4-r5,pc} ");
   486 	}
   487 
   488 
   489 /**	Find a set of consecutive bit positions with specified alignment, with
   490 	support for chaining multiple allocators.
   491 	Note that this function does not mark the positions as allocated.
   492 
   493 	@param	aLength		number of consecutive bit positions to allocate
   494 	@param	aAlign		logarithm to base 2 of the alignment required
   495 	@param	aBase		the alignment of the first bit of this allocator - only significant modulo 2^aAlign
   496 	@param	aBestFit	TRUE for best fit allocation strategy, FALSE for first fit
   497 	@param	aCarry		carry in/carry out
   498 	@param	aRunLength	Holds best run length found so far.  This will be set to KMaxTInt when no
   499 						suitable run length has been found.  In best fit mode aCarry should also be
   500 						checked as aRunLength will not be set if aCarry is the only suitable run length
   501 						found.
   502 	@param	aOffset		The bit position to start the search from, set to 0 to search all bit positions.
   503 						aOffset will be aligned so all bits before an aligned aOffset will be
   504 						ignored.  This can only be non-zero if aCarry is zero as any carry in bits will be
   505 						ignored if aOffset is non-zero.
   506 
   507 	@return	Start position if a suitable run was found
   508 	@return	KErrNotFound if no suitable run was found
   509 	@return KErrOverflow, if all positions free and best fit mode, or if all positions free 
   510 			in first fit mode and length requested > number of positions available.
   511 
   512 	@see	TBitMapAllocator::AllocConsecutive(TInt aLength, TBool aBestFit)
   513 	@see	TBitMapAllocator::AllocAligned(TInt aLength, TInt aAlign, TInt aBase, TBool aBestFit)
   514 	@see	..\bma.cpp for more details
   515  */
   516 EXPORT_C __NAKED__ TInt TBitMapAllocator::AllocAligned(TInt /*aLength*/, TInt /*aAlign*/, TInt /*aBase*/,
   517 												TBool /*aBestFit*/, TInt& /*aCarry*/, TInt& /*aRunLength*/,
   518 												TUint /*aOffset*/) const
   519 	{
   520 	// r0=this, r1=aLength, r2=aAlign, r3=aBase, [sp+0]=aBestFit, [sp+4]=&aCarry, [sp+8]=&aRunLength
   521 	// [sp+12] = aOffset.
   522 	asm("ldr r12, [sp, #0] ");				// r12=aBestFit
   523 	asm("cmp r1, #0 ");
   524 	asm("ble aa_inv ");						// __ASSERT_ALWAYS(aLength>0, TBMA_FAULT())
   525 	asm("cmp r2, #31 ");					
   526 	asm("bhs aa_inv ");						// __ASSERT_ALWAYS(TUint(aAlign)<31, TBMA_FAULT())
   527 	asm("stmfd sp!, {r4-r11,lr} ");
   528 	asm("movs r8, r12 ");					//
   529 	asm("ldr r11, [sp, #40] ");				// r11=&aCarry
   530 	asm("mvnne r8, #0x80000000 ");			// if (aBestFit) r8=7fffffff else r8=0
   531 	asm("ldmia r0!, {r4-r6} ");				// r4=iAvail, r5=iCheckFirst, r6=iSize, r0->iMap[0]
   532 	asm("ldr r12, [sp, #48] ");				// r12 = aOffset;
   533 	asm("cmp r6, r12 ");
   534 	asm("bls aa_inv ");						// __ASSERT_ALWAYS(aOffset < (TUint)iSize, TBMA_FAULT())
   535 	asm("ldr r9, [r11] ");					// r9=aCarry
   536 	asm("cmp r9, #0 ");
   537 	asm("cmpne r12, #0 ");
   538 	asm("bne aa_inv ");						//__ASSERT_ALWAYS(!aCarry || !aOffset, TBMA_FAULT())
   539 	asm("mov r12, #1 ");
   540 	asm("mov r12, r12, lsl r2 ");			// r12=alignsize = 1<<aAlign
   541 	asm("sub r2, r12, #1 ");				// r2=alignmask = alignsize-1
   542 	asm("cmp r4, r6 ");						// check for iAvail==iSize
   543 	asm("beq aa_all_free ");				// branch if so
   544 	asm("rsbs r9, r9, #0 ");				// r9=run start=-aCarry
   545 	asm("movne r5, r0 ");					// if carry, pW=iMap
   546 	asm("sub r4, r5, r0 ");					// r4=first check address - &iMap[0]
   547 	asm("add r12, r6, #31 ");
   548 	asm("mov r4, r4, lsl #3 ");				// r4=bit number of first bit to check
   549 	asm("bic r12, r12, #31 ");				// r12=size rounded up to multiple of 32
   550 	asm("mvn r7, #0 ");						// saved bit number (p)
   551 	asm("add r10, r0, r12, lsr #3 ");		// r10=end address of bitmap
   552 	asm("str r7, [sp, #-4]! ");				// saved bit number (p) onto stack
   553 	asm("movs r11, r9 ");
   554 	asm("mvnne r11, #0 ");					// if (aCarry) r0=~0 else r0=0
   555 
   556 	// registers:	r0=this->iMap, r1=aLength, r2=alignmask, r3=aBase, r4=current bit number, r5=word pointer
   557 	//				r6=iSize, r7=, r8=saved run length, r9=run start pos
   558 	//				r10=end address of bitmap, r11=state
   559 	asm("ldr r7, [sp, #52] ");				// r7 = aOffset;
   560 	asm("cmp r7, #0 ");						// if (aOffset)
   561 	asm("beq aa_word ");
   562 	asm("add r7, r7, r3 ");					// r7 = aOffset + aBase
   563 	asm("add r7, r7, r2 ");					// r7 = aOffset + aBase + alignmask
   564 	asm("bic r7, r7, r2 ");					// r7 = (aOffset + aBase + alignmask) & ~alignmask
   565 	asm("sub r7, r7, r3 ");					// r7 -= aBase
   566 	asm("mov r12, r7, lsr #5 ");			// r12 = aOffset >> 5 (number of pointer increments required)
   567 	asm("add r0, r0, r12, lsl #2 ");		// r0 = offsetWord = iMap + (aOffset >> 5)	(pointer add so shift=2)
   568 	asm("cmp r0, r5 ");						// if (offsetWord >= pW)
   569 	asm("movpl r5, r0 ");					// r5 = pW = offsetWord
   570 	asm("andpl r4, r7, #0xffffffe0 ");		// r4 = n = aOffset & 0xffffffe0
   571 	asm("andpl r7, r7, #31 ");				// r7 = aOffset & 31
   572 	asm("mov r0, #0xffffffff ");			// r0 = 0xffffffff
   573 	asm("mov r7, r0, lsr r7 ");				// r7 = offsetMask = 0xffffffff >> (aOffset & 31)
   574 
   575 	// registers:	r0=bit to check (b), r1=aLength, r2=alignmask, r3=aBase, r4=current bit number, r5=word pointer
   576 	//				r6=iSize, r7=offsetMask, r8=saved run length, r9=run start pos
   577 	//				r10=end address of bitmap, r11=state, r12=word
   578 	asm("aa_word: ");						// while (pW < pE)
   579 	asm("cmp r5, r10 ");					// reached end?
   580 	asm("ldrlo r12, [r5], #4 ");			// if not, r12=next word (=*pW++)
   581 	asm("bhs aa_end_loop ");				// if end, branch out
   582 
   583 	asm("cmp r7, #0 ");						// if (offsetMask)
   584 	asm("andne r12, r12, r7 ");				// r12 = word &= offsetMask
   585 	asm("movne r7, #0 ");					// offsetmask = 0;
   586 	
   587 	asm("eors r12, r12, r11 ");				// r12=w^s, test if any of required bit present
   588 	asm("addeq r4, r4, #32 ");				// if not, increment bit # by 32
   589 	asm("beq aa_word ");					// and do next word
   590 	asm("mov r0, #0x80000000 ");			// bit to check (b)
   591 
   592 	asm("aa_bit: ");						// if ((word ^ s) & b)
   593 	asm("tst r12, r0 ");					// does bit have required state?
   594 	asm("bne aa_bit_found ");
   595 	asm("aa_end_for: ");
   596 	asm("add r4, r4, #1 ");					// increment bit number
   597 	asm("movs r0, r0, lsr #1 ");			// next bit
   598 	asm("bne aa_bit ");						// if all bits not done, do next
   599 	asm("b aa_word ");						// else do next word
   600 
   601 	asm("aa_bit_found: ");
   602 	asm("mvns r12, r12 ");					// Invert r12 to invert search bit
   603 	asm("mvns r14, r11 ");					// if (s)
   604 	asm("cmpeq r4, r6 ");					// && n==iSize
   605 	asm("beq aa_end_loop ");				// ... finished
   606 	asm("mvns r11, r11 ");					// else s=~s
   607 	asm("movne r9, r4 ");					// if (s) q=n (1 found so save position)
   608 	asm("bne aa_end_for ");
   609 
   610 	asm("sub r14, r4, r9 ");				// r14 = run length = n - q
   611 	asm("stmdb sp!, {r0,r12} ");			// store b (r0) and word (r12) on stack
   612 	asm("add r12, r9, r3 ");				// r12 = q + aBase
   613 	asm("add r12, r12, r2 ");				// r12 = q + aBase + alignmask
   614 	asm("bic r12, r12, r2 ");				// r12 = (q + aBase + alignmask) & ~alignmask
   615 	asm("sub r12, r12, r3 ");				// r12 = alignedStartPos = r12 - aBase
   616 	asm("sub r0, r12, r9 ");				// r0 = lost = alignedStartPos - q
   617 	asm("sub r0, r14, r0 ");				// r0 = run length - lost
   618 	asm("cmp r0, r1 ");						// if (run length - lost >= aLength)
   619 	asm("ldmltia sp!, {r0,r12} ");			// if aligned length too short: r0 = b and r12 = word from stack 
   620 	asm("blt aa_end_for ");					// (run length - lost) too short (must be signed comparison)
   621 
   622 // if (rl-lost>=aLength)
   623 
   624 	asm("cmp r1, r14 ");					// check for exact run length match (if (run length == aLength))
   625 	asm("cmpne r8, #0 ");					// check for best fit (r8 only ever set if (aBestfit))
   626 	asm("beq aa_found_it ");				// exact match or not in best fit mode
   627 
   628 // 		if (r1<minrl)
   629 	asm("cmp r12, #0 ");
   630 	asm("movmi r12, #0 ");					// r12 = (alignedStartPos >= 0)? alignedStartPos : 0
   631 	asm("cmp r14, r8 ");					// Compare run length with current minimum
   632 	asm("movlo r8, r14 ");					// if shorter, replace
   633 	asm("strlo r12, [sp, #8] ");			// save alignedStartPos (p = (alignedStartPos >= 0)? alignedStartPos : 0)
   634 	asm("ldmia sp!, {r0,r12} ");			// r0 = b and r12 = word from stack
   635 	asm("b aa_end_for ");					// next bit
   636 // 		end {if (r1<minrl)}
   637 
   638 // 		if (!aBestFit || run length == aLength)
   639 	// registers:	r12 = alignedStartPos, r14 = run length
   640 	asm("aa_found_it: ");
   641 	asm("ldr r1, [sp, #52] ");				// r1=&aCarry
   642 	asm("ldr r7, [sp, #56] ");				// r7=&aRunLength
   643 	asm("subs r0, r12, #0 ");				// r0 = alignStartPos, alignedStartPos >= 0?
   644 	asm("movmi r0, #0 ");					// if alignedStartPos < 0 r0=0
   645 	asm("str r14, [r7] ");					// aRunLength = run length
   646 	asm("mov r14, #0 ");
   647 	asm("strge r14, [r1] ");				// if (alignedStartPos >= 0), aCarry=0
   648 	asm("ldmfd sp!, {r1-r11,pc} ");			// return
   649 // 		end {if (!aBestFit || run length == aLength)}
   650 
   651 // end {if (rl-lost>=aLength)}
   652 
   653 	asm("aa_end_loop: ");
   654 	asm("ldr r10, [sp, #48] ");				// r10=&aRunLength
   655 
   656 //		registers: 	r2 = alignmask, r3 = aBase, r4=current bit number(n), 
   657 //					r9=run start pos(q),  r10=&aRunLength, r11 = state(s), r14 = run length(rl)
   658 	asm("cmp r8, r1 ");						// compare min rl with aLength
   659 	asm("beq aa_end_loop2 ");				// if exact match, skip
   660 
   661 // if (minrl != aLength)
   662 	asm("ldr r12, [sp, #44] ");				// r12=&aCarry
   663 	asm("mov r14, #0 ");					// r14 = run length = 0
   664 	asm("cmp r11, #0 ");
   665 	asm("beq aa_end_loop3 ");				// if (!s) no final run
   666 	asm("sub r14, r4, r9 ");				// rl4 = run length = n-q
   667 	asm("cmp r8, #0 ");						// if (!aBestFit) (r8 only and always set when best fit mode)
   668 	asm("bne aa_end_loop3 ");				// if best fit, don't count final run
   669 
   670 //		if (!aBestFit)
   671 	asm("add r0, r9, r3 ");					// r0 = q + aBase
   672 	asm("add r0, r0, r2 ");					// r0 = q + aBase + alignmask
   673 	asm("bic r0, r0, r2 ");					// r0 = (q + aBase + alignmask) & ~alignmask
   674 	asm("sub r0, r0, r3 ");					// r0 = alignedStartPos = r0 -= aBase
   675 	asm("sub r2, r0, r9 ");					// r2 = lost = alignedStartPos - q
   676 	asm("sub r2, r14, r2 ");				// r2 = run length - lost
   677 	asm("cmp r2, r1 ");						// if (run length - lost >= aLength)
   678 	asm("blt aa_end_loop3 ");
   679 
   680 //			if (run length - lost >= aLength)
   681 	asm("mov r8, r14 ");					// r8 = run length (ready to be stored in return)
   682 	asm("mov r14, #0 ");					// r14 = 0 (aCarry on return)
   683 	asm("str r0, [sp, #0] ");				// Save alignedStartPos on stack ready for return
   684 
   685 //			end {if (run length - lost >= aLength)}
   686 //		end {if (!aBestFit)}
   687 
   688 	asm("aa_end_loop3: ");
   689 	asm("str r14, [r12] ");					// Save aCarry = run length = r14
   690 // end {if (minrl != aLength)}
   691 
   692 	asm("aa_end_loop2: ");
   693 	asm("str r8, [r10] ");					// aRunLength = minrl
   694 	asm("ldmfd sp!, {r0,r4-r11,pc} ");		// return saved pos
   695 
   696 // r1 = aLength r2 = alignmask, r3 = aBase,  r4 = iAvail, r6 = iSize, r9 = aCarry, r11 = &aCarry
   697 	asm("aa_all_free: ");
   698 	asm("ldr r12, [sp, #48] ");				// r12 = aOffset;
   699 	asm("cmp r12, #0 ");					// if (aOffset)
   700 	asm("addne r12, r12, r3 ");				// r12 = aOffset + aBase
   701 	asm("addne r12, r12, r2 ");				// r12 = aOffset + aBase + alignmask
   702 	asm("bicne r12, r12, r2 ");				// r12 = (aOffset + aBase + alignmask)&~alignmask
   703 	asm("subne r12, r12, r3 ");				// r12 = ((aOffset + aBase + alignmask)&~alignmask) - aBase
   704 	asm("subs r10, r6, r12 ");				// r10 = runLength = iSize - aOffset
   705 	asm("movmi r10, #0 ");					// if (aOffset < (TUint)iSize) runLength = 0;
   706 
   707 	asm("movs r0, r8 ");					// best fit? if not, r0=0
   708 	asm("bne aa_all_free2 ");				// skip if best fit mode
   709 	asm("sub r6, r12, r9 ");				// r6=aOffset-aCarry
   710 	asm("add r6, r6, r3 ");					// r6=aOffset-aCarry+aBase
   711 	asm("add r6, r6, r2 ");					// r6=aOffset-aCarry+aBase+alignmask
   712 	asm("bic r6, r6, r2 ");					// r6=(aOffset-aCarry+aBase+alignmask)&~alignmask
   713 	asm("sub r6, r6, r3 ");					// r6 = alignedStartPos
   714 	asm("sub r3, r12, r9 ");				// r3 = aOffset - aCarry
   715 	asm("sub r3, r6, r3 ");					// r3 = lost = alignedStartPos - (aOffset - aCarry)
   716 	asm("add r2, r10, r9 ");				// r2 = aRunLength + aCarry
   717 	asm("sub r2, r2, r3 ");					// r2 -= lost
   718 	asm("cmp r2, r1 ");						// if (aRunLength + aCarry - lost >= aLength)
   719 	asm("blt aa_all_free2 ");
   720 	asm("cmp r6, #0 ");
   721 	asm("ldr r5, [sp, #44] ");				// r5 = &RunLength
   722 	asm("str r10, [r5] ");					// Save aRunLength (aRunLength = runLength)
   723 	asm("movge r9, #0 ");					// if (alignedStartPos >= 0) aCarry = 0;
   724 	asm("str r9, [r11] ");					// Save aCarry
   725 	asm("movge r0, r6 ");					// r0 = (alignedStartPos >= 0)? alignedStartPos : 0
   726 	asm("ldmfd sp!, {r4-r11,pc} ");			// return r0
   727 
   728 	asm("aa_all_free2: ");
   729 	asm("ldr r12, [sp, #48] ");				// r12 = aOffset;
   730 	asm("cmp r12, #0 ");					// if (aOffset)
   731 	asm("movne r9, r10 ");					// r9 = aCarry = runLength
   732 	asm("addeq r9, r9, r4 ");				// r9 = aCarry + iAvail
   733 	asm("str r9, [r11] ");					// Save aCarry
   734 	asm("ldr r5, [sp, #44] ");				// r5 = &RunLength
   735 	asm("mov r0, #%a0" : : "i" ((TInt)KMaxTInt));
   736 	asm("str r0, [r5] ");					// aRunLength = KMaxTInt
   737 	asm("mov r0, #%a0" : : "i" ((TInt)KErrOverflow));
   738 	asm("ldmfd sp!, {r4-r11,pc} ");			// return KErrOverflow
   739 
   740 	asm("aa_inv: ");
   741 	ASM_FAULT();
   742 	}
   743 #endif