kernel/eka/euser/epoc/arm/uc_huffman.cia
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/euser/epoc/arm/uc_huffman.cia	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,310 @@
+// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\euser\epoc\arm\uc_huffman.cia
+// 
+//
+
+#include "e32huffman.h"
+#include <cpudefs.h>
+
+#ifdef __HUFFMAN_MACHINE_CODED__
+
+// NB The EABI layout of TBitInput is different from GCC. Its vtbl is at 
+// offset 0 rather than offset 16
+
+EXPORT_C __NAKED__ TUint TBitInput::ReadL()
+/** Read a single bit from the input
+
+	Return the next bit in the input stream. This will call UnderflowL() if
+	there are no more bits available.
+
+	@return The next bit in the stream
+
+	@leave "UnderflowL()" It the bit stream is exhausted more UnderflowL is called
+		to get more data
+*/
+	{
+	asm(".code 32");
+#ifdef __EABI__
+	asm("ldmib r0!, {r2,r3}");
+#else
+	asm("ldmia r0!, {r2,r3}");
+#endif
+	// r0 = this+8
+	asm("subs	r2, r2, #1");
+	asm("movpl	r12, r3, asl #1");
+#ifdef __EABI__
+	asm("stmplda r0, {r2,r12}");
+#else
+	asm("stmpldb r0, {r2,r12}");
+#endif
+	asm("movpl	r0, r3, lsr #31");
+	__JUMP(pl,lr);
+	asm("mov r12, #0");
+	asm("b __readmorebits");	// r2==-1, r12==0 -> so all set
+	}
+
+EXPORT_C __NAKED__ TUint TBitInput::ReadL(TInt aSize)
+/** Read a multi-bit value from the input
+
+	Return the next few bits as an unsigned integer. The last bit read is
+	the least significant bit of the returned value, and the value is
+	zero extended to return a 32-bit result.
+
+	A read of zero bits will always reaturn zero.
+	
+	This will call UnderflowL() if there are not enough bits available.
+
+	@param "TInt aSize" The number of bits to read
+	
+	@return The bits read from the stream
+
+	@leave "UnderflowL()" It the bit stream is exhausted more UnderflowL is called
+		to get more data
+*/
+	{
+	asm(".code 32");
+#ifdef __EABI__
+	asm("   ldmib r0!, {r2,r3}");
+#else
+	asm("   ldmia r0!, {r2,r3}");
+#endif
+	asm("	subs r2, r2, r1");
+	asm("	movpl r12, r3, asl r1");
+#ifdef __EABI__
+	asm("   stmplda r0, {r2,r12}");
+#else
+	asm("   stmpldb r0, {r2,r12}");
+#endif
+	asm("	rsb r1, r1, #32");
+	asm("	movpl r0, r3, lsr r1");
+	__JUMP(pl,lr);
+	// r0=this+8, r1=32-#reqd, r2=count-#reqd (<0), r3=bits
+	asm("   sub r1, r1, r2");		// r1 = 32-iCount
+	asm("	mov r3, r3, lsr r1");	// scrub existing bits
+	asm("	rsb r1, r2, #0");		// r1 = #reqd-iCount
+	asm("	mov r12, r3, lsl r1");	// r12 has bits in final position
+	asm("__readmorebits:");
+	//r0=this+8
+	asm("	stmfd sp!, {r12,lr}");
+	
+#ifdef __EABI__
+	asm("	ldmib r0!, {r1,r14}");	// r1=remain, r14=ptr
+#else
+	asm("	ldmia r0!, {r1,r14}");	// r1=remain, r14=ptr
+#endif
+	//r0=this+16
+	asm("	cmp r1, #0");
+	asm("	ble	__readunderflow");
+	asm("	ldr	r12, [r14], #4");
+	asm("	subs r3, r1, #32");
+#ifdef __EABI__
+	asm("	stmda r0!, {r3,r14}");
+#else
+	asm("	stmdb r0!, {r3,r14}");
+#endif
+	// r0=this+8
+	asm("	addmi r1, r2, r1");
+	asm("	addpl r1, r2, #32");		// r1 = bits left in
+	asm("	eor	r3, r12, r12, ror #16");
+	asm("	bic	r3, r3, #16711680");
+	asm("	mov	r3, r3, lsr #8");
+	asm("	eor	r3, r3, r12, ror #8");		// r3=bits
+	// r0=this+8, r1=count-#reqd, r2=-#reqd, r3=bits, sp[0]=accum, sp[4]=return-pc
+	asm("	cmp r1, #0");
+	asm("	bmi __readgoroundagain");
+	asm("__readhavebits:");
+	asm("	rsb r12, r2, #0");
+	asm("	mov r12, r3, asl r12");
+#ifdef __EABI__
+	asm("	stmda r0, {r1,r12}");
+#else
+	asm("	stmdb r0, {r1,r12}");
+#endif
+	asm("	ldmfd sp!, {r12,lr}");
+	asm("	add r2, r2, #32");
+	asm("	orr	r0, r12, r3, lsr r2");
+	__JUMP(,lr);
+	asm("__readunderflow:");
+#ifdef __EABI__
+	asm("	ldr	r3, [r0, #-16]!");	// restore r0 to this
+#else
+	asm("	ldr	r3, [r0], #-16");	// restore r0 to this
+#endif
+	asm("	stmfd sp!, {r0,r2}");
+	// at this point the stack has grown by 16 bytes from the CFA
+	__EH_FRAME_ADDRESS(sp,16)
+	// The stack looks like this
+	// CFA-4  -> lr
+	// CFA-8  -> r12
+	// CFA-12 -> r2
+	// CFA-16 -> r0
+	// So we need to record lr @ CFA-4
+	// Nothing else needs to be restored since there's no barrier here
+	__EH_FRAME_SAVE1(lr,-4)
+	asm("	adr lr, 1f ");
+#ifdef __EABI__
+	asm("	ldr	ip, [r3, #0]");
+#else
+	asm("	ldr	ip, [r3, #8]");
+#endif
+	__JUMP(,ip);
+	asm("1: ");
+	asm("	ldmfd sp!, {r0,r2}");
+#ifdef __EABI__
+	asm("	ldmib r0!, {r1,r3}");	// r1=count, r3=bits
+#else
+	asm("	ldmia r0!, {r1,r3}");	// r1=count, r3=bits
+#endif
+	asm("	adds r1, r1, r2");		// adjust count for bits to extract
+	asm("	bpl __readhavebits");
+	asm("__readgoroundagain:");
+	// r0=this+8, r1=count-#reqd (<0), r2=-#reqd, r3=bits, sp[0]=accum, sp[4]=return-pc
+	asm("   sub r12, r1, r2");		// r12 = iCount
+	asm("	rsb r12, r12, #32");	// r12= 32-iCount
+	asm("	mov r3, r3, lsr r12");	// scrub existing bits
+	asm("	ldmfd sp!, {r12,lr}");
+	asm("	mov r2, r1");			// r2 = iCount-#reqd
+	asm("	rsb r1, r1, #0");		// r1 = #reqd-iCount
+	asm("	orr r12, r12, r3, lsl r1");	// r12 has bits in final position
+	asm("	b __readmorebits");
+	}
+
+EXPORT_C __NAKED__ TUint TBitInput::HuffmanL(const TUint32* aTree)
+/** Read and decode a Huffman Code
+
+	Interpret the next bits in the input as a Huffman code in the specified
+	decoding. The decoding tree should be the output from Huffman::Decoding().
+
+	@param "const TUint32* aTree" The huffman decoding tree
+
+	@return The symbol that was decoded
+
+	@leave "UnderflowL()" It the bit stream is exhausted more UnderflowL is called
+		to get more data
+*/
+	{
+	asm(".code 32");
+	asm("__huffman:");
+#ifdef __EABI__
+	asm("   ldmib r0!, {r2,r3}");
+#else
+	asm("   ldmia r0!, {r2,r3}");
+#endif
+	asm("__decode:");
+	asm("	ldr r12, [r1]");
+	asm("	subs	r2, r2, #4");
+	asm("	bmi __fewbits");
+	asm("__fastloop:");
+	asm("	movs	r3, r3, asl #1");
+	asm("	movcc	r12, r12, asl #16");
+	asm("	tst	r12, #65536");
+	asm("	bne	__fastdecoded");
+	asm("	ldr	r12, [r1, r12, lsr #16]!");
+	asm("	sub	r2, r2, #1");
+	asm("	movs	r3, r3, asl #1");
+	asm("	movcc	r12, r12, asl #16");
+	asm("	tst	r12, #65536");
+	asm("	bne	__fastdecoded");
+	asm("	ldr	r12, [r1, r12, lsr #16]!");
+	asm("	sub	r2, r2, #1");
+	asm("	movs	r3, r3, asl #1");
+	asm("	movcc	r12, r12, asl #16");
+	asm("	tst	r12, #65536");
+	asm("	bne	__fastdecoded");
+	asm("	ldr	r12, [r1, r12, lsr #16]!");
+	asm("	sub	r2, r2, #1");
+	asm("	movs	r3, r3, asl #1");
+	asm("	movcc	r12, r12, asl #16");
+	asm("	tst	r12, #65536");
+	asm("	bne	__fastdecoded");
+	asm("	ldr	r12, [r1, r12, lsr #16]!");
+	asm("	subs	r2, r2, #1");
+	asm("	bpl __fastloop");
+	asm("__fewbits:");
+	asm("	adds r2, r2, #3");
+	asm("	bmi __nobits");
+	asm("__slowloop:");
+	asm("	movs	r3, r3, asl #1");
+	asm("	movcc	r12, r12, asl #16");
+	asm("	tst	r12, #65536");
+	asm("	bne	__decoded");
+	asm("	ldr	r12, [r1, r12, lsr #16]!");
+	asm("	subs	r2, r2, #1");
+	asm("	bpl __slowloop");
+	asm("__nobits:");
+	// r0=this, r1=tree, r2=count (-1), r3=bits (0), r12=node=*tree
+	// must preserve r0,r1
+#ifdef __EABI__
+	asm("	ldmib r0!, {r2,r3}");	// r2=remain, r3=ptr
+#else
+	asm("	ldmia r0!, {r2,r3}");	// r2=remain, r3=ptr
+#endif
+	asm("	cmp r2, #0");
+	asm("	ble	__underflow");
+	asm("	ldr	r12, [r3], #4");
+	asm("	subs r2, r2, #32");
+#ifdef __EABI__
+	asm("	stmda r0!, {r2,r3}");
+#else
+	asm("	stmdb r0!, {r2,r3}");
+#endif
+	asm("	addmi r2, r2, #32");
+	asm("	movpl r2, #32");
+	asm("	eor	r3, r12, r12, ror #16");
+	asm("	bic	r3, r3, #16711680");
+	asm("	mov	r3, r3, lsr #8");
+	asm("	eor	r3, r3, r12, ror #8");
+	asm("	b	__decode");
+	asm("__underflow:");
+#ifdef __EABI__
+	asm("	ldr	r3, [r0, #-16]!");	// restore r0 to this
+#else
+	asm("	ldr	r3, [r0], #-16");	// restore r0 to this
+#endif
+	asm("	stmfd sp!, {r0,r1,r2,lr}");
+	// sp is 16 bytes from CFA
+	__EH_FRAME_ADDRESS(sp,16)
+	// The stack looks like this:
+	// CFA-4  -> lr
+	// CFA-8  -> r2
+	// CFA-12 -> r1
+	// CFA-16 -> r0
+	// We saved lr @ CFA-4
+	// Nothing else needs to be restored since there's no barrier here
+	__EH_FRAME_SAVE1(lr,-4)
+	asm("	adr lr, 1f ");
+#ifdef __EABI__
+	asm("	ldr	ip, [r3, #0]");
+#else
+	asm("	ldr	ip, [r3, #8]");
+#endif
+	__JUMP(,ip);
+	asm("1: ");
+	asm("	ldmfd sp!, {r0,r1,r2,lr}");
+	asm("	b __huffman");
+	asm("__fastdecoded:");
+	asm("	add r2, r2, #3");
+	asm("__decoded:");
+#ifdef __EABI__
+	asm("	stmda r0, {r2, r3}");
+#else
+	asm("	stmdb r0, {r2, r3}");
+#endif
+	asm("	mov	r0, r12, lsr #17");
+	__JUMP(,lr);
+	}
+
+#endif
+