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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\euser\epoc\arm\uc_huffman.cia
18 #include "e32huffman.h"
21 #ifdef __HUFFMAN_MACHINE_CODED__
23 // NB The EABI layout of TBitInput is different from GCC. Its vtbl is at
24 // offset 0 rather than offset 16
26 EXPORT_C __NAKED__ TUint TBitInput::ReadL()
27 /** Read a single bit from the input
29 Return the next bit in the input stream. This will call UnderflowL() if
30 there are no more bits available.
32 @return The next bit in the stream
34 @leave "UnderflowL()" It the bit stream is exhausted more UnderflowL is called
40 asm("ldmib r0!, {r2,r3}");
42 asm("ldmia r0!, {r2,r3}");
45 asm("subs r2, r2, #1");
46 asm("movpl r12, r3, asl #1");
48 asm("stmplda r0, {r2,r12}");
50 asm("stmpldb r0, {r2,r12}");
52 asm("movpl r0, r3, lsr #31");
55 asm("b __readmorebits"); // r2==-1, r12==0 -> so all set
58 EXPORT_C __NAKED__ TUint TBitInput::ReadL(TInt aSize)
59 /** Read a multi-bit value from the input
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.
65 A read of zero bits will always reaturn zero.
67 This will call UnderflowL() if there are not enough bits available.
69 @param "TInt aSize" The number of bits to read
71 @return The bits read from the stream
73 @leave "UnderflowL()" It the bit stream is exhausted more UnderflowL is called
79 asm(" ldmib r0!, {r2,r3}");
81 asm(" ldmia r0!, {r2,r3}");
83 asm(" subs r2, r2, r1");
84 asm(" movpl r12, r3, asl r1");
86 asm(" stmplda r0, {r2,r12}");
88 asm(" stmpldb r0, {r2,r12}");
90 asm(" rsb r1, r1, #32");
91 asm(" movpl r0, r3, lsr r1");
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:");
100 asm(" stmfd sp!, {r12,lr}");
103 asm(" ldmib r0!, {r1,r14}"); // r1=remain, r14=ptr
105 asm(" ldmia r0!, {r1,r14}"); // r1=remain, r14=ptr
109 asm(" ble __readunderflow");
110 asm(" ldr r12, [r14], #4");
111 asm(" subs r3, r1, #32");
113 asm(" stmda r0!, {r3,r14}");
115 asm(" stmdb r0!, {r3,r14}");
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
126 asm(" bmi __readgoroundagain");
127 asm("__readhavebits:");
128 asm(" rsb r12, r2, #0");
129 asm(" mov r12, r3, asl r12");
131 asm(" stmda r0, {r1,r12}");
133 asm(" stmdb r0, {r1,r12}");
135 asm(" ldmfd sp!, {r12,lr}");
136 asm(" add r2, r2, #32");
137 asm(" orr r0, r12, r3, lsr r2");
139 asm("__readunderflow:");
141 asm(" ldr r3, [r0, #-16]!"); // restore r0 to this
143 asm(" ldr r3, [r0], #-16"); // restore r0 to this
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
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)
158 asm(" ldr ip, [r3, #0]");
160 asm(" ldr ip, [r3, #8]");
164 asm(" ldmfd sp!, {r0,r2}");
166 asm(" ldmib r0!, {r1,r3}"); // r1=count, r3=bits
168 asm(" ldmia r0!, {r1,r3}"); // r1=count, r3=bits
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");
184 EXPORT_C __NAKED__ TUint TBitInput::HuffmanL(const TUint32* aTree)
185 /** Read and decode a Huffman Code
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().
190 @param "const TUint32* aTree" The huffman decoding tree
192 @return The symbol that was decoded
194 @leave "UnderflowL()" It the bit stream is exhausted more UnderflowL is called
201 asm(" ldmib r0!, {r2,r3}");
203 asm(" ldmia r0!, {r2,r3}");
206 asm(" ldr r12, [r1]");
207 asm(" subs r2, r2, #4");
208 asm(" bmi __fewbits");
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");
236 asm(" adds r2, r2, #3");
237 asm(" bmi __nobits");
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");
247 // r0=this, r1=tree, r2=count (-1), r3=bits (0), r12=node=*tree
248 // must preserve r0,r1
250 asm(" ldmib r0!, {r2,r3}"); // r2=remain, r3=ptr
252 asm(" ldmia r0!, {r2,r3}"); // r2=remain, r3=ptr
255 asm(" ble __underflow");
256 asm(" ldr r12, [r3], #4");
257 asm(" subs r2, r2, #32");
259 asm(" stmda r0!, {r2,r3}");
261 asm(" stmdb r0!, {r2,r3}");
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");
272 asm(" ldr r3, [r0, #-16]!"); // restore r0 to this
274 asm(" ldr r3, [r0], #-16"); // restore r0 to this
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:
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)
289 asm(" ldr ip, [r3, #0]");
291 asm(" ldr ip, [r3, #8]");
295 asm(" ldmfd sp!, {r0,r1,r2,lr}");
297 asm("__fastdecoded:");
298 asm(" add r2, r2, #3");
301 asm(" stmda r0, {r2, r3}");
303 asm(" stmdb r0, {r2, r3}");
305 asm(" mov r0, r12, lsr #17");