[svn] / trunk / xvidcore / src / quant / x86_asm / quantize_mpeg_mmx.asm Repository:
ViewVC logotype

Annotation of /trunk/xvidcore/src/quant/x86_asm/quantize_mpeg_mmx.asm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1877 - (view) (download)

1 : edgomez 1382 ;/**************************************************************************
2 :     ; *
3 :     ; * XVID MPEG-4 VIDEO CODEC
4 :     ; * - 3dne Quantization/Dequantization -
5 :     ; *
6 :     ; * Copyright (C) 2002-2003 Peter Ross <pross@xvid.org>
7 : Isibaar 1795 ; * 2002-2008 Michael Militzer <michael@xvid.org>
8 : edgomez 1382 ; * 2002-2003 Pascal Massimino <skal@planet-d.net>
9 :     ; *
10 :     ; * This program is free software ; you can redistribute it and/or modify
11 :     ; * it under the terms of the GNU General Public License as published by
12 :     ; * the Free Software Foundation ; either version 2 of the License, or
13 :     ; * (at your option) any later version.
14 :     ; *
15 :     ; * This program is distributed in the hope that it will be useful,
16 :     ; * but WITHOUT ANY WARRANTY ; without even the implied warranty of
17 :     ; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 :     ; * GNU General Public License for more details.
19 :     ; *
20 :     ; * You should have received a copy of the GNU General Public License
21 :     ; * along with this program ; if not, write to the Free Software
22 :     ; * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 :     ; *
24 : Isibaar 1877 ; * $Id: quantize_mpeg_mmx.asm,v 1.16 2009-09-16 17:07:58 Isibaar Exp $
25 : edgomez 1382 ; *
26 :     ; *************************************************************************/
27 :    
28 :     %define SATURATE
29 :    
30 : Isibaar 1795 %include "nasm.inc"
31 : edgomez 1382
32 :     ;=============================================================================
33 :     ; Local data (Read Only)
34 :     ;=============================================================================
35 :    
36 : Isibaar 1795 DATA
37 : edgomez 1382
38 :     mmx_one:
39 :     times 4 dw 1
40 :    
41 :     ;-----------------------------------------------------------------------------
42 :     ; divide by 2Q table
43 :     ;-----------------------------------------------------------------------------
44 :    
45 : Isibaar 1795 ALIGN SECTION_ALIGN
46 : edgomez 1382 mmx_div:
47 :     times 4 dw 65535 ; the div by 2 formula will overflow for the case
48 :     ; quant=1 but we don't care much because quant=1
49 :     ; is handled by a different piece of code that
50 :     ; doesn't use this table.
51 :     %assign quant 2
52 :     %rep 30
53 :     times 4 dw (1<<17) / (quant*2) + 1
54 :     %assign quant quant+1
55 :     %endrep
56 :    
57 :     %define VM18P 3
58 :     %define VM18Q 4
59 :    
60 :    
61 :     ;-----------------------------------------------------------------------------
62 :     ; quantd table
63 :     ;-----------------------------------------------------------------------------
64 :    
65 :     quantd:
66 :     %assign quant 1
67 :     %rep 31
68 :     times 4 dw ((VM18P*quant) + (VM18Q/2)) / VM18Q
69 :     %assign quant quant+1
70 :     %endrep
71 :    
72 :     ;-----------------------------------------------------------------------------
73 :     ; multiple by 2Q table
74 :     ;-----------------------------------------------------------------------------
75 :    
76 :     mmx_mul_quant:
77 :     %assign quant 1
78 :     %rep 31
79 :     times 4 dw quant
80 :     %assign quant quant+1
81 :     %endrep
82 :    
83 :     ;-----------------------------------------------------------------------------
84 :     ; saturation limits
85 :     ;-----------------------------------------------------------------------------
86 :    
87 : Isibaar 1795 ALIGN SECTION_ALIGN
88 : edgomez 1382
89 :     mmx_32767_minus_2047:
90 :     times 4 dw (32767-2047)
91 :     mmx_32768_minus_2048:
92 :     times 4 dw (32768-2048)
93 :     mmx_2047:
94 :     times 4 dw 2047
95 :     mmx_minus_2048:
96 :     times 4 dw (-2048)
97 :     zero:
98 :     times 4 dw 0
99 :    
100 :     ;=============================================================================
101 : syskin 1713 ; rounding
102 :     ;=============================================================================
103 :    
104 : Isibaar 1795 ALIGN SECTION_ALIGN
105 :    
106 : syskin 1713 mmx_rounding:
107 : Isibaar 1795 dd (1<<13)
108 :     dd (1<<13)
109 : syskin 1713
110 :     ;=============================================================================
111 : edgomez 1382 ; Code
112 :     ;=============================================================================
113 :    
114 : Isibaar 1844 TEXT
115 : edgomez 1382
116 :     cglobal quant_mpeg_intra_mmx
117 :     cglobal quant_mpeg_inter_mmx
118 :     cglobal dequant_mpeg_intra_mmx
119 :     cglobal dequant_mpeg_inter_mmx
120 :    
121 : syskin 1713
122 :     %macro QUANT_MMX 1
123 : Isibaar 1795 movq mm0, [_EAX + 16*(%1)] ; data
124 :     movq mm2, [TMP0 + 16*(%1) + 128] ; intra_matrix_rec
125 :     movq mm4, [_EAX + 16*(%1) + 8] ; data
126 :     movq mm6, [TMP0 + 16*(%1) + 128 + 8] ; intra_matrix_rec
127 : syskin 1713
128 :     movq mm1, mm0
129 :     movq mm5, mm4
130 :    
131 :     pmullw mm0, mm2 ; low results
132 :     pmulhw mm1, mm2 ; high results
133 :     pmullw mm4, mm6 ; low results
134 :     pmulhw mm5, mm6 ; high results
135 :    
136 :     movq mm2, mm0
137 :     movq mm6, mm4
138 :    
139 :     punpckhwd mm0, mm1
140 :     punpcklwd mm2, mm1
141 :     punpckhwd mm4, mm5
142 :     punpcklwd mm6, mm5
143 :    
144 :     paddd mm2, mm7
145 :     paddd mm0, mm7
146 :     paddd mm6, mm7
147 :     paddd mm4, mm7
148 :    
149 :     psrad mm2, 14
150 :     psrad mm0, 14
151 :     psrad mm6, 14
152 :     psrad mm4, 14
153 :    
154 :     packssdw mm2, mm0
155 :     packssdw mm6, mm4
156 :    
157 : Isibaar 1795 movq [TMP1 + 16*(%1)], mm2
158 :     movq [TMP1 + 16*(%1)+8], mm6
159 : syskin 1713 %endmacro
160 :    
161 : edgomez 1382 ;-----------------------------------------------------------------------------
162 :     ;
163 :     ; uint32_t quant_mpeg_intra_mmx(int16_t * coeff,
164 :     ; const int16_t const * data,
165 :     ; const uint32_t quant,
166 :     ; const uint32_t dcscalar,
167 :     ; const uint16_t *mpeg_matrices);
168 :     ;
169 :     ;-----------------------------------------------------------------------------
170 :    
171 : Isibaar 1795 ALIGN SECTION_ALIGN
172 : edgomez 1382 quant_mpeg_intra_mmx:
173 :    
174 : Isibaar 1795 mov _EAX, prm2 ; data
175 :     mov TMP0, prm5 ; mpeg_quant_matrices
176 :     mov TMP1, prm1 ; coeff
177 :    
178 : syskin 1713 movq mm7, [mmx_rounding]
179 : edgomez 1382
180 : Isibaar 1798 QUANT_MMX(0)
181 :     QUANT_MMX(1)
182 :     QUANT_MMX(2)
183 :     QUANT_MMX(3)
184 :     QUANT_MMX(4)
185 :     QUANT_MMX(5)
186 :     QUANT_MMX(6)
187 :     QUANT_MMX(7)
188 : edgomez 1382
189 : syskin 1713 ; calculate DC
190 : Isibaar 1845 movsx _EAX, word [_EAX] ; data[0]
191 :     mov TMP0, prm4 ; dcscalar
192 : Isibaar 1798 mov _EDX, _EAX
193 : Isibaar 1845 shr TMP0, 1 ; TMP0 = dcscalar/2
194 :     sar _EDX, 31 ; TMP1 = sign extend of _EAX (ready for division too)
195 :    
196 :     xor TMP0, _EDX ; adjust TMP0 according to the sign of data[0]
197 : Isibaar 1798 sub TMP0, _EDX
198 :     add _EAX, TMP0
199 : syskin 1713
200 : Isibaar 1798 mov TMP0, prm4 ; dcscalar
201 :     idiv TMP0 ; _EAX = _EDX:_EAX / dcscalar
202 : edgomez 1382
203 : Isibaar 1798 mov _EDX, prm1 ; coeff again
204 :     mov word [_EDX], ax ; coeff[0] = ax
205 : Isibaar 1795
206 :     xor _EAX, _EAX ; return(0);
207 : edgomez 1382 ret
208 : Isibaar 1793 ENDFUNC
209 : edgomez 1382
210 :    
211 :     ;-----------------------------------------------------------------------------
212 :     ;
213 :     ; uint32_t quant_mpeg_inter_mmx(int16_t * coeff,
214 :     ; const int16_t const * data,
215 :     ; const uint32_t quant,
216 :     ; const uint16_t *mpeg_matrices);
217 :     ;
218 :     ;-----------------------------------------------------------------------------
219 :    
220 : Isibaar 1795 ALIGN SECTION_ALIGN
221 : edgomez 1382 quant_mpeg_inter_mmx:
222 :    
223 : Isibaar 1795 mov TMP1, prm1 ; coeff
224 :     mov _EAX, prm3 ; quant
225 :     mov TMP0, prm4 ; mpeg_quant_matrices
226 : edgomez 1382
227 : Isibaar 1795 push _ESI
228 :     %ifdef ARCH_IS_X86_64
229 :     mov _ESI, prm2 ; data
230 :     %else
231 :     mov _ESI, [_ESP + 4 + 8] ; data
232 :     %endif
233 : edgomez 1382
234 : Isibaar 1795 push _EBX
235 :     xor _EBX, _EBX
236 : edgomez 1382
237 :     pxor mm5, mm5 ; sum
238 :    
239 :     cmp al, 1
240 :     jz near .q1loop
241 :    
242 :     cmp al, 2
243 :     jz near .q2loop
244 :    
245 : Isibaar 1795 %ifdef ARCH_IS_X86_64
246 :     lea r9, [mmx_div]
247 :     movq mm7, [r9 + _EAX * 8 - 8]
248 :     %else
249 :     movq mm7, [mmx_div + _EAX * 8 - 8] ; divider
250 :     %endif
251 : edgomez 1382
252 : Isibaar 1795 ALIGN SECTION_ALIGN
253 : Isibaar 1793 .loop:
254 : Isibaar 1795 movq mm0, [_ESI + 8*_EBX] ; mm0 = [1st]
255 :     movq mm3, [_ESI + 8*_EBX + 8] ;
256 : edgomez 1382 pxor mm1, mm1 ; mm1 = 0
257 :     pxor mm4, mm4 ;
258 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
259 :     pcmpgtw mm4, mm3 ;
260 :     pxor mm0, mm1 ; mm0 = |mm0|
261 :     pxor mm3, mm4 ;
262 :     psubw mm0, mm1 ; displace
263 :     psubw mm3, mm4 ;
264 :     psllw mm0, 4
265 :     psllw mm3, 4
266 : Isibaar 1795 movq mm2, [TMP0 + 512 + 8*_EBX]
267 : edgomez 1382 psrlw mm2, 1
268 :     paddw mm0, mm2
269 : Isibaar 1795 movq mm2, [TMP0 + 768 + _EBX*8]
270 : edgomez 1382 pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
271 : Isibaar 1795 movq mm2, [TMP0 + 512 + 8*_EBX + 8]
272 : edgomez 1382 psrlw mm2, 1
273 :     paddw mm3, mm2
274 : Isibaar 1795 movq mm2, [TMP0 + 768 + _EBX*8 + 8]
275 : edgomez 1382 pmulhw mm3, mm2
276 :     pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16
277 :     pmulhw mm3, mm7 ;
278 :     psrlw mm0, 1 ; additional shift by 1 => 16 + 1 = 17
279 :     psrlw mm3, 1
280 :     paddw mm5, mm0 ; sum += mm0
281 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
282 :     paddw mm5, mm3 ;
283 :     pxor mm3, mm4 ;
284 :     psubw mm0, mm1 ; undisplace
285 :     psubw mm3, mm4
286 : Isibaar 1795 movq [TMP1 + 8*_EBX], mm0
287 :     movq [TMP1 + 8*_EBX + 8], mm3
288 : edgomez 1382
289 : Isibaar 1795 add _EBX, 2
290 :     cmp _EBX, 16
291 : edgomez 1382 jnz near .loop
292 :    
293 : Isibaar 1793 .done:
294 : edgomez 1382 pmaddwd mm5, [mmx_one]
295 :     movq mm0, mm5
296 :     psrlq mm5, 32
297 :     paddd mm0, mm5
298 :     movd eax, mm0 ; return sum
299 :    
300 : Isibaar 1795 pop _EBX
301 :     pop _ESI
302 : edgomez 1382
303 :     ret
304 :    
305 : Isibaar 1795 ALIGN SECTION_ALIGN
306 : Isibaar 1793 .q1loop:
307 : Isibaar 1795 movq mm0, [_ESI + 8*_EBX] ; mm0 = [1st]
308 :     movq mm3, [_ESI + 8*_EBX+ 8]
309 : edgomez 1382 pxor mm1, mm1 ; mm1 = 0
310 :     pxor mm4, mm4 ;
311 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
312 :     pcmpgtw mm4, mm3 ;
313 :     pxor mm0, mm1 ; mm0 = |mm0|
314 :     pxor mm3, mm4 ;
315 :     psubw mm0, mm1 ; displace
316 :     psubw mm3, mm4 ;
317 :     psllw mm0, 4
318 :     psllw mm3, 4
319 : Isibaar 1795 movq mm2, [TMP0 + 512 + 8*_EBX]
320 : edgomez 1382 psrlw mm2, 1
321 :     paddw mm0, mm2
322 : Isibaar 1795 movq mm2, [TMP0 + 768 + _EBX*8]
323 : edgomez 1382 pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
324 : Isibaar 1795 movq mm2, [TMP0 + 512 + 8*_EBX + 8]
325 : edgomez 1382 psrlw mm2, 1
326 :     paddw mm3, mm2
327 : Isibaar 1795 movq mm2, [TMP0 + 768 + _EBX*8 + 8]
328 : edgomez 1382 pmulhw mm3, mm2
329 :     psrlw mm0, 1 ; mm0 >>= 1 (/2)
330 :     psrlw mm3, 1 ;
331 :     paddw mm5, mm0 ; sum += mm0
332 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
333 :     paddw mm5, mm3 ;
334 :     pxor mm3, mm4 ;
335 :     psubw mm0, mm1 ; undisplace
336 :     psubw mm3, mm4
337 : Isibaar 1795 movq [TMP1 + 8*_EBX], mm0
338 :     movq [TMP1 + 8*_EBX + 8], mm3
339 : edgomez 1382
340 : Isibaar 1795 add _EBX, 2
341 :     cmp _EBX, 16
342 : edgomez 1382 jnz near .q1loop
343 :    
344 :     jmp .done
345 :    
346 : Isibaar 1795 ALIGN SECTION_ALIGN
347 : Isibaar 1793 .q2loop:
348 : Isibaar 1795 movq mm0, [_ESI + 8*_EBX] ; mm0 = [1st]
349 :     movq mm3, [_ESI + 8*_EBX+ 8]
350 : edgomez 1382 pxor mm1, mm1 ; mm1 = 0
351 :     pxor mm4, mm4 ;
352 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
353 :     pcmpgtw mm4, mm3 ;
354 :     pxor mm0, mm1 ; mm0 = |mm0|
355 :     pxor mm3, mm4 ;
356 :     psubw mm0, mm1 ; displace
357 :     psubw mm3, mm4 ;
358 :     psllw mm0, 4
359 :     psllw mm3, 4
360 : Isibaar 1795 movq mm2, [TMP0 + 512 + 8*_EBX]
361 : edgomez 1382 psrlw mm2, 1
362 :     paddw mm0, mm2
363 : Isibaar 1795 movq mm2, [TMP0 + 768 + _EBX*8]
364 : edgomez 1382 pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
365 : Isibaar 1795 movq mm2, [TMP0 + 512 + 8*_EBX + 8]
366 : edgomez 1382 psrlw mm2, 1
367 :     paddw mm3, mm2
368 : Isibaar 1795 movq mm2, [TMP0 + 768 + _EBX*8 + 8]
369 : edgomez 1382 pmulhw mm3, mm2
370 :     psrlw mm0, 2 ; mm0 >>= 1 (/2)
371 :     psrlw mm3, 2 ;
372 :     paddw mm5, mm0 ; sum += mm0
373 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
374 :     paddw mm5, mm3 ;
375 :     pxor mm3, mm4 ;
376 :     psubw mm0, mm1 ; undisplace
377 :     psubw mm3, mm4
378 : Isibaar 1795 movq [TMP1 + 8*_EBX], mm0
379 :     movq [TMP1 + 8*_EBX + 8], mm3
380 : edgomez 1382
381 : Isibaar 1795 add _EBX, 2
382 :     cmp _EBX, 16
383 : edgomez 1382 jnz near .q2loop
384 :    
385 :     jmp .done
386 : Isibaar 1793 ENDFUNC
387 : edgomez 1382
388 :    
389 :     ;-----------------------------------------------------------------------------
390 :     ;
391 :     ; uint32_t dequant_mpeg_intra_mmx(int16_t *data,
392 :     ; const int16_t const *coeff,
393 :     ; const uint32_t quant,
394 :     ; const uint32_t dcscalar,
395 :     ; const uint16_t *mpeg_matrices);
396 :     ;
397 :     ;-----------------------------------------------------------------------------
398 :    
399 :     ; Note: in order to saturate 'easily', we pre-shift the quantifier
400 :     ; by 4. Then, the high-word of (coeff[]*matrix[i]*quant) are used to
401 :     ; build a saturating mask. It is non-zero only when an overflow occured.
402 :     ; We thus avoid packing/unpacking toward double-word.
403 :     ; Moreover, we perform the mult (matrix[i]*quant) first, instead of, e.g.,
404 :     ; (coeff[i]*matrix[i]). This is less prone to overflow if coeff[] are not
405 :     ; checked. Input ranges are: coeff in [-127,127], inter_matrix in [1..255],a
406 :     ; and quant in [1..31].
407 :     ;
408 :     ; The original loop is:
409 :     ;
410 :     %if 0
411 : Isibaar 1795 movq mm0, [TMP0+8*_EAX + 8*16] ; mm0 = coeff[i]
412 : edgomez 1382 pxor mm1, mm1
413 :     pcmpgtw mm1, mm0
414 :     pxor mm0, mm1 ; change sign if negative
415 :     psubw mm0, mm1 ; -> mm0 = abs(coeff[i]), mm1 = sign of coeff[i]
416 :    
417 :     movq mm2, mm7 ; mm2 = quant
418 : Isibaar 1795 pmullw mm2, [_EBX + 8*_EAX + 8*16 ] ; matrix[i]*quant.
419 : edgomez 1382
420 :     movq mm6, mm2
421 :     pmulhw mm2, mm0 ; high of coeff*(matrix*quant) (should be 0 if no overflow)
422 :     pmullw mm0, mm6 ; low of coeff*(matrix*quant)
423 :    
424 :     pxor mm5, mm5
425 :     pcmpgtw mm2, mm5 ; otherflow?
426 :     psrlw mm2, 5 ; =0 if no clamp, 2047 otherwise
427 :     psrlw mm0, 5
428 :     paddw mm0, mm1 ; start restoring sign
429 :     por mm0, mm2 ; saturate to 2047 if needed
430 :     pxor mm0, mm1 ; finish negating back
431 :    
432 : Isibaar 1795 movq [TMP1 + 8*_EAX + 8*16], mm0 ; data[i]
433 :     add _EAX, 1
434 : edgomez 1382 %endif
435 :    
436 :     ;********************************************************************
437 :    
438 : Isibaar 1795 ALIGN SECTION_ALIGN
439 : edgomez 1382 dequant_mpeg_intra_mmx:
440 :    
441 : Isibaar 1795 mov TMP1, prm1 ; data
442 :     mov TMP0, prm2 ; coeff
443 :     mov _EAX, prm5 ; mpeg_quant_matrices
444 :    
445 :     push _EBX
446 :     mov _EBX, _EAX
447 :     %ifdef ARCH_IS_X86_64
448 :     mov _EAX, prm3
449 : Isibaar 1803 lea prm1, [mmx_mul_quant]
450 :     movq mm7, [prm1 + _EAX*8 - 8]
451 : Isibaar 1795 %else
452 :     mov _EAX, [_ESP + 4 + 12] ; quant
453 :     movq mm7, [mmx_mul_quant + _EAX*8 - 8]
454 :     %endif
455 : edgomez 1382
456 : Isibaar 1795 mov _EAX, -16 ; to keep ALIGNed, we regularly process coeff[0]
457 : edgomez 1382 psllw mm7, 2 ; << 2. See comment.
458 :     pxor mm6, mm6 ; this is a NOP
459 :    
460 : Isibaar 1795 ALIGN SECTION_ALIGN
461 : Isibaar 1793 .loop:
462 : Isibaar 1795 movq mm0, [TMP0+8*_EAX + 8*16] ; mm0 = c = coeff[i]
463 :     movq mm3, [TMP0+8*_EAX + 8*16 +8]; mm3 = c' = coeff[i+1]
464 : edgomez 1382 pxor mm1, mm1
465 :     pxor mm4, mm4
466 :     pcmpgtw mm1, mm0 ; mm1 = sgn(c)
467 :     movq mm2, mm7 ; mm2 = quant
468 :    
469 :     pcmpgtw mm4, mm3 ; mm4 = sgn(c')
470 : Isibaar 1795 pmullw mm2, [_EBX + 8*_EAX + 8*16 ] ; matrix[i]*quant
471 : edgomez 1382
472 :     pxor mm0, mm1 ; negate if negative
473 :     pxor mm3, mm4 ; negate if negative
474 :    
475 :     psubw mm0, mm1
476 :     psubw mm3, mm4
477 :    
478 :     ; we're short on register, here. Poor pairing...
479 :    
480 :     movq mm5, mm2
481 :     pmullw mm2, mm0 ; low of coeff*(matrix*quant)
482 :    
483 :     pmulhw mm0, mm5 ; high of coeff*(matrix*quant)
484 :     movq mm5, mm7 ; mm2 = quant
485 :    
486 : Isibaar 1795 pmullw mm5, [_EBX + 8*_EAX + 8*16 +8] ; matrix[i+1]*quant
487 : edgomez 1382
488 :     movq mm6, mm5
489 : Isibaar 1795 add _EAX,2 ; z-flag will be tested later
490 : edgomez 1382
491 :     pmullw mm6, mm3 ; low of coeff*(matrix*quant)
492 :     pmulhw mm3, mm5 ; high of coeff*(matrix*quant)
493 :    
494 :     pcmpgtw mm0, [zero]
495 :     paddusw mm2, mm0
496 :     psrlw mm2, 5
497 :    
498 :     pcmpgtw mm3, [zero]
499 :     paddusw mm6, mm3
500 :     psrlw mm6, 5
501 :    
502 :     pxor mm2, mm1 ; start negating back
503 :     pxor mm6, mm4 ; start negating back
504 :    
505 :     psubusw mm1, mm0
506 :     psubusw mm4, mm3
507 :    
508 :     psubw mm2, mm1 ; finish negating back
509 :     psubw mm6, mm4 ; finish negating back
510 :    
511 : Isibaar 1795 movq [TMP1 + 8*_EAX + 8*16 -2*8 ], mm2 ; data[i]
512 :     movq [TMP1 + 8*_EAX + 8*16 -2*8 +8], mm6 ; data[i+1]
513 : edgomez 1382
514 :     jnz near .loop
515 :    
516 : Isibaar 1795 pop _EBX
517 :    
518 : edgomez 1382 ; deal with DC
519 : Isibaar 1795 movd mm0, [TMP0]
520 :     %ifdef ARCH_IS_X86_64
521 :     movq mm6, prm4
522 :     pmullw mm0, mm6
523 :     %else
524 :     pmullw mm0, prm4 ; dcscalar
525 :     %endif
526 : edgomez 1382 movq mm2, [mmx_32767_minus_2047]
527 :     paddsw mm0, mm2
528 :     psubsw mm0, mm2
529 :     movq mm2, [mmx_32768_minus_2048]
530 :     psubsw mm0, mm2
531 :     paddsw mm0, mm2
532 :     movd eax, mm0
533 : Isibaar 1795 mov [TMP1], ax
534 : edgomez 1382
535 : Isibaar 1795 xor _EAX, _EAX
536 : edgomez 1382
537 :     ret
538 : Isibaar 1793 ENDFUNC
539 : edgomez 1382
540 :     ;-----------------------------------------------------------------------------
541 :     ;
542 :     ; uint32_t dequant_mpeg_inter_mmx(int16_t * data,
543 :     ; const int16_t * const coeff,
544 :     ; const uint32_t quant,
545 :     ; const uint16_t *mpeg_matrices);
546 :     ;
547 :     ;-----------------------------------------------------------------------------
548 :    
549 :     ; Note: We use (2*c + sgn(c) - sgn(-c)) as multiplier
550 :     ; so we handle the 3 cases: c<0, c==0, and c>0 in one shot.
551 :     ; sgn(x) is the result of 'pcmpgtw 0,x': 0 if x>=0, -1 if x<0.
552 :     ; It's mixed with the extraction of the absolute value.
553 :    
554 : Isibaar 1795 ALIGN SECTION_ALIGN
555 : edgomez 1382 dequant_mpeg_inter_mmx:
556 :    
557 :    
558 : Isibaar 1795 mov TMP1, prm1 ; data
559 :     mov TMP0, prm2 ; coeff
560 :     mov _EAX, prm3 ; quant
561 : edgomez 1382
562 : Isibaar 1795 push _EBX
563 :     %ifdef ARCH_IS_X86_64
564 :     mov _EBX, prm4
565 :     lea r9, [mmx_mul_quant]
566 :     movq mm7, [r9 + _EAX*8 - 8]
567 :     %else
568 :     mov _EBX, [_ESP + 4 + 16] ; mpeg_quant_matrices
569 :     movq mm7, [mmx_mul_quant + _EAX*8 - 8]
570 :     %endif
571 :    
572 :     mov _EAX, -16
573 : edgomez 1382 paddw mm7, mm7 ; << 1
574 :     pxor mm6, mm6 ; mismatch sum
575 :    
576 : Isibaar 1795 ALIGN SECTION_ALIGN
577 : Isibaar 1793 .loop:
578 : Isibaar 1795 movq mm0, [TMP0+8*_EAX + 8*16 ] ; mm0 = coeff[i]
579 :     movq mm2, [TMP0+8*_EAX + 8*16 +8] ; mm2 = coeff[i+1]
580 :     add _EAX, 2
581 : edgomez 1382
582 :     pxor mm1, mm1
583 :     pxor mm3, mm3
584 :     pcmpgtw mm1, mm0 ; mm1 = sgn(c) (preserved)
585 :     pcmpgtw mm3, mm2 ; mm3 = sgn(c') (preserved)
586 :     paddsw mm0, mm1 ; c += sgn(c)
587 :     paddsw mm2, mm3 ; c += sgn(c')
588 :     paddw mm0, mm0 ; c *= 2
589 :     paddw mm2, mm2 ; c'*= 2
590 :    
591 :     pxor mm4, mm4
592 :     pxor mm5, mm5
593 :     psubw mm4, mm0 ; -c
594 :     psubw mm5, mm2 ; -c'
595 :     psraw mm4, 16 ; mm4 = sgn(-c)
596 :     psraw mm5, 16 ; mm5 = sgn(-c')
597 :     psubsw mm0, mm4 ; c -= sgn(-c)
598 :     psubsw mm2, mm5 ; c' -= sgn(-c')
599 :     pxor mm0, mm1 ; finish changing sign if needed
600 :     pxor mm2, mm3 ; finish changing sign if needed
601 :    
602 :     ; we're short on register, here. Poor pairing...
603 :    
604 :     movq mm4, mm7 ; (matrix*quant)
605 : Isibaar 1795 pmullw mm4, [_EBX + 512 + 8*_EAX + 8*16 -2*8]
606 : edgomez 1382 movq mm5, mm4
607 :     pmulhw mm5, mm0 ; high of c*(matrix*quant)
608 :     pmullw mm0, mm4 ; low of c*(matrix*quant)
609 :    
610 :     movq mm4, mm7 ; (matrix*quant)
611 : Isibaar 1795 pmullw mm4, [_EBX + 512 + 8*_EAX + 8*16 -2*8 + 8]
612 : edgomez 1382
613 :     pcmpgtw mm5, [zero]
614 :     paddusw mm0, mm5
615 :     psrlw mm0, 5
616 :     pxor mm0, mm1 ; start restoring sign
617 :     psubusw mm1, mm5
618 :    
619 :     movq mm5, mm4
620 :     pmulhw mm5, mm2 ; high of c*(matrix*quant)
621 :     pmullw mm2, mm4 ; low of c*(matrix*quant)
622 :     psubw mm0, mm1 ; finish restoring sign
623 :    
624 :     pcmpgtw mm5, [zero]
625 :     paddusw mm2, mm5
626 :     psrlw mm2, 5
627 :     pxor mm2, mm3 ; start restoring sign
628 :     psubusw mm3, mm5
629 :     psubw mm2, mm3 ; finish restoring sign
630 :    
631 :     pxor mm6, mm0 ; mismatch control
632 : Isibaar 1795 movq [TMP1 + 8*_EAX + 8*16 -2*8 ], mm0 ; data[i]
633 : edgomez 1382 pxor mm6, mm2 ; mismatch control
634 : Isibaar 1795 movq [TMP1 + 8*_EAX + 8*16 -2*8 +8], mm2 ; data[i+1]
635 : edgomez 1382
636 :     jnz near .loop
637 :    
638 :     ; mismatch control
639 :    
640 :     movq mm0, mm6
641 :     psrlq mm0, 48
642 :     movq mm1, mm6
643 :     movq mm2, mm6
644 :     psrlq mm1, 32
645 :     pxor mm6, mm0
646 :     psrlq mm2, 16
647 :     pxor mm6, mm1
648 :     pxor mm6, mm2
649 :     movd eax, mm6
650 : Isibaar 1795 and _EAX, 1
651 :     xor _EAX, 1
652 :     xor word [TMP1 + 2*63], ax
653 : edgomez 1382
654 : Isibaar 1795 xor _EAX, _EAX
655 : edgomez 1382
656 : Isibaar 1795 pop _EBX
657 : edgomez 1382
658 :     ret
659 : Isibaar 1793 ENDFUNC
660 : edgomez 1540
661 : Isibaar 1877 NON_EXEC_STACK

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4