kernel/eka/euser/epoc/arm/uc_huffman.cia
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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