[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 1798 - (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 1798 ; * $Id: quantize_mpeg_mmx.asm,v 1.12 2008-11-26 02:21:02 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 1795 SECTION .rotext align=SECTION_ALIGN
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 1798 movsx _EAX, word [_EAX] ; data[0]
191 :     mov TMP0, prm4 ; dcscalar
192 :     mov _EDX, _EAX
193 :     shr TMP0, 1 ; TMP0 = dcscalar/2
194 :     sar _EDX, 31 ; TMP1 = sign extend of _EAX (ready for division too)
195 :     xor TMP0, _EDX ; adjust TMP0 according to the sign of data[0]
196 :     sub TMP0, _EDX
197 :     add _EAX, TMP0
198 : syskin 1713
199 : Isibaar 1798 mov TMP0, prm4 ; dcscalar
200 :     idiv TMP0 ; _EAX = _EDX:_EAX / dcscalar
201 : edgomez 1382
202 : Isibaar 1798 mov _EDX, prm1 ; coeff again
203 :     mov word [_EDX], ax ; coeff[0] = ax
204 : Isibaar 1795
205 :     xor _EAX, _EAX ; return(0);
206 : edgomez 1382 ret
207 : Isibaar 1793 ENDFUNC
208 : edgomez 1382
209 :    
210 :     ;-----------------------------------------------------------------------------
211 :     ;
212 :     ; uint32_t quant_mpeg_inter_mmx(int16_t * coeff,
213 :     ; const int16_t const * data,
214 :     ; const uint32_t quant,
215 :     ; const uint16_t *mpeg_matrices);
216 :     ;
217 :     ;-----------------------------------------------------------------------------
218 :    
219 : Isibaar 1795 ALIGN SECTION_ALIGN
220 : edgomez 1382 quant_mpeg_inter_mmx:
221 :    
222 : Isibaar 1795 mov TMP1, prm1 ; coeff
223 :     mov _EAX, prm3 ; quant
224 :     mov TMP0, prm4 ; mpeg_quant_matrices
225 : edgomez 1382
226 : Isibaar 1795 push _ESI
227 :     %ifdef ARCH_IS_X86_64
228 :     mov _ESI, prm2 ; data
229 :     %else
230 :     mov _ESI, [_ESP + 4 + 8] ; data
231 :     %endif
232 : edgomez 1382
233 : Isibaar 1795 push _EBX
234 :     xor _EBX, _EBX
235 : edgomez 1382
236 :     pxor mm5, mm5 ; sum
237 :    
238 :     cmp al, 1
239 :     jz near .q1loop
240 :    
241 :     cmp al, 2
242 :     jz near .q2loop
243 :    
244 : Isibaar 1795 %ifdef ARCH_IS_X86_64
245 :     lea r9, [mmx_div]
246 :     movq mm7, [r9 + _EAX * 8 - 8]
247 :     %else
248 :     movq mm7, [mmx_div + _EAX * 8 - 8] ; divider
249 :     %endif
250 : edgomez 1382
251 : Isibaar 1795 ALIGN SECTION_ALIGN
252 : Isibaar 1793 .loop:
253 : Isibaar 1795 movq mm0, [_ESI + 8*_EBX] ; mm0 = [1st]
254 :     movq mm3, [_ESI + 8*_EBX + 8] ;
255 : edgomez 1382 pxor mm1, mm1 ; mm1 = 0
256 :     pxor mm4, mm4 ;
257 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
258 :     pcmpgtw mm4, mm3 ;
259 :     pxor mm0, mm1 ; mm0 = |mm0|
260 :     pxor mm3, mm4 ;
261 :     psubw mm0, mm1 ; displace
262 :     psubw mm3, mm4 ;
263 :     psllw mm0, 4
264 :     psllw mm3, 4
265 : Isibaar 1795 movq mm2, [TMP0 + 512 + 8*_EBX]
266 : edgomez 1382 psrlw mm2, 1
267 :     paddw mm0, mm2
268 : Isibaar 1795 movq mm2, [TMP0 + 768 + _EBX*8]
269 : edgomez 1382 pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
270 : Isibaar 1795 movq mm2, [TMP0 + 512 + 8*_EBX + 8]
271 : edgomez 1382 psrlw mm2, 1
272 :     paddw mm3, mm2
273 : Isibaar 1795 movq mm2, [TMP0 + 768 + _EBX*8 + 8]
274 : edgomez 1382 pmulhw mm3, mm2
275 :     pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16
276 :     pmulhw mm3, mm7 ;
277 :     psrlw mm0, 1 ; additional shift by 1 => 16 + 1 = 17
278 :     psrlw mm3, 1
279 :     paddw mm5, mm0 ; sum += mm0
280 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
281 :     paddw mm5, mm3 ;
282 :     pxor mm3, mm4 ;
283 :     psubw mm0, mm1 ; undisplace
284 :     psubw mm3, mm4
285 : Isibaar 1795 movq [TMP1 + 8*_EBX], mm0
286 :     movq [TMP1 + 8*_EBX + 8], mm3
287 : edgomez 1382
288 : Isibaar 1795 add _EBX, 2
289 :     cmp _EBX, 16
290 : edgomez 1382 jnz near .loop
291 :    
292 : Isibaar 1793 .done:
293 : edgomez 1382 pmaddwd mm5, [mmx_one]
294 :     movq mm0, mm5
295 :     psrlq mm5, 32
296 :     paddd mm0, mm5
297 :     movd eax, mm0 ; return sum
298 :    
299 : Isibaar 1795 pop _EBX
300 :     pop _ESI
301 : edgomez 1382
302 :     ret
303 :    
304 : Isibaar 1795 ALIGN SECTION_ALIGN
305 : Isibaar 1793 .q1loop:
306 : Isibaar 1795 movq mm0, [_ESI + 8*_EBX] ; mm0 = [1st]
307 :     movq mm3, [_ESI + 8*_EBX+ 8]
308 : edgomez 1382 pxor mm1, mm1 ; mm1 = 0
309 :     pxor mm4, mm4 ;
310 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
311 :     pcmpgtw mm4, mm3 ;
312 :     pxor mm0, mm1 ; mm0 = |mm0|
313 :     pxor mm3, mm4 ;
314 :     psubw mm0, mm1 ; displace
315 :     psubw mm3, mm4 ;
316 :     psllw mm0, 4
317 :     psllw mm3, 4
318 : Isibaar 1795 movq mm2, [TMP0 + 512 + 8*_EBX]
319 : edgomez 1382 psrlw mm2, 1
320 :     paddw mm0, mm2
321 : Isibaar 1795 movq mm2, [TMP0 + 768 + _EBX*8]
322 : edgomez 1382 pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
323 : Isibaar 1795 movq mm2, [TMP0 + 512 + 8*_EBX + 8]
324 : edgomez 1382 psrlw mm2, 1
325 :     paddw mm3, mm2
326 : Isibaar 1795 movq mm2, [TMP0 + 768 + _EBX*8 + 8]
327 : edgomez 1382 pmulhw mm3, mm2
328 :     psrlw mm0, 1 ; mm0 >>= 1 (/2)
329 :     psrlw mm3, 1 ;
330 :     paddw mm5, mm0 ; sum += mm0
331 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
332 :     paddw mm5, mm3 ;
333 :     pxor mm3, mm4 ;
334 :     psubw mm0, mm1 ; undisplace
335 :     psubw mm3, mm4
336 : Isibaar 1795 movq [TMP1 + 8*_EBX], mm0
337 :     movq [TMP1 + 8*_EBX + 8], mm3
338 : edgomez 1382
339 : Isibaar 1795 add _EBX, 2
340 :     cmp _EBX, 16
341 : edgomez 1382 jnz near .q1loop
342 :    
343 :     jmp .done
344 :    
345 : Isibaar 1795 ALIGN SECTION_ALIGN
346 : Isibaar 1793 .q2loop:
347 : Isibaar 1795 movq mm0, [_ESI + 8*_EBX] ; mm0 = [1st]
348 :     movq mm3, [_ESI + 8*_EBX+ 8]
349 : edgomez 1382 pxor mm1, mm1 ; mm1 = 0
350 :     pxor mm4, mm4 ;
351 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
352 :     pcmpgtw mm4, mm3 ;
353 :     pxor mm0, mm1 ; mm0 = |mm0|
354 :     pxor mm3, mm4 ;
355 :     psubw mm0, mm1 ; displace
356 :     psubw mm3, mm4 ;
357 :     psllw mm0, 4
358 :     psllw mm3, 4
359 : Isibaar 1795 movq mm2, [TMP0 + 512 + 8*_EBX]
360 : edgomez 1382 psrlw mm2, 1
361 :     paddw mm0, mm2
362 : Isibaar 1795 movq mm2, [TMP0 + 768 + _EBX*8]
363 : edgomez 1382 pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
364 : Isibaar 1795 movq mm2, [TMP0 + 512 + 8*_EBX + 8]
365 : edgomez 1382 psrlw mm2, 1
366 :     paddw mm3, mm2
367 : Isibaar 1795 movq mm2, [TMP0 + 768 + _EBX*8 + 8]
368 : edgomez 1382 pmulhw mm3, mm2
369 :     psrlw mm0, 2 ; mm0 >>= 1 (/2)
370 :     psrlw mm3, 2 ;
371 :     paddw mm5, mm0 ; sum += mm0
372 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
373 :     paddw mm5, mm3 ;
374 :     pxor mm3, mm4 ;
375 :     psubw mm0, mm1 ; undisplace
376 :     psubw mm3, mm4
377 : Isibaar 1795 movq [TMP1 + 8*_EBX], mm0
378 :     movq [TMP1 + 8*_EBX + 8], mm3
379 : edgomez 1382
380 : Isibaar 1795 add _EBX, 2
381 :     cmp _EBX, 16
382 : edgomez 1382 jnz near .q2loop
383 :    
384 :     jmp .done
385 : Isibaar 1793 ENDFUNC
386 : edgomez 1382
387 :    
388 :     ;-----------------------------------------------------------------------------
389 :     ;
390 :     ; uint32_t dequant_mpeg_intra_mmx(int16_t *data,
391 :     ; const int16_t const *coeff,
392 :     ; const uint32_t quant,
393 :     ; const uint32_t dcscalar,
394 :     ; const uint16_t *mpeg_matrices);
395 :     ;
396 :     ;-----------------------------------------------------------------------------
397 :    
398 :     ; Note: in order to saturate 'easily', we pre-shift the quantifier
399 :     ; by 4. Then, the high-word of (coeff[]*matrix[i]*quant) are used to
400 :     ; build a saturating mask. It is non-zero only when an overflow occured.
401 :     ; We thus avoid packing/unpacking toward double-word.
402 :     ; Moreover, we perform the mult (matrix[i]*quant) first, instead of, e.g.,
403 :     ; (coeff[i]*matrix[i]). This is less prone to overflow if coeff[] are not
404 :     ; checked. Input ranges are: coeff in [-127,127], inter_matrix in [1..255],a
405 :     ; and quant in [1..31].
406 :     ;
407 :     ; The original loop is:
408 :     ;
409 :     %if 0
410 : Isibaar 1795 movq mm0, [TMP0+8*_EAX + 8*16] ; mm0 = coeff[i]
411 : edgomez 1382 pxor mm1, mm1
412 :     pcmpgtw mm1, mm0
413 :     pxor mm0, mm1 ; change sign if negative
414 :     psubw mm0, mm1 ; -> mm0 = abs(coeff[i]), mm1 = sign of coeff[i]
415 :    
416 :     movq mm2, mm7 ; mm2 = quant
417 : Isibaar 1795 pmullw mm2, [_EBX + 8*_EAX + 8*16 ] ; matrix[i]*quant.
418 : edgomez 1382
419 :     movq mm6, mm2
420 :     pmulhw mm2, mm0 ; high of coeff*(matrix*quant) (should be 0 if no overflow)
421 :     pmullw mm0, mm6 ; low of coeff*(matrix*quant)
422 :    
423 :     pxor mm5, mm5
424 :     pcmpgtw mm2, mm5 ; otherflow?
425 :     psrlw mm2, 5 ; =0 if no clamp, 2047 otherwise
426 :     psrlw mm0, 5
427 :     paddw mm0, mm1 ; start restoring sign
428 :     por mm0, mm2 ; saturate to 2047 if needed
429 :     pxor mm0, mm1 ; finish negating back
430 :    
431 : Isibaar 1795 movq [TMP1 + 8*_EAX + 8*16], mm0 ; data[i]
432 :     add _EAX, 1
433 : edgomez 1382 %endif
434 :    
435 :     ;********************************************************************
436 :    
437 : Isibaar 1795 ALIGN SECTION_ALIGN
438 : edgomez 1382 dequant_mpeg_intra_mmx:
439 :    
440 : Isibaar 1795 mov TMP1, prm1 ; data
441 :     mov TMP0, prm2 ; coeff
442 :     mov _EAX, prm5 ; mpeg_quant_matrices
443 :    
444 :     push _EBX
445 :     mov _EBX, _EAX
446 :     %ifdef ARCH_IS_X86_64
447 :     mov _EAX, prm3
448 :     lea r9, [mmx_mul_quant]
449 :     movq mm7, [r9 + _EAX*8 - 8]
450 :     %else
451 :     mov _EAX, [_ESP + 4 + 12] ; quant
452 :     movq mm7, [mmx_mul_quant + _EAX*8 - 8]
453 :     %endif
454 : edgomez 1382
455 : Isibaar 1795 mov _EAX, -16 ; to keep ALIGNed, we regularly process coeff[0]
456 : edgomez 1382 psllw mm7, 2 ; << 2. See comment.
457 :     pxor mm6, mm6 ; this is a NOP
458 :    
459 : Isibaar 1795 ALIGN SECTION_ALIGN
460 : Isibaar 1793 .loop:
461 : Isibaar 1795 movq mm0, [TMP0+8*_EAX + 8*16] ; mm0 = c = coeff[i]
462 :     movq mm3, [TMP0+8*_EAX + 8*16 +8]; mm3 = c' = coeff[i+1]
463 : edgomez 1382 pxor mm1, mm1
464 :     pxor mm4, mm4
465 :     pcmpgtw mm1, mm0 ; mm1 = sgn(c)
466 :     movq mm2, mm7 ; mm2 = quant
467 :    
468 :     pcmpgtw mm4, mm3 ; mm4 = sgn(c')
469 : Isibaar 1795 pmullw mm2, [_EBX + 8*_EAX + 8*16 ] ; matrix[i]*quant
470 : edgomez 1382
471 :     pxor mm0, mm1 ; negate if negative
472 :     pxor mm3, mm4 ; negate if negative
473 :    
474 :     psubw mm0, mm1
475 :     psubw mm3, mm4
476 :    
477 :     ; we're short on register, here. Poor pairing...
478 :    
479 :     movq mm5, mm2
480 :     pmullw mm2, mm0 ; low of coeff*(matrix*quant)
481 :    
482 :     pmulhw mm0, mm5 ; high of coeff*(matrix*quant)
483 :     movq mm5, mm7 ; mm2 = quant
484 :    
485 : Isibaar 1795 pmullw mm5, [_EBX + 8*_EAX + 8*16 +8] ; matrix[i+1]*quant
486 : edgomez 1382
487 :     movq mm6, mm5
488 : Isibaar 1795 add _EAX,2 ; z-flag will be tested later
489 : edgomez 1382
490 :     pmullw mm6, mm3 ; low of coeff*(matrix*quant)
491 :     pmulhw mm3, mm5 ; high of coeff*(matrix*quant)
492 :    
493 :     pcmpgtw mm0, [zero]
494 :     paddusw mm2, mm0
495 :     psrlw mm2, 5
496 :    
497 :     pcmpgtw mm3, [zero]
498 :     paddusw mm6, mm3
499 :     psrlw mm6, 5
500 :    
501 :     pxor mm2, mm1 ; start negating back
502 :     pxor mm6, mm4 ; start negating back
503 :    
504 :     psubusw mm1, mm0
505 :     psubusw mm4, mm3
506 :    
507 :     psubw mm2, mm1 ; finish negating back
508 :     psubw mm6, mm4 ; finish negating back
509 :    
510 : Isibaar 1795 movq [TMP1 + 8*_EAX + 8*16 -2*8 ], mm2 ; data[i]
511 :     movq [TMP1 + 8*_EAX + 8*16 -2*8 +8], mm6 ; data[i+1]
512 : edgomez 1382
513 :     jnz near .loop
514 :    
515 : Isibaar 1795 pop _EBX
516 :    
517 : edgomez 1382 ; deal with DC
518 : Isibaar 1795 movd mm0, [TMP0]
519 :     %ifdef ARCH_IS_X86_64
520 :     movq mm6, prm4
521 :     pmullw mm0, mm6
522 :     %else
523 :     pmullw mm0, prm4 ; dcscalar
524 :     %endif
525 : edgomez 1382 movq mm2, [mmx_32767_minus_2047]
526 :     paddsw mm0, mm2
527 :     psubsw mm0, mm2
528 :     movq mm2, [mmx_32768_minus_2048]
529 :     psubsw mm0, mm2
530 :     paddsw mm0, mm2
531 :     movd eax, mm0
532 : Isibaar 1795 mov [TMP1], ax
533 : edgomez 1382
534 : Isibaar 1795 xor _EAX, _EAX
535 : edgomez 1382
536 :     ret
537 : Isibaar 1793 ENDFUNC
538 : edgomez 1382
539 :     ;-----------------------------------------------------------------------------
540 :     ;
541 :     ; uint32_t dequant_mpeg_inter_mmx(int16_t * data,
542 :     ; const int16_t * const coeff,
543 :     ; const uint32_t quant,
544 :     ; const uint16_t *mpeg_matrices);
545 :     ;
546 :     ;-----------------------------------------------------------------------------
547 :    
548 :     ; Note: We use (2*c + sgn(c) - sgn(-c)) as multiplier
549 :     ; so we handle the 3 cases: c<0, c==0, and c>0 in one shot.
550 :     ; sgn(x) is the result of 'pcmpgtw 0,x': 0 if x>=0, -1 if x<0.
551 :     ; It's mixed with the extraction of the absolute value.
552 :    
553 : Isibaar 1795 ALIGN SECTION_ALIGN
554 : edgomez 1382 dequant_mpeg_inter_mmx:
555 :    
556 :    
557 : Isibaar 1795 mov TMP1, prm1 ; data
558 :     mov TMP0, prm2 ; coeff
559 :     mov _EAX, prm3 ; quant
560 : edgomez 1382
561 : Isibaar 1795 push _EBX
562 :     %ifdef ARCH_IS_X86_64
563 :     mov _EBX, prm4
564 :     lea r9, [mmx_mul_quant]
565 :     movq mm7, [r9 + _EAX*8 - 8]
566 :     %else
567 :     mov _EBX, [_ESP + 4 + 16] ; mpeg_quant_matrices
568 :     movq mm7, [mmx_mul_quant + _EAX*8 - 8]
569 :     %endif
570 :    
571 :     mov _EAX, -16
572 : edgomez 1382 paddw mm7, mm7 ; << 1
573 :     pxor mm6, mm6 ; mismatch sum
574 :    
575 : Isibaar 1795 ALIGN SECTION_ALIGN
576 : Isibaar 1793 .loop:
577 : Isibaar 1795 movq mm0, [TMP0+8*_EAX + 8*16 ] ; mm0 = coeff[i]
578 :     movq mm2, [TMP0+8*_EAX + 8*16 +8] ; mm2 = coeff[i+1]
579 :     add _EAX, 2
580 : edgomez 1382
581 :     pxor mm1, mm1
582 :     pxor mm3, mm3
583 :     pcmpgtw mm1, mm0 ; mm1 = sgn(c) (preserved)
584 :     pcmpgtw mm3, mm2 ; mm3 = sgn(c') (preserved)
585 :     paddsw mm0, mm1 ; c += sgn(c)
586 :     paddsw mm2, mm3 ; c += sgn(c')
587 :     paddw mm0, mm0 ; c *= 2
588 :     paddw mm2, mm2 ; c'*= 2
589 :    
590 :     pxor mm4, mm4
591 :     pxor mm5, mm5
592 :     psubw mm4, mm0 ; -c
593 :     psubw mm5, mm2 ; -c'
594 :     psraw mm4, 16 ; mm4 = sgn(-c)
595 :     psraw mm5, 16 ; mm5 = sgn(-c')
596 :     psubsw mm0, mm4 ; c -= sgn(-c)
597 :     psubsw mm2, mm5 ; c' -= sgn(-c')
598 :     pxor mm0, mm1 ; finish changing sign if needed
599 :     pxor mm2, mm3 ; finish changing sign if needed
600 :    
601 :     ; we're short on register, here. Poor pairing...
602 :    
603 :     movq mm4, mm7 ; (matrix*quant)
604 : Isibaar 1795 pmullw mm4, [_EBX + 512 + 8*_EAX + 8*16 -2*8]
605 : edgomez 1382 movq mm5, mm4
606 :     pmulhw mm5, mm0 ; high of c*(matrix*quant)
607 :     pmullw mm0, mm4 ; low of c*(matrix*quant)
608 :    
609 :     movq mm4, mm7 ; (matrix*quant)
610 : Isibaar 1795 pmullw mm4, [_EBX + 512 + 8*_EAX + 8*16 -2*8 + 8]
611 : edgomez 1382
612 :     pcmpgtw mm5, [zero]
613 :     paddusw mm0, mm5
614 :     psrlw mm0, 5
615 :     pxor mm0, mm1 ; start restoring sign
616 :     psubusw mm1, mm5
617 :    
618 :     movq mm5, mm4
619 :     pmulhw mm5, mm2 ; high of c*(matrix*quant)
620 :     pmullw mm2, mm4 ; low of c*(matrix*quant)
621 :     psubw mm0, mm1 ; finish restoring sign
622 :    
623 :     pcmpgtw mm5, [zero]
624 :     paddusw mm2, mm5
625 :     psrlw mm2, 5
626 :     pxor mm2, mm3 ; start restoring sign
627 :     psubusw mm3, mm5
628 :     psubw mm2, mm3 ; finish restoring sign
629 :    
630 :     pxor mm6, mm0 ; mismatch control
631 : Isibaar 1795 movq [TMP1 + 8*_EAX + 8*16 -2*8 ], mm0 ; data[i]
632 : edgomez 1382 pxor mm6, mm2 ; mismatch control
633 : Isibaar 1795 movq [TMP1 + 8*_EAX + 8*16 -2*8 +8], mm2 ; data[i+1]
634 : edgomez 1382
635 :     jnz near .loop
636 :    
637 :     ; mismatch control
638 :    
639 :     movq mm0, mm6
640 :     psrlq mm0, 48
641 :     movq mm1, mm6
642 :     movq mm2, mm6
643 :     psrlq mm1, 32
644 :     pxor mm6, mm0
645 :     psrlq mm2, 16
646 :     pxor mm6, mm1
647 :     pxor mm6, mm2
648 :     movd eax, mm6
649 : Isibaar 1795 and _EAX, 1
650 :     xor _EAX, 1
651 :     xor word [TMP1 + 2*63], ax
652 : edgomez 1382
653 : Isibaar 1795 xor _EAX, _EAX
654 : edgomez 1382
655 : Isibaar 1795 pop _EBX
656 : edgomez 1382
657 :     ret
658 : Isibaar 1793 ENDFUNC
659 : edgomez 1540
660 : Isibaar 1790
661 :     %ifidn __OUTPUT_FORMAT__,elf
662 :     section ".note.GNU-stack" noalloc noexec nowrite progbits
663 :     %endif
664 :    

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