4 #include "gstgetbits.h"
6 /* Defined in gstgetbits_i386.s */
7 extern unsigned long _gst_get1bit_i386(gst_getbits_t *gb, unsigned long bits);
8 extern unsigned long _gst_getbits_i386(gst_getbits_t *gb, unsigned long bits);
9 extern unsigned long _gst_getbits_fast_i386(gst_getbits_t *gb, unsigned long bits);
10 extern unsigned long _gst_showbits_i386(gst_getbits_t *gb, unsigned long bits);
11 extern void _gst_flushbits_i386(gst_getbits_t *gb, unsigned long bits);
12 extern void _gst_getbits_back_i386(gst_getbits_t *gb, unsigned long bits);
14 /* Defined in gstgetbits_generic.c */
15 extern unsigned long _gst_getbits_int_cb(gst_getbits_t *gb, unsigned long bits);
16 extern unsigned long _gst_get1bit_int(gst_getbits_t *gb, unsigned long bits);
17 extern unsigned long _gst_getbits_int(gst_getbits_t *gb, unsigned long bits);
18 extern unsigned long _gst_getbits_fast_int(gst_getbits_t *gb, unsigned long bits);
19 extern unsigned long _gst_showbits_int(gst_getbits_t *gb, unsigned long bits);
20 extern void _gst_flushbits_int(gst_getbits_t *gb, unsigned long bits);
21 extern void _gst_getbits_back_int(gst_getbits_t *gb, unsigned long bits);
24 unsigned long gst_getbits_nBitMask[] = {
25 0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
26 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
27 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
28 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
29 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
30 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
31 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
32 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe};
34 unsigned long _getbits_masks[] = {
36 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
37 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
38 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
39 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
40 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
41 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
42 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
43 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff,
47 unsigned long _getbits_64_minus_index[] = {
48 64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,
49 40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,
50 16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1 };
52 /* this routine taken from Intel AppNote AP-527:
53 "Using MMX[tm] Instructions to Get Bits From a Data Stream"
54 written in C with libmmx to *closely* mimic Intel's ASM implementation
56 this isn't as cycle-efficient, due to the simple fact that I must call
57 emms() at the end. all state must be kept in *gb, not in registers */
58 unsigned long _gst_getbits_mmx(gst_getbits_t *gb,unsigned long bits) {
59 signed long remaining;
62 /* NOTE: this is a code-size optimization Intel seems to have missed!
63 according to the MMX Programmer's Reference Manual, Chapter 5,
64 neither movd nor movq have any effect on the flags. that means you
65 can put them before the sub and jl in their code, which I've done
66 symbolically in this C code. gcc is probably going to lose horribly,
67 I'll do an inline asm version later. I've a point to prove ;-) */
68 /* find the right shift value, put it in mm3 */
69 movd_m2r(_getbits_64_minus_index[bits],mm3);
70 /* load the current quadword into mm0 */
71 movq_m2r(gb->qword,mm0);
75 remaining = gb->bits - bits;
78 unsigned long dword1,dword2;
80 /* shift the pointer by 64 bits (8 bytes) */
82 /* add 64 to bits remaining, to bring it positive */
85 /* grab the first 32 bits from the buffer and swap them around */
86 dword1 = swab32(*(gb->ptr-8));
87 /* grab the second 32 bits, swap */
88 dword2 = swab32(*(gb->ptr-4));
90 /* put second dword in mm4 */
92 /* shift mm2 over to make room for new bits */
95 /* put first dword in mm1 */
97 /* shift second dword up 32 bits */
100 /* put the shift counter in mm3 */
101 movd_m2r(remaining,mm3);
102 /* combine the swapped data in mm4 */
105 /* save off the bits in mm4 to mm0 */
107 /* get the new low-order bits in mm4, shifted by 'mm3' */
110 /* save off new remaining bits */
111 gb->bits = remaining;
112 /* combine bits into mm2 */
115 /* save off the result */
116 movd_r2m(mm2,result);
117 /* get rid of the bits we just read */
121 movq_r2m(mm0,gb->qword);
123 /* finished with MMX */
126 /* we have what we came for */
129 /* load the number of bits requested into mm1 */
131 /* shift the quadword in mm2 by 'mm3' bits */
134 /* update the number of valid bits */
135 gb->bits = remaining;
137 /* save off the remaining bits */
138 movd_r2m(mm2,result);
139 /* discard those bits in mm0 */
143 movq_r2m(mm0,gb->qword);
144 /* finished with MMX */
147 /* we have what we came for */
151 #endif /* HAVE_LIBMMX */
153 unsigned long _gst_getbyte(gst_getbits_t *gb, unsigned long bits) {
157 /* initialize the getbits structure with the proper getbits func */
158 void gst_getbits_init(gst_getbits_t *gb, GstGetbitsCallback callback, void *data) {
161 gb->callback = callback;
166 gb->getbits = _gst_getbits_mmx;
167 // gb->backbits = _gst_getbits_back_mmx;
168 // gb->backbytes = _gst_getbits_byteback_mmx;
169 // printf("gstgetbits: using MMX optimized versions\n");
171 #endif /* HAVE_LIBMMX */
174 gb->getbits = _gst_getbits_int_cb;
175 gb->showbits = _gst_showbits_int;
176 gb->flushbits = _gst_flushbits_int;
177 gb->backbits = _gst_getbits_back_int;
178 // printf("gstgetbits: using callback versions\n");
182 gb->get1bit = _gst_get1bit_i386;
183 gb->getbits = _gst_getbits_i386;
184 gb->getbits_fast = _gst_getbits_fast_i386;
185 gb->getbyte = _gst_getbyte;
186 gb->show1bit = _gst_showbits_i386;
187 gb->showbits = _gst_showbits_i386;
188 gb->flushbits = _gst_flushbits_i386;
189 gb->backbits = _gst_getbits_back_i386;
190 // printf("gstgetbits: using i386 optimized versions\n");
192 gb->get1bit = _gst_get1bit_int;
193 gb->getbits = _gst_getbits_int;
194 gb->getbits_fast = _gst_getbits_fast_int;
195 gb->getbyte = _gst_getbyte;
196 gb->show1bit = _gst_showbits_int;
197 gb->showbits = _gst_showbits_int;
198 gb->flushbits = _gst_flushbits_int;
199 gb->backbits = _gst_getbits_back_int;
200 // printf("gstgetbits: using normal versions\n");
206 /* set up the getbits structure with a new buffer */
207 void gst_getbits_newbuf(gst_getbits_t *gb,unsigned char *buffer, unsigned long len) {
209 gb->endptr = buffer+len;
213 #endif /* HAVE_LIBMMX */