Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/libtheora/x86_vc/mmxidct.c
9906 views
1
/********************************************************************
2
* *
3
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
4
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
7
* *
8
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
9
* by the Xiph.Org Foundation and contributors *
10
* https://www.xiph.org/ *
11
* *
12
********************************************************************
13
14
function:
15
16
********************************************************************/
17
18
/*MMX acceleration of Theora's iDCT.
19
Originally written by Rudolf Marek, based on code from On2's VP3.*/
20
#include "x86int.h"
21
#include "../dct.h"
22
23
#if defined(OC_X86_ASM)
24
25
/*These are offsets into the table of constants below.*/
26
/*7 rows of cosines, in order: pi/16 * (1 ... 7).*/
27
#define OC_COSINE_OFFSET (8)
28
/*A row of 8's.*/
29
#define OC_EIGHT_OFFSET (0)
30
31
32
33
/*A table of constants used by the MMX routines.*/
34
static const OC_ALIGN16(ogg_uint16_t) OC_IDCT_CONSTS[(1+7)*4]={
35
8, 8, 8, 8,
36
(ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7,
37
(ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7,
38
(ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6,
39
(ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6,
40
(ogg_uint16_t)OC_C3S5,(ogg_uint16_t)OC_C3S5,
41
(ogg_uint16_t)OC_C3S5,(ogg_uint16_t)OC_C3S5,
42
(ogg_uint16_t)OC_C4S4,(ogg_uint16_t)OC_C4S4,
43
(ogg_uint16_t)OC_C4S4,(ogg_uint16_t)OC_C4S4,
44
(ogg_uint16_t)OC_C5S3,(ogg_uint16_t)OC_C5S3,
45
(ogg_uint16_t)OC_C5S3,(ogg_uint16_t)OC_C5S3,
46
(ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2,
47
(ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2,
48
(ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1,
49
(ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1
50
};
51
52
/*38 cycles*/
53
#define OC_IDCT_BEGIN(_y,_x) __asm{ \
54
__asm movq mm2,OC_I(3,_x) \
55
__asm movq mm6,OC_C(3) \
56
__asm movq mm4,mm2 \
57
__asm movq mm7,OC_J(5,_x) \
58
__asm pmulhw mm4,mm6 \
59
__asm movq mm1,OC_C(5) \
60
__asm pmulhw mm6,mm7 \
61
__asm movq mm5,mm1 \
62
__asm pmulhw mm1,mm2 \
63
__asm movq mm3,OC_I(1,_x) \
64
__asm pmulhw mm5,mm7 \
65
__asm movq mm0,OC_C(1) \
66
__asm paddw mm4,mm2 \
67
__asm paddw mm6,mm7 \
68
__asm paddw mm2,mm1 \
69
__asm movq mm1,OC_J(7,_x) \
70
__asm paddw mm7,mm5 \
71
__asm movq mm5,mm0 \
72
__asm pmulhw mm0,mm3 \
73
__asm paddw mm4,mm7 \
74
__asm pmulhw mm5,mm1 \
75
__asm movq mm7,OC_C(7) \
76
__asm psubw mm6,mm2 \
77
__asm paddw mm0,mm3 \
78
__asm pmulhw mm3,mm7 \
79
__asm movq mm2,OC_I(2,_x) \
80
__asm pmulhw mm7,mm1 \
81
__asm paddw mm5,mm1 \
82
__asm movq mm1,mm2 \
83
__asm pmulhw mm2,OC_C(2) \
84
__asm psubw mm3,mm5 \
85
__asm movq mm5,OC_J(6,_x) \
86
__asm paddw mm0,mm7 \
87
__asm movq mm7,mm5 \
88
__asm psubw mm0,mm4 \
89
__asm pmulhw mm5,OC_C(2) \
90
__asm paddw mm2,mm1 \
91
__asm pmulhw mm1,OC_C(6) \
92
__asm paddw mm4,mm4 \
93
__asm paddw mm4,mm0 \
94
__asm psubw mm3,mm6 \
95
__asm paddw mm5,mm7 \
96
__asm paddw mm6,mm6 \
97
__asm pmulhw mm7,OC_C(6) \
98
__asm paddw mm6,mm3 \
99
__asm movq OC_I(1,_y),mm4 \
100
__asm psubw mm1,mm5 \
101
__asm movq mm4,OC_C(4) \
102
__asm movq mm5,mm3 \
103
__asm pmulhw mm3,mm4 \
104
__asm paddw mm7,mm2 \
105
__asm movq OC_I(2,_y),mm6 \
106
__asm movq mm2,mm0 \
107
__asm movq mm6,OC_I(0,_x) \
108
__asm pmulhw mm0,mm4 \
109
__asm paddw mm5,mm3 \
110
__asm movq mm3,OC_J(4,_x) \
111
__asm psubw mm5,mm1 \
112
__asm paddw mm2,mm0 \
113
__asm psubw mm6,mm3 \
114
__asm movq mm0,mm6 \
115
__asm pmulhw mm6,mm4 \
116
__asm paddw mm3,mm3 \
117
__asm paddw mm1,mm1 \
118
__asm paddw mm3,mm0 \
119
__asm paddw mm1,mm5 \
120
__asm pmulhw mm4,mm3 \
121
__asm paddw mm6,mm0 \
122
__asm psubw mm6,mm2 \
123
__asm paddw mm2,mm2 \
124
__asm movq mm0,OC_I(1,_y) \
125
__asm paddw mm2,mm6 \
126
__asm paddw mm4,mm3 \
127
__asm psubw mm2,mm1 \
128
}
129
130
/*38+8=46 cycles.*/
131
#define OC_ROW_IDCT(_y,_x) __asm{ \
132
OC_IDCT_BEGIN(_y,_x) \
133
/*r3=D'*/ \
134
__asm movq mm3,OC_I(2,_y) \
135
/*r4=E'=E-G*/ \
136
__asm psubw mm4,mm7 \
137
/*r1=H'+H'*/ \
138
__asm paddw mm1,mm1 \
139
/*r7=G+G*/ \
140
__asm paddw mm7,mm7 \
141
/*r1=R1=A''+H'*/ \
142
__asm paddw mm1,mm2 \
143
/*r7=G'=E+G*/ \
144
__asm paddw mm7,mm4 \
145
/*r4=R4=E'-D'*/ \
146
__asm psubw mm4,mm3 \
147
__asm paddw mm3,mm3 \
148
/*r6=R6=F'-B''*/ \
149
__asm psubw mm6,mm5 \
150
__asm paddw mm5,mm5 \
151
/*r3=R3=E'+D'*/ \
152
__asm paddw mm3,mm4 \
153
/*r5=R5=F'+B''*/ \
154
__asm paddw mm5,mm6 \
155
/*r7=R7=G'-C'*/ \
156
__asm psubw mm7,mm0 \
157
__asm paddw mm0,mm0 \
158
/*Save R1.*/ \
159
__asm movq OC_I(1,_y),mm1 \
160
/*r0=R0=G.+C.*/ \
161
__asm paddw mm0,mm7 \
162
}
163
164
/*The following macro does two 4x4 transposes in place.
165
At entry, we assume:
166
r0 = a3 a2 a1 a0
167
I(1) = b3 b2 b1 b0
168
r2 = c3 c2 c1 c0
169
r3 = d3 d2 d1 d0
170
171
r4 = e3 e2 e1 e0
172
r5 = f3 f2 f1 f0
173
r6 = g3 g2 g1 g0
174
r7 = h3 h2 h1 h0
175
176
At exit, we have:
177
I(0) = d0 c0 b0 a0
178
I(1) = d1 c1 b1 a1
179
I(2) = d2 c2 b2 a2
180
I(3) = d3 c3 b3 a3
181
182
J(4) = h0 g0 f0 e0
183
J(5) = h1 g1 f1 e1
184
J(6) = h2 g2 f2 e2
185
J(7) = h3 g3 f3 e3
186
187
I(0) I(1) I(2) I(3) is the transpose of r0 I(1) r2 r3.
188
J(4) J(5) J(6) J(7) is the transpose of r4 r5 r6 r7.
189
190
Since r1 is free at entry, we calculate the Js first.*/
191
/*19 cycles.*/
192
#define OC_TRANSPOSE(_y) __asm{ \
193
__asm movq mm1,mm4 \
194
__asm punpcklwd mm4,mm5 \
195
__asm movq OC_I(0,_y),mm0 \
196
__asm punpckhwd mm1,mm5 \
197
__asm movq mm0,mm6 \
198
__asm punpcklwd mm6,mm7 \
199
__asm movq mm5,mm4 \
200
__asm punpckldq mm4,mm6 \
201
__asm punpckhdq mm5,mm6 \
202
__asm movq mm6,mm1 \
203
__asm movq OC_J(4,_y),mm4 \
204
__asm punpckhwd mm0,mm7 \
205
__asm movq OC_J(5,_y),mm5 \
206
__asm punpckhdq mm6,mm0 \
207
__asm movq mm4,OC_I(0,_y) \
208
__asm punpckldq mm1,mm0 \
209
__asm movq mm5,OC_I(1,_y) \
210
__asm movq mm0,mm4 \
211
__asm movq OC_J(7,_y),mm6 \
212
__asm punpcklwd mm0,mm5 \
213
__asm movq OC_J(6,_y),mm1 \
214
__asm punpckhwd mm4,mm5 \
215
__asm movq mm5,mm2 \
216
__asm punpcklwd mm2,mm3 \
217
__asm movq mm1,mm0 \
218
__asm punpckldq mm0,mm2 \
219
__asm punpckhdq mm1,mm2 \
220
__asm movq mm2,mm4 \
221
__asm movq OC_I(0,_y),mm0 \
222
__asm punpckhwd mm5,mm3 \
223
__asm movq OC_I(1,_y),mm1 \
224
__asm punpckhdq mm4,mm5 \
225
__asm punpckldq mm2,mm5 \
226
__asm movq OC_I(3,_y),mm4 \
227
__asm movq OC_I(2,_y),mm2 \
228
}
229
230
/*38+19=57 cycles.*/
231
#define OC_COLUMN_IDCT(_y) __asm{ \
232
OC_IDCT_BEGIN(_y,_y) \
233
__asm paddw mm2,OC_8 \
234
/*r1=H'+H'*/ \
235
__asm paddw mm1,mm1 \
236
/*r1=R1=A''+H'*/ \
237
__asm paddw mm1,mm2 \
238
/*r2=NR2*/ \
239
__asm psraw mm2,4 \
240
/*r4=E'=E-G*/ \
241
__asm psubw mm4,mm7 \
242
/*r1=NR1*/ \
243
__asm psraw mm1,4 \
244
/*r3=D'*/ \
245
__asm movq mm3,OC_I(2,_y) \
246
/*r7=G+G*/ \
247
__asm paddw mm7,mm7 \
248
/*Store NR2 at I(2).*/ \
249
__asm movq OC_I(2,_y),mm2 \
250
/*r7=G'=E+G*/ \
251
__asm paddw mm7,mm4 \
252
/*Store NR1 at I(1).*/ \
253
__asm movq OC_I(1,_y),mm1 \
254
/*r4=R4=E'-D'*/ \
255
__asm psubw mm4,mm3 \
256
__asm paddw mm4,OC_8 \
257
/*r3=D'+D'*/ \
258
__asm paddw mm3,mm3 \
259
/*r3=R3=E'+D'*/ \
260
__asm paddw mm3,mm4 \
261
/*r4=NR4*/ \
262
__asm psraw mm4,4 \
263
/*r6=R6=F'-B''*/ \
264
__asm psubw mm6,mm5 \
265
/*r3=NR3*/ \
266
__asm psraw mm3,4 \
267
__asm paddw mm6,OC_8 \
268
/*r5=B''+B''*/ \
269
__asm paddw mm5,mm5 \
270
/*r5=R5=F'+B''*/ \
271
__asm paddw mm5,mm6 \
272
/*r6=NR6*/ \
273
__asm psraw mm6,4 \
274
/*Store NR4 at J(4).*/ \
275
__asm movq OC_J(4,_y),mm4 \
276
/*r5=NR5*/ \
277
__asm psraw mm5,4 \
278
/*Store NR3 at I(3).*/ \
279
__asm movq OC_I(3,_y),mm3 \
280
/*r7=R7=G'-C'*/ \
281
__asm psubw mm7,mm0 \
282
__asm paddw mm7,OC_8 \
283
/*r0=C'+C'*/ \
284
__asm paddw mm0,mm0 \
285
/*r0=R0=G'+C'*/ \
286
__asm paddw mm0,mm7 \
287
/*r7=NR7*/ \
288
__asm psraw mm7,4 \
289
/*Store NR6 at J(6).*/ \
290
__asm movq OC_J(6,_y),mm6 \
291
/*r0=NR0*/ \
292
__asm psraw mm0,4 \
293
/*Store NR5 at J(5).*/ \
294
__asm movq OC_J(5,_y),mm5 \
295
/*Store NR7 at J(7).*/ \
296
__asm movq OC_J(7,_y),mm7 \
297
/*Store NR0 at I(0).*/ \
298
__asm movq OC_I(0,_y),mm0 \
299
}
300
301
#define OC_MID(_m,_i) [CONSTS+_m+(_i)*8]
302
#define OC_C(_i) OC_MID(OC_COSINE_OFFSET,_i-1)
303
#define OC_8 OC_MID(OC_EIGHT_OFFSET,0)
304
305
static void oc_idct8x8_slow(ogg_int16_t _y[64],ogg_int16_t _x[64]){
306
int i;
307
/*This routine accepts an 8x8 matrix, but in partially transposed form.
308
Every 4x4 block is transposed.*/
309
__asm{
310
#define CONSTS eax
311
#define Y edx
312
#define X ecx
313
mov CONSTS,offset OC_IDCT_CONSTS
314
mov Y,_y
315
mov X,_x
316
#define OC_I(_k,_y) [(_y)+(_k)*16]
317
#define OC_J(_k,_y) [(_y)+((_k)-4)*16+8]
318
OC_ROW_IDCT(Y,X)
319
OC_TRANSPOSE(Y)
320
#undef OC_I
321
#undef OC_J
322
#define OC_I(_k,_y) [(_y)+(_k)*16+64]
323
#define OC_J(_k,_y) [(_y)+((_k)-4)*16+72]
324
OC_ROW_IDCT(Y,X)
325
OC_TRANSPOSE(Y)
326
#undef OC_I
327
#undef OC_J
328
#define OC_I(_k,_y) [(_y)+(_k)*16]
329
#define OC_J(_k,_y) OC_I(_k,_y)
330
OC_COLUMN_IDCT(Y)
331
#undef OC_I
332
#undef OC_J
333
#define OC_I(_k,_y) [(_y)+(_k)*16+8]
334
#define OC_J(_k,_y) OC_I(_k,_y)
335
OC_COLUMN_IDCT(Y)
336
#undef OC_I
337
#undef OC_J
338
#undef CONSTS
339
#undef Y
340
#undef X
341
}
342
__asm pxor mm0,mm0;
343
for(i=0;i<4;i++){
344
ogg_int16_t *x;
345
x=_x+16*i;
346
#define X ecx
347
__asm{
348
mov X,x
349
movq [X+0x00],mm0
350
movq [X+0x08],mm0
351
movq [X+0x10],mm0
352
movq [X+0x18],mm0
353
}
354
#undef X
355
}
356
}
357
358
/*25 cycles.*/
359
#define OC_IDCT_BEGIN_10(_y,_x) __asm{ \
360
__asm movq mm2,OC_I(3,_x) \
361
__asm nop \
362
__asm movq mm6,OC_C(3) \
363
__asm movq mm4,mm2 \
364
__asm movq mm1,OC_C(5) \
365
__asm pmulhw mm4,mm6 \
366
__asm movq mm3,OC_I(1,_x) \
367
__asm pmulhw mm1,mm2 \
368
__asm movq mm0,OC_C(1) \
369
__asm paddw mm4,mm2 \
370
__asm pxor mm6,mm6 \
371
__asm paddw mm2,mm1 \
372
__asm movq mm5,OC_I(2,_x) \
373
__asm pmulhw mm0,mm3 \
374
__asm movq mm1,mm5 \
375
__asm paddw mm0,mm3 \
376
__asm pmulhw mm3,OC_C(7) \
377
__asm psubw mm6,mm2 \
378
__asm pmulhw mm5,OC_C(2) \
379
__asm psubw mm0,mm4 \
380
__asm movq mm7,OC_I(2,_x) \
381
__asm paddw mm4,mm4 \
382
__asm paddw mm7,mm5 \
383
__asm paddw mm4,mm0 \
384
__asm pmulhw mm1,OC_C(6) \
385
__asm psubw mm3,mm6 \
386
__asm movq OC_I(1,_y),mm4 \
387
__asm paddw mm6,mm6 \
388
__asm movq mm4,OC_C(4) \
389
__asm paddw mm6,mm3 \
390
__asm movq mm5,mm3 \
391
__asm pmulhw mm3,mm4 \
392
__asm movq OC_I(2,_y),mm6 \
393
__asm movq mm2,mm0 \
394
__asm movq mm6,OC_I(0,_x) \
395
__asm pmulhw mm0,mm4 \
396
__asm paddw mm5,mm3 \
397
__asm paddw mm2,mm0 \
398
__asm psubw mm5,mm1 \
399
__asm pmulhw mm6,mm4 \
400
__asm paddw mm6,OC_I(0,_x) \
401
__asm paddw mm1,mm1 \
402
__asm movq mm4,mm6 \
403
__asm paddw mm1,mm5 \
404
__asm psubw mm6,mm2 \
405
__asm paddw mm2,mm2 \
406
__asm movq mm0,OC_I(1,_y) \
407
__asm paddw mm2,mm6 \
408
__asm psubw mm2,mm1 \
409
__asm nop \
410
}
411
412
/*25+8=33 cycles.*/
413
#define OC_ROW_IDCT_10(_y,_x) __asm{ \
414
OC_IDCT_BEGIN_10(_y,_x) \
415
/*r3=D'*/ \
416
__asm movq mm3,OC_I(2,_y) \
417
/*r4=E'=E-G*/ \
418
__asm psubw mm4,mm7 \
419
/*r1=H'+H'*/ \
420
__asm paddw mm1,mm1 \
421
/*r7=G+G*/ \
422
__asm paddw mm7,mm7 \
423
/*r1=R1=A''+H'*/ \
424
__asm paddw mm1,mm2 \
425
/*r7=G'=E+G*/ \
426
__asm paddw mm7,mm4 \
427
/*r4=R4=E'-D'*/ \
428
__asm psubw mm4,mm3 \
429
__asm paddw mm3,mm3 \
430
/*r6=R6=F'-B''*/ \
431
__asm psubw mm6,mm5 \
432
__asm paddw mm5,mm5 \
433
/*r3=R3=E'+D'*/ \
434
__asm paddw mm3,mm4 \
435
/*r5=R5=F'+B''*/ \
436
__asm paddw mm5,mm6 \
437
/*r7=R7=G'-C'*/ \
438
__asm psubw mm7,mm0 \
439
__asm paddw mm0,mm0 \
440
/*Save R1.*/ \
441
__asm movq OC_I(1,_y),mm1 \
442
/*r0=R0=G'+C'*/ \
443
__asm paddw mm0,mm7 \
444
}
445
446
/*25+19=44 cycles'*/
447
#define OC_COLUMN_IDCT_10(_y) __asm{ \
448
OC_IDCT_BEGIN_10(_y,_y) \
449
__asm paddw mm2,OC_8 \
450
/*r1=H'+H'*/ \
451
__asm paddw mm1,mm1 \
452
/*r1=R1=A''+H'*/ \
453
__asm paddw mm1,mm2 \
454
/*r2=NR2*/ \
455
__asm psraw mm2,4 \
456
/*r4=E'=E-G*/ \
457
__asm psubw mm4,mm7 \
458
/*r1=NR1*/ \
459
__asm psraw mm1,4 \
460
/*r3=D'*/ \
461
__asm movq mm3,OC_I(2,_y) \
462
/*r7=G+G*/ \
463
__asm paddw mm7,mm7 \
464
/*Store NR2 at I(2).*/ \
465
__asm movq OC_I(2,_y),mm2 \
466
/*r7=G'=E+G*/ \
467
__asm paddw mm7,mm4 \
468
/*Store NR1 at I(1).*/ \
469
__asm movq OC_I(1,_y),mm1 \
470
/*r4=R4=E'-D'*/ \
471
__asm psubw mm4,mm3 \
472
__asm paddw mm4,OC_8 \
473
/*r3=D'+D'*/ \
474
__asm paddw mm3,mm3 \
475
/*r3=R3=E'+D'*/ \
476
__asm paddw mm3,mm4 \
477
/*r4=NR4*/ \
478
__asm psraw mm4,4 \
479
/*r6=R6=F'-B''*/ \
480
__asm psubw mm6,mm5 \
481
/*r3=NR3*/ \
482
__asm psraw mm3,4 \
483
__asm paddw mm6,OC_8 \
484
/*r5=B''+B''*/ \
485
__asm paddw mm5,mm5 \
486
/*r5=R5=F'+B''*/ \
487
__asm paddw mm5,mm6 \
488
/*r6=NR6*/ \
489
__asm psraw mm6,4 \
490
/*Store NR4 at J(4).*/ \
491
__asm movq OC_J(4,_y),mm4 \
492
/*r5=NR5*/ \
493
__asm psraw mm5,4 \
494
/*Store NR3 at I(3).*/ \
495
__asm movq OC_I(3,_y),mm3 \
496
/*r7=R7=G'-C'*/ \
497
__asm psubw mm7,mm0 \
498
__asm paddw mm7,OC_8 \
499
/*r0=C'+C'*/ \
500
__asm paddw mm0,mm0 \
501
/*r0=R0=G'+C'*/ \
502
__asm paddw mm0,mm7 \
503
/*r7=NR7*/ \
504
__asm psraw mm7,4 \
505
/*Store NR6 at J(6).*/ \
506
__asm movq OC_J(6,_y),mm6 \
507
/*r0=NR0*/ \
508
__asm psraw mm0,4 \
509
/*Store NR5 at J(5).*/ \
510
__asm movq OC_J(5,_y),mm5 \
511
/*Store NR7 at J(7).*/ \
512
__asm movq OC_J(7,_y),mm7 \
513
/*Store NR0 at I(0).*/ \
514
__asm movq OC_I(0,_y),mm0 \
515
}
516
517
static void oc_idct8x8_10(ogg_int16_t _y[64],ogg_int16_t _x[64]){
518
__asm{
519
#define CONSTS eax
520
#define Y edx
521
#define X ecx
522
mov CONSTS,offset OC_IDCT_CONSTS
523
mov Y,_y
524
mov X,_x
525
#define OC_I(_k,_y) [(_y)+(_k)*16]
526
#define OC_J(_k,_y) [(_y)+((_k)-4)*16+8]
527
/*Done with dequant, descramble, and partial transpose.
528
Now do the iDCT itself.*/
529
OC_ROW_IDCT_10(Y,X)
530
OC_TRANSPOSE(Y)
531
#undef OC_I
532
#undef OC_J
533
#define OC_I(_k,_y) [(_y)+(_k)*16]
534
#define OC_J(_k,_y) OC_I(_k,_y)
535
OC_COLUMN_IDCT_10(Y)
536
#undef OC_I
537
#undef OC_J
538
#define OC_I(_k,_y) [(_y)+(_k)*16+8]
539
#define OC_J(_k,_y) OC_I(_k,_y)
540
OC_COLUMN_IDCT_10(Y)
541
#undef OC_I
542
#undef OC_J
543
#undef CONSTS
544
#undef Y
545
#undef X
546
}
547
#define X ecx
548
__asm{
549
pxor mm0,mm0;
550
mov X,_x
551
movq [X+0x00],mm0
552
movq [X+0x10],mm0
553
movq [X+0x20],mm0
554
movq [X+0x30],mm0
555
}
556
#undef X
557
}
558
559
/*Performs an inverse 8x8 Type-II DCT transform.
560
The input is assumed to be scaled by a factor of 4 relative to orthonormal
561
version of the transform.*/
562
void oc_idct8x8_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi){
563
/*_last_zzi is subtly different from an actual count of the number of
564
coefficients we decoded for this block.
565
It contains the value of zzi BEFORE the final token in the block was
566
decoded.
567
In most cases this is an EOB token (the continuation of an EOB run from a
568
previous block counts), and so this is the same as the coefficient count.
569
However, in the case that the last token was NOT an EOB token, but filled
570
the block up with exactly 64 coefficients, _last_zzi will be less than 64.
571
Provided the last token was not a pure zero run, the minimum value it can
572
be is 46, and so that doesn't affect any of the cases in this routine.
573
However, if the last token WAS a pure zero run of length 63, then _last_zzi
574
will be 1 while the number of coefficients decoded is 64.
575
Thus, we will trigger the following special case, where the real
576
coefficient count would not.
577
Note also that a zero run of length 64 will give _last_zzi a value of 0,
578
but we still process the DC coefficient, which might have a non-zero value
579
due to DC prediction.
580
Although convoluted, this is arguably the correct behavior: it allows us to
581
use a smaller transform when the block ends with a long zero run instead
582
of a normal EOB token.
583
It could be smarter... multiple separate zero runs at the end of a block
584
will fool it, but an encoder that generates these really deserves what it
585
gets.
586
Needless to say we inherited this approach from VP3.*/
587
/*Perform the iDCT.*/
588
if(_last_zzi<=10)oc_idct8x8_10(_y,_x);
589
else oc_idct8x8_slow(_y,_x);
590
}
591
592
#endif
593
594