diff -r 000000000000 -r a41df078684a kernel/eka/euser/epoc/arm/uc_huffman.cia --- /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 + +#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 +