os/kernelhwsrv/kernel/eka/euser/epoc/arm/uc_huffman.cia
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\euser\epoc\arm\uc_huffman.cia
    15 // 
    16 //
    17 
    18 #include "e32huffman.h"
    19 #include <cpudefs.h>
    20 
    21 #ifdef __HUFFMAN_MACHINE_CODED__
    22 
    23 // NB The EABI layout of TBitInput is different from GCC. Its vtbl is at 
    24 // offset 0 rather than offset 16
    25 
    26 EXPORT_C __NAKED__ TUint TBitInput::ReadL()
    27 /** Read a single bit from the input
    28 
    29 	Return the next bit in the input stream. This will call UnderflowL() if
    30 	there are no more bits available.
    31 
    32 	@return The next bit in the stream
    33 
    34 	@leave "UnderflowL()" It the bit stream is exhausted more UnderflowL is called
    35 		to get more data
    36 */
    37 	{
    38 	asm(".code 32");
    39 #ifdef __EABI__
    40 	asm("ldmib r0!, {r2,r3}");
    41 #else
    42 	asm("ldmia r0!, {r2,r3}");
    43 #endif
    44 	// r0 = this+8
    45 	asm("subs	r2, r2, #1");
    46 	asm("movpl	r12, r3, asl #1");
    47 #ifdef __EABI__
    48 	asm("stmplda r0, {r2,r12}");
    49 #else
    50 	asm("stmpldb r0, {r2,r12}");
    51 #endif
    52 	asm("movpl	r0, r3, lsr #31");
    53 	__JUMP(pl,lr);
    54 	asm("mov r12, #0");
    55 	asm("b __readmorebits");	// r2==-1, r12==0 -> so all set
    56 	}
    57 
    58 EXPORT_C __NAKED__ TUint TBitInput::ReadL(TInt aSize)
    59 /** Read a multi-bit value from the input
    60 
    61 	Return the next few bits as an unsigned integer. The last bit read is
    62 	the least significant bit of the returned value, and the value is
    63 	zero extended to return a 32-bit result.
    64 
    65 	A read of zero bits will always reaturn zero.
    66 	
    67 	This will call UnderflowL() if there are not enough bits available.
    68 
    69 	@param "TInt aSize" The number of bits to read
    70 	
    71 	@return The bits read from the stream
    72 
    73 	@leave "UnderflowL()" It the bit stream is exhausted more UnderflowL is called
    74 		to get more data
    75 */
    76 	{
    77 	asm(".code 32");
    78 #ifdef __EABI__
    79 	asm("   ldmib r0!, {r2,r3}");
    80 #else
    81 	asm("   ldmia r0!, {r2,r3}");
    82 #endif
    83 	asm("	subs r2, r2, r1");
    84 	asm("	movpl r12, r3, asl r1");
    85 #ifdef __EABI__
    86 	asm("   stmplda r0, {r2,r12}");
    87 #else
    88 	asm("   stmpldb r0, {r2,r12}");
    89 #endif
    90 	asm("	rsb r1, r1, #32");
    91 	asm("	movpl r0, r3, lsr r1");
    92 	__JUMP(pl,lr);
    93 	// r0=this+8, r1=32-#reqd, r2=count-#reqd (<0), r3=bits
    94 	asm("   sub r1, r1, r2");		// r1 = 32-iCount
    95 	asm("	mov r3, r3, lsr r1");	// scrub existing bits
    96 	asm("	rsb r1, r2, #0");		// r1 = #reqd-iCount
    97 	asm("	mov r12, r3, lsl r1");	// r12 has bits in final position
    98 	asm("__readmorebits:");
    99 	//r0=this+8
   100 	asm("	stmfd sp!, {r12,lr}");
   101 	
   102 #ifdef __EABI__
   103 	asm("	ldmib r0!, {r1,r14}");	// r1=remain, r14=ptr
   104 #else
   105 	asm("	ldmia r0!, {r1,r14}");	// r1=remain, r14=ptr
   106 #endif
   107 	//r0=this+16
   108 	asm("	cmp r1, #0");
   109 	asm("	ble	__readunderflow");
   110 	asm("	ldr	r12, [r14], #4");
   111 	asm("	subs r3, r1, #32");
   112 #ifdef __EABI__
   113 	asm("	stmda r0!, {r3,r14}");
   114 #else
   115 	asm("	stmdb r0!, {r3,r14}");
   116 #endif
   117 	// r0=this+8
   118 	asm("	addmi r1, r2, r1");
   119 	asm("	addpl r1, r2, #32");		// r1 = bits left in
   120 	asm("	eor	r3, r12, r12, ror #16");
   121 	asm("	bic	r3, r3, #16711680");
   122 	asm("	mov	r3, r3, lsr #8");
   123 	asm("	eor	r3, r3, r12, ror #8");		// r3=bits
   124 	// r0=this+8, r1=count-#reqd, r2=-#reqd, r3=bits, sp[0]=accum, sp[4]=return-pc
   125 	asm("	cmp r1, #0");
   126 	asm("	bmi __readgoroundagain");
   127 	asm("__readhavebits:");
   128 	asm("	rsb r12, r2, #0");
   129 	asm("	mov r12, r3, asl r12");
   130 #ifdef __EABI__
   131 	asm("	stmda r0, {r1,r12}");
   132 #else
   133 	asm("	stmdb r0, {r1,r12}");
   134 #endif
   135 	asm("	ldmfd sp!, {r12,lr}");
   136 	asm("	add r2, r2, #32");
   137 	asm("	orr	r0, r12, r3, lsr r2");
   138 	__JUMP(,lr);
   139 	asm("__readunderflow:");
   140 #ifdef __EABI__
   141 	asm("	ldr	r3, [r0, #-16]!");	// restore r0 to this
   142 #else
   143 	asm("	ldr	r3, [r0], #-16");	// restore r0 to this
   144 #endif
   145 	asm("	stmfd sp!, {r0,r2}");
   146 	// at this point the stack has grown by 16 bytes from the CFA
   147 	__EH_FRAME_ADDRESS(sp,16)
   148 	// The stack looks like this
   149 	// CFA-4  -> lr
   150 	// CFA-8  -> r12
   151 	// CFA-12 -> r2
   152 	// CFA-16 -> r0
   153 	// So we need to record lr @ CFA-4
   154 	// Nothing else needs to be restored since there's no barrier here
   155 	__EH_FRAME_SAVE1(lr,-4)
   156 	asm("	adr lr, 1f ");
   157 #ifdef __EABI__
   158 	asm("	ldr	ip, [r3, #0]");
   159 #else
   160 	asm("	ldr	ip, [r3, #8]");
   161 #endif
   162 	__JUMP(,ip);
   163 	asm("1: ");
   164 	asm("	ldmfd sp!, {r0,r2}");
   165 #ifdef __EABI__
   166 	asm("	ldmib r0!, {r1,r3}");	// r1=count, r3=bits
   167 #else
   168 	asm("	ldmia r0!, {r1,r3}");	// r1=count, r3=bits
   169 #endif
   170 	asm("	adds r1, r1, r2");		// adjust count for bits to extract
   171 	asm("	bpl __readhavebits");
   172 	asm("__readgoroundagain:");
   173 	// r0=this+8, r1=count-#reqd (<0), r2=-#reqd, r3=bits, sp[0]=accum, sp[4]=return-pc
   174 	asm("   sub r12, r1, r2");		// r12 = iCount
   175 	asm("	rsb r12, r12, #32");	// r12= 32-iCount
   176 	asm("	mov r3, r3, lsr r12");	// scrub existing bits
   177 	asm("	ldmfd sp!, {r12,lr}");
   178 	asm("	mov r2, r1");			// r2 = iCount-#reqd
   179 	asm("	rsb r1, r1, #0");		// r1 = #reqd-iCount
   180 	asm("	orr r12, r12, r3, lsl r1");	// r12 has bits in final position
   181 	asm("	b __readmorebits");
   182 	}
   183 
   184 EXPORT_C __NAKED__ TUint TBitInput::HuffmanL(const TUint32* aTree)
   185 /** Read and decode a Huffman Code
   186 
   187 	Interpret the next bits in the input as a Huffman code in the specified
   188 	decoding. The decoding tree should be the output from Huffman::Decoding().
   189 
   190 	@param "const TUint32* aTree" The huffman decoding tree
   191 
   192 	@return The symbol that was decoded
   193 
   194 	@leave "UnderflowL()" It the bit stream is exhausted more UnderflowL is called
   195 		to get more data
   196 */
   197 	{
   198 	asm(".code 32");
   199 	asm("__huffman:");
   200 #ifdef __EABI__
   201 	asm("   ldmib r0!, {r2,r3}");
   202 #else
   203 	asm("   ldmia r0!, {r2,r3}");
   204 #endif
   205 	asm("__decode:");
   206 	asm("	ldr r12, [r1]");
   207 	asm("	subs	r2, r2, #4");
   208 	asm("	bmi __fewbits");
   209 	asm("__fastloop:");
   210 	asm("	movs	r3, r3, asl #1");
   211 	asm("	movcc	r12, r12, asl #16");
   212 	asm("	tst	r12, #65536");
   213 	asm("	bne	__fastdecoded");
   214 	asm("	ldr	r12, [r1, r12, lsr #16]!");
   215 	asm("	sub	r2, r2, #1");
   216 	asm("	movs	r3, r3, asl #1");
   217 	asm("	movcc	r12, r12, asl #16");
   218 	asm("	tst	r12, #65536");
   219 	asm("	bne	__fastdecoded");
   220 	asm("	ldr	r12, [r1, r12, lsr #16]!");
   221 	asm("	sub	r2, r2, #1");
   222 	asm("	movs	r3, r3, asl #1");
   223 	asm("	movcc	r12, r12, asl #16");
   224 	asm("	tst	r12, #65536");
   225 	asm("	bne	__fastdecoded");
   226 	asm("	ldr	r12, [r1, r12, lsr #16]!");
   227 	asm("	sub	r2, r2, #1");
   228 	asm("	movs	r3, r3, asl #1");
   229 	asm("	movcc	r12, r12, asl #16");
   230 	asm("	tst	r12, #65536");
   231 	asm("	bne	__fastdecoded");
   232 	asm("	ldr	r12, [r1, r12, lsr #16]!");
   233 	asm("	subs	r2, r2, #1");
   234 	asm("	bpl __fastloop");
   235 	asm("__fewbits:");
   236 	asm("	adds r2, r2, #3");
   237 	asm("	bmi __nobits");
   238 	asm("__slowloop:");
   239 	asm("	movs	r3, r3, asl #1");
   240 	asm("	movcc	r12, r12, asl #16");
   241 	asm("	tst	r12, #65536");
   242 	asm("	bne	__decoded");
   243 	asm("	ldr	r12, [r1, r12, lsr #16]!");
   244 	asm("	subs	r2, r2, #1");
   245 	asm("	bpl __slowloop");
   246 	asm("__nobits:");
   247 	// r0=this, r1=tree, r2=count (-1), r3=bits (0), r12=node=*tree
   248 	// must preserve r0,r1
   249 #ifdef __EABI__
   250 	asm("	ldmib r0!, {r2,r3}");	// r2=remain, r3=ptr
   251 #else
   252 	asm("	ldmia r0!, {r2,r3}");	// r2=remain, r3=ptr
   253 #endif
   254 	asm("	cmp r2, #0");
   255 	asm("	ble	__underflow");
   256 	asm("	ldr	r12, [r3], #4");
   257 	asm("	subs r2, r2, #32");
   258 #ifdef __EABI__
   259 	asm("	stmda r0!, {r2,r3}");
   260 #else
   261 	asm("	stmdb r0!, {r2,r3}");
   262 #endif
   263 	asm("	addmi r2, r2, #32");
   264 	asm("	movpl r2, #32");
   265 	asm("	eor	r3, r12, r12, ror #16");
   266 	asm("	bic	r3, r3, #16711680");
   267 	asm("	mov	r3, r3, lsr #8");
   268 	asm("	eor	r3, r3, r12, ror #8");
   269 	asm("	b	__decode");
   270 	asm("__underflow:");
   271 #ifdef __EABI__
   272 	asm("	ldr	r3, [r0, #-16]!");	// restore r0 to this
   273 #else
   274 	asm("	ldr	r3, [r0], #-16");	// restore r0 to this
   275 #endif
   276 	asm("	stmfd sp!, {r0,r1,r2,lr}");
   277 	// sp is 16 bytes from CFA
   278 	__EH_FRAME_ADDRESS(sp,16)
   279 	// The stack looks like this:
   280 	// CFA-4  -> lr
   281 	// CFA-8  -> r2
   282 	// CFA-12 -> r1
   283 	// CFA-16 -> r0
   284 	// We saved lr @ CFA-4
   285 	// Nothing else needs to be restored since there's no barrier here
   286 	__EH_FRAME_SAVE1(lr,-4)
   287 	asm("	adr lr, 1f ");
   288 #ifdef __EABI__
   289 	asm("	ldr	ip, [r3, #0]");
   290 #else
   291 	asm("	ldr	ip, [r3, #8]");
   292 #endif
   293 	__JUMP(,ip);
   294 	asm("1: ");
   295 	asm("	ldmfd sp!, {r0,r1,r2,lr}");
   296 	asm("	b __huffman");
   297 	asm("__fastdecoded:");
   298 	asm("	add r2, r2, #3");
   299 	asm("__decoded:");
   300 #ifdef __EABI__
   301 	asm("	stmda r0, {r2, r3}");
   302 #else
   303 	asm("	stmdb r0, {r2, r3}");
   304 #endif
   305 	asm("	mov	r0, r12, lsr #17");
   306 	__JUMP(,lr);
   307 	}
   308 
   309 #endif
   310