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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.2.2 - (view) (download)

1 : edgomez 1.1.2.2 ;/**************************************************************************
2 :     ; *
3 :     ; * XVID MPEG-4 VIDEO CODEC
4 :     ; * - 3dne Quantization/Dequantization -
5 :     ; *
6 :     ; * Copyright (C) 2002-2003 Peter Ross <pross@xvid.org>
7 :     ; * 2002-2003 Michael Militzer <isibaar@xvid.org>
8 :     ; * 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 :     ; * $Id$
25 :     ; *
26 :     ; *************************************************************************/
27 : edgomez 1.1.2.1
28 :     ; data/text alignment
29 :     %define ALIGN 8
30 :    
31 :     %define SATURATE
32 :    
33 :     bits 32
34 :    
35 :     %macro cglobal 1
36 :     %ifdef PREFIX
37 :     global _%1
38 :     %define %1 _%1
39 :     %else
40 :     global %1
41 :     %endif
42 :     %endmacro
43 :    
44 :     %macro cextern 1
45 :     %ifdef PREFIX
46 :     extern _%1
47 :     %define %1 _%1
48 :     %else
49 :     extern %1
50 :     %endif
51 :     %endmacro
52 :    
53 : edgomez 1.1.2.2 ;***************************************************************************
54 :     ; Local data
55 :     ;***************************************************************************
56 :    
57 :     %ifdef FORMAT_COFF
58 :     SECTION .data data
59 :     %else
60 :     SECTION .data data align=8
61 :     %endif
62 :    
63 :     mmx_one:
64 :     times 4 dw 1
65 : edgomez 1.1.2.1
66 :     ;===========================================================================
67 :     ;
68 :     ; divide by 2Q table
69 :     ;
70 :     ;===========================================================================
71 :    
72 : edgomez 1.1.2.2 align 16
73 :     mmx_div:
74 :     %assign quant 1
75 :     %rep 31
76 :     times 4 dw (1<<17) / (quant*2) + 1
77 :     %assign quant quant+1
78 :     %endrep
79 : edgomez 1.1.2.1
80 :     ;===========================================================================
81 :     ;
82 :     ; intra matrix
83 :     ;
84 :     ;===========================================================================
85 :    
86 :     cextern intra_matrix
87 :     cextern intra_matrix_fix
88 :    
89 :     ;===========================================================================
90 :     ;
91 :     ; inter matrix
92 :     ;
93 :     ;===========================================================================
94 :    
95 :     cextern inter_matrix
96 :     cextern inter_matrix_fix
97 :    
98 :    
99 :     %define VM18P 3
100 :     %define VM18Q 4
101 :    
102 :    
103 :     ;===========================================================================
104 :     ;
105 :     ; quantd table
106 :     ;
107 :     ;===========================================================================
108 :    
109 : edgomez 1.1.2.2 quantd:
110 :     %assign quant 1
111 :     %rep 31
112 :     times 4 dw ((VM18P*quant) + (VM18Q/2)) / VM18Q
113 :     %assign quant quant+1
114 :     %endrep
115 : edgomez 1.1.2.1
116 :     ;===========================================================================
117 :     ;
118 :     ; multiple by 2Q table
119 :     ;
120 :     ;===========================================================================
121 :    
122 : edgomez 1.1.2.2 mmx_mul_quant:
123 :     %assign quant 1
124 :     %rep 31
125 :     times 4 dw quant
126 :     %assign quant quant+1
127 :     %endrep
128 : edgomez 1.1.2.1
129 :     ;===========================================================================
130 :     ;
131 :     ; saturation limits
132 :     ;
133 :     ;===========================================================================
134 :    
135 :     align 16
136 :    
137 : edgomez 1.1.2.2 mmx_32767_minus_2047:
138 :     times 4 dw (32767-2047)
139 :     mmx_32768_minus_2048:
140 :     times 4 dw (32768-2048)
141 :     mmx_2047:
142 :     times 4 dw 2047
143 :     mmx_minus_2048:
144 :     times 4 dw (-2048)
145 :     zero:
146 :     times 4 dw 0
147 :    
148 :     ;***************************************************************************
149 :     ; Local data
150 :     ;***************************************************************************
151 : edgomez 1.1.2.1
152 :     section .text
153 :    
154 :     ;===========================================================================
155 :     ;
156 : edgomez 1.1.2.2 ; uint32_t quant_mpeg_intra_mmx(int16_t * coeff,
157 :     ; const int16_t const * data,
158 :     ; const uint32_t quant,
159 :     ; const uint32_t dcscalar);
160 : edgomez 1.1.2.1 ;
161 :     ;===========================================================================
162 :    
163 :     align ALIGN
164 :     cglobal quant_mpeg_intra_mmx
165 :     quant_mpeg_intra_mmx:
166 :    
167 : edgomez 1.1.2.2 push ecx
168 :     push esi
169 :     push edi
170 : edgomez 1.1.2.1
171 : edgomez 1.1.2.2 mov edi, [esp + 12 + 4] ; coeff
172 :     mov esi, [esp + 12 + 8] ; data
173 :     mov eax, [esp + 12 + 12] ; quant
174 : edgomez 1.1.2.1
175 : edgomez 1.1.2.2 movq mm5, [quantd + eax * 8 - 8] ; quantd -> mm5
176 : edgomez 1.1.2.1
177 : edgomez 1.1.2.2 xor ecx, ecx
178 :     cmp al, 1
179 :     jz near .q1loop
180 : edgomez 1.1.2.1
181 : edgomez 1.1.2.2 cmp al, 2
182 :     jz near .q2loop
183 : edgomez 1.1.2.1
184 : edgomez 1.1.2.2 movq mm7, [mmx_div + eax * 8 - 8] ; multipliers[quant] -> mm7
185 : edgomez 1.1.2.1
186 :     align ALIGN
187 :     .loop
188 : edgomez 1.1.2.2 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
189 :     movq mm3, [esi + 8*ecx + 8] ;
190 : edgomez 1.1.2.1
191 : edgomez 1.1.2.2 pxor mm1, mm1 ; mm1 = 0
192 :     pxor mm4, mm4
193 : edgomez 1.1.2.1
194 : edgomez 1.1.2.2 pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
195 :     pcmpgtw mm4, mm3
196 : edgomez 1.1.2.1
197 : edgomez 1.1.2.2 pxor mm0, mm1 ; mm0 = |mm0|
198 :     pxor mm3, mm4 ;
199 :     psubw mm0, mm1 ; displace
200 :     psubw mm3, mm4 ;
201 :    
202 :     psllw mm0, 4 ; level << 4
203 :     psllw mm3, 4 ;
204 :    
205 :     movq mm2, [intra_matrix + 8*ecx]
206 :     psrlw mm2, 1 ; intra_matrix[i]>>1
207 :     paddw mm0, mm2
208 :    
209 :     movq mm2, [intra_matrix_fix + ecx*8]
210 :     pmulhw mm0, mm2 ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i]
211 :    
212 :     movq mm2, [intra_matrix + 8*ecx + 8]
213 :     psrlw mm2, 1
214 :     paddw mm3, mm2
215 :    
216 :     movq mm2, [intra_matrix_fix + ecx*8 + 8]
217 :     pmulhw mm3, mm2
218 :    
219 :     paddw mm0, mm5 ; + quantd
220 :     paddw mm3, mm5
221 :     pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16
222 :     pmulhw mm3, mm7 ;
223 :     psrlw mm0, 1 ; additional shift by 1 => 16 + 1 = 17
224 :     psrlw mm3, 1
225 :    
226 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
227 :     pxor mm3, mm4 ;
228 :     psubw mm0, mm1 ; undisplace
229 :     psubw mm3, mm4 ;
230 :    
231 :     movq [edi + 8*ecx], mm0
232 :     movq [edi + 8*ecx + 8], mm3
233 :    
234 :     add ecx,2
235 :     cmp ecx,16
236 :     jnz near .loop
237 : edgomez 1.1.2.1
238 :     .done
239 :     ; caclulate data[0] // (int32_t)dcscalar)
240 :    
241 : edgomez 1.1.2.2 mov ecx, [esp + 12 + 16] ; dcscalar
242 :     mov edx, ecx
243 :     movsx eax, word [esi] ; data[0]
244 :     shr edx, 1 ; edx = dcscalar /2
245 :     cmp eax, 0
246 :     jg .gtzero
247 : edgomez 1.1.2.1
248 : edgomez 1.1.2.2 sub eax, edx
249 :     jmp short .mul
250 : edgomez 1.1.2.1 .gtzero
251 : edgomez 1.1.2.2 add eax, edx
252 : edgomez 1.1.2.1 .mul
253 : edgomez 1.1.2.2 cdq ; expand eax -> edx:eax
254 :     idiv ecx ; eax = edx:eax / dcscalar
255 : edgomez 1.1.2.1
256 : edgomez 1.1.2.2 mov [edi], ax ; coeff[0] = ax
257 : edgomez 1.1.2.1
258 : edgomez 1.1.2.2 pop edi
259 :     pop esi
260 :     pop ecx
261 : edgomez 1.1.2.1
262 : edgomez 1.1.2.2 xor eax, eax ; return(0);
263 :     ret
264 : edgomez 1.1.2.1
265 :     align ALIGN
266 :     .q1loop
267 : edgomez 1.1.2.2 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
268 :     movq mm3, [esi + 8*ecx + 8] ;
269 : edgomez 1.1.2.1
270 : edgomez 1.1.2.2 pxor mm1, mm1 ; mm1 = 0
271 :     pxor mm4, mm4 ;
272 : edgomez 1.1.2.1
273 : edgomez 1.1.2.2 pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
274 :     pcmpgtw mm4, mm3 ;
275 : edgomez 1.1.2.1
276 : edgomez 1.1.2.2 pxor mm0, mm1 ; mm0 = |mm0|
277 :     pxor mm3, mm4 ;
278 :     psubw mm0, mm1 ; displace
279 :     psubw mm3, mm4 ;
280 :    
281 :     psllw mm0, 4
282 :     psllw mm3, 4
283 :    
284 :     movq mm2, [intra_matrix + 8*ecx]
285 :     psrlw mm2, 1
286 :     paddw mm0, mm2
287 :    
288 :     movq mm2, [intra_matrix_fix + ecx*8]
289 :     pmulhw mm0, mm2 ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i]
290 :    
291 :     movq mm2, [intra_matrix + 8*ecx + 8]
292 :     psrlw mm2, 1
293 :     paddw mm3, mm2
294 :    
295 :     movq mm2, [intra_matrix_fix + ecx*8 + 8]
296 :     pmulhw mm3, mm2
297 :    
298 :     paddw mm0, mm5
299 :     paddw mm3, mm5
300 :    
301 :     psrlw mm0, 1 ; mm0 >>= 1 (/2)
302 :     psrlw mm3, 1 ;
303 :    
304 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
305 :     pxor mm3, mm4 ;
306 :     psubw mm0, mm1 ; undisplace
307 :     psubw mm3, mm4 ;
308 :    
309 :     movq [edi + 8*ecx], mm0
310 :     movq [edi + 8*ecx + 8], mm3
311 :    
312 :     add ecx, 2
313 :     cmp ecx, 16
314 :     jnz near .q1loop
315 :     jmp near .done
316 : edgomez 1.1.2.1
317 :    
318 :     align ALIGN
319 :     .q2loop
320 : edgomez 1.1.2.2 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
321 :     movq mm3, [esi + 8*ecx + 8] ;
322 : edgomez 1.1.2.1
323 : edgomez 1.1.2.2 pxor mm1, mm1 ; mm1 = 0
324 :     pxor mm4, mm4 ;
325 : edgomez 1.1.2.1
326 : edgomez 1.1.2.2 pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
327 :     pcmpgtw mm4, mm3 ;
328 : edgomez 1.1.2.1
329 : edgomez 1.1.2.2 pxor mm0, mm1 ; mm0 = |mm0|
330 :     pxor mm3, mm4 ;
331 :     psubw mm0, mm1 ; displace
332 :     psubw mm3, mm4 ;
333 : edgomez 1.1.2.1
334 : edgomez 1.1.2.2 psllw mm0, 4
335 :     psllw mm3, 4
336 : edgomez 1.1.2.1
337 : edgomez 1.1.2.2 movq mm2, [intra_matrix + 8*ecx]
338 :     psrlw mm2, 1
339 :     paddw mm0, mm2
340 : edgomez 1.1.2.1
341 : edgomez 1.1.2.2 movq mm2, [intra_matrix_fix + ecx*8]
342 :     pmulhw mm0, mm2 ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i]
343 : edgomez 1.1.2.1
344 : edgomez 1.1.2.2 movq mm2, [intra_matrix + 8*ecx + 8]
345 :     psrlw mm2, 1
346 :     paddw mm3, mm2
347 : edgomez 1.1.2.1
348 : edgomez 1.1.2.2 movq mm2, [intra_matrix_fix + ecx*8 + 8]
349 :     pmulhw mm3, mm2
350 : edgomez 1.1.2.1
351 : edgomez 1.1.2.2 paddw mm0, mm5
352 :     paddw mm3, mm5
353 : edgomez 1.1.2.1
354 : edgomez 1.1.2.2 psrlw mm0, 2 ; mm0 >>= 1 (/4)
355 :     psrlw mm3, 2 ;
356 : edgomez 1.1.2.1
357 : edgomez 1.1.2.2 pxor mm0, mm1 ; mm0 *= sign(mm0)
358 :     pxor mm3, mm4 ;
359 :     psubw mm0, mm1 ; undisplace
360 :     psubw mm3, mm4 ;
361 : edgomez 1.1.2.1
362 : edgomez 1.1.2.2 movq [edi + 8*ecx], mm0
363 :     movq [edi + 8*ecx + 8], mm3
364 : edgomez 1.1.2.1
365 : edgomez 1.1.2.2 add ecx,2
366 :     cmp ecx,16
367 :     jnz near .q2loop
368 :     jmp near .done
369 : edgomez 1.1.2.1
370 :    
371 :     ;===========================================================================
372 :     ;
373 : edgomez 1.1.2.2 ; uint32_t quant_mpeg_inter_mmx(int16_t * coeff,
374 :     ; const int16_t const * data,
375 :     ; const uint32_t quant);
376 : edgomez 1.1.2.1 ;
377 :     ;===========================================================================
378 :    
379 :     align ALIGN
380 :     cglobal quant_mpeg_inter_mmx
381 :     quant_mpeg_inter_mmx:
382 :    
383 : edgomez 1.1.2.2 push ecx
384 :     push esi
385 :     push edi
386 : edgomez 1.1.2.1
387 : edgomez 1.1.2.2 mov edi, [esp + 12 + 4] ; coeff
388 :     mov esi, [esp + 12 + 8] ; data
389 :     mov eax, [esp + 12 + 12] ; quant
390 : edgomez 1.1.2.1
391 : edgomez 1.1.2.2 xor ecx, ecx
392 : edgomez 1.1.2.1
393 : edgomez 1.1.2.2 pxor mm5, mm5 ; sum
394 : edgomez 1.1.2.1
395 : edgomez 1.1.2.2 cmp al, 1
396 :     jz near .q1loop
397 : edgomez 1.1.2.1
398 : edgomez 1.1.2.2 cmp al, 2
399 :     jz near .q2loop
400 : edgomez 1.1.2.1
401 : edgomez 1.1.2.2 movq mm7, [mmx_div + eax * 8 - 8] ; divider
402 : edgomez 1.1.2.1
403 :     align ALIGN
404 :     .loop
405 : edgomez 1.1.2.2 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
406 :     movq mm3, [esi + 8*ecx + 8] ;
407 :     pxor mm1, mm1 ; mm1 = 0
408 :     pxor mm4, mm4 ;
409 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
410 :     pcmpgtw mm4, mm3 ;
411 :     pxor mm0, mm1 ; mm0 = |mm0|
412 :     pxor mm3, mm4 ;
413 :     psubw mm0, mm1 ; displace
414 :     psubw mm3, mm4 ;
415 :    
416 :     psllw mm0, 4
417 :     psllw mm3, 4
418 :    
419 :     movq mm2, [inter_matrix + 8*ecx]
420 :     psrlw mm2, 1
421 :     paddw mm0, mm2
422 :    
423 :     movq mm2, [inter_matrix_fix + ecx*8]
424 :     pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
425 :    
426 :     movq mm2, [inter_matrix + 8*ecx + 8]
427 :     psrlw mm2, 1
428 :     paddw mm3, mm2
429 :    
430 :     movq mm2, [inter_matrix_fix + ecx*8 + 8]
431 :     pmulhw mm3, mm2
432 :    
433 :     pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16
434 :     pmulhw mm3, mm7 ;
435 :     psrlw mm0, 1 ; additional shift by 1 => 16 + 1 = 17
436 :     psrlw mm3, 1
437 :    
438 :     paddw mm5, mm0 ; sum += mm0
439 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
440 :     paddw mm5, mm3 ;
441 :     pxor mm3, mm4 ;
442 :     psubw mm0, mm1 ; undisplace
443 :     psubw mm3, mm4
444 :     movq [edi + 8*ecx], mm0
445 :     movq [edi + 8*ecx + 8], mm3
446 :    
447 :     add ecx, 2
448 :     cmp ecx, 16
449 :     jnz near .loop
450 : edgomez 1.1.2.1
451 :     .done
452 : edgomez 1.1.2.2 pmaddwd mm5, [mmx_one]
453 :     movq mm0, mm5
454 :     psrlq mm5, 32
455 :     paddd mm0, mm5
456 :     movd eax, mm0 ; return sum
457 :    
458 :     pop edi
459 :     pop esi
460 :     pop ecx
461 : edgomez 1.1.2.1
462 : edgomez 1.1.2.2 ret
463 : edgomez 1.1.2.1
464 :     align ALIGN
465 :     .q1loop
466 : edgomez 1.1.2.2 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
467 :     movq mm3, [esi + 8*ecx+ 8]
468 : edgomez 1.1.2.1 ;
469 : edgomez 1.1.2.2 pxor mm1, mm1 ; mm1 = 0
470 :     pxor mm4, mm4 ;
471 : edgomez 1.1.2.1
472 : edgomez 1.1.2.2 pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
473 :     pcmpgtw mm4, mm3 ;
474 : edgomez 1.1.2.1
475 : edgomez 1.1.2.2 pxor mm0, mm1 ; mm0 = |mm0|
476 :     pxor mm3, mm4 ;
477 :     psubw mm0, mm1 ; displace
478 :     psubw mm3, mm4 ;
479 : edgomez 1.1.2.1
480 : edgomez 1.1.2.2 psllw mm0, 4
481 :     psllw mm3, 4
482 : edgomez 1.1.2.1
483 : edgomez 1.1.2.2 movq mm2, [inter_matrix + 8*ecx]
484 :     psrlw mm2, 1
485 :     paddw mm0, mm2
486 : edgomez 1.1.2.1
487 : edgomez 1.1.2.2 movq mm2, [inter_matrix_fix + ecx*8]
488 :     pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
489 : edgomez 1.1.2.1
490 : edgomez 1.1.2.2 movq mm2, [inter_matrix + 8*ecx + 8]
491 :     psrlw mm2, 1
492 :     paddw mm3, mm2
493 :    
494 :     movq mm2, [inter_matrix_fix + ecx*8 + 8]
495 :     pmulhw mm3, mm2
496 : edgomez 1.1.2.1
497 : edgomez 1.1.2.2 psrlw mm0, 1 ; mm0 >>= 1 (/2)
498 :     psrlw mm3, 1 ;
499 : edgomez 1.1.2.1
500 : edgomez 1.1.2.2 paddw mm5, mm0 ; sum += mm0
501 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
502 :     paddw mm5, mm3 ;
503 :     pxor mm3, mm4 ;
504 :     psubw mm0, mm1 ; undisplace
505 :     psubw mm3, mm4
506 :    
507 :     movq [edi + 8*ecx], mm0
508 :     movq [edi + 8*ecx + 8], mm3
509 :    
510 :     add ecx, 2
511 :     cmp ecx, 16
512 :     jnz near .q1loop
513 : edgomez 1.1.2.1
514 : edgomez 1.1.2.2 jmp .done
515 : edgomez 1.1.2.1
516 :    
517 :     align ALIGN
518 :     .q2loop
519 : edgomez 1.1.2.2 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
520 :     movq mm3, [esi + 8*ecx+ 8]
521 : edgomez 1.1.2.1 ;
522 : edgomez 1.1.2.2 pxor mm1, mm1 ; mm1 = 0
523 :     pxor mm4, mm4 ;
524 : edgomez 1.1.2.1
525 : edgomez 1.1.2.2 pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
526 :     pcmpgtw mm4, mm3 ;
527 : edgomez 1.1.2.1
528 : edgomez 1.1.2.2 pxor mm0, mm1 ; mm0 = |mm0|
529 :     pxor mm3, mm4 ;
530 :     psubw mm0, mm1 ; displace
531 :     psubw mm3, mm4 ;
532 : edgomez 1.1.2.1
533 : edgomez 1.1.2.2 psllw mm0, 4
534 :     psllw mm3, 4
535 : edgomez 1.1.2.1
536 : edgomez 1.1.2.2 movq mm2, [inter_matrix + 8*ecx]
537 :     psrlw mm2, 1
538 :     paddw mm0, mm2
539 : edgomez 1.1.2.1
540 : edgomez 1.1.2.2 movq mm2, [inter_matrix_fix + ecx*8]
541 :     pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
542 : edgomez 1.1.2.1
543 : edgomez 1.1.2.2 movq mm2, [inter_matrix + 8*ecx + 8]
544 :     psrlw mm2, 1
545 :     paddw mm3, mm2
546 : edgomez 1.1.2.1
547 : edgomez 1.1.2.2 movq mm2, [inter_matrix_fix + ecx*8 + 8]
548 :     pmulhw mm3, mm2
549 : edgomez 1.1.2.1
550 : edgomez 1.1.2.2 psrlw mm0, 2 ; mm0 >>= 1 (/2)
551 :     psrlw mm3, 2 ;
552 : edgomez 1.1.2.1
553 : edgomez 1.1.2.2 paddw mm5, mm0 ; sum += mm0
554 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
555 :     paddw mm5, mm3 ;
556 :     pxor mm3, mm4 ;
557 :     psubw mm0, mm1 ; undisplace
558 :     psubw mm3, mm4
559 : edgomez 1.1.2.1
560 : edgomez 1.1.2.2 movq [edi + 8*ecx], mm0
561 :     movq [edi + 8*ecx + 8], mm3
562 : edgomez 1.1.2.1
563 : edgomez 1.1.2.2 add ecx, 2
564 :     cmp ecx, 16
565 :     jnz near .q2loop
566 : edgomez 1.1.2.1
567 : edgomez 1.1.2.2 jmp .done
568 : edgomez 1.1.2.1
569 :    
570 :     ;===========================================================================
571 :     ;
572 : edgomez 1.1.2.2 ; uint32_t dequant_mpeg_intra_mmx(int16_t *data,
573 :     ; const int16_t const *coeff,
574 :     ; const uint32_t quant,
575 :     ; const uint32_t dcscalar);
576 : edgomez 1.1.2.1 ;
577 :     ;===========================================================================
578 :    
579 :     ; Note: in order to saturate 'easily', we pre-shift the quantifier
580 :     ; by 4. Then, the high-word of (coeff[]*matrix[i]*quant) are used to
581 :     ; build a saturating mask. It is non-zero only when an overflow occured.
582 :     ; We thus avoid packing/unpacking toward double-word.
583 :     ; Moreover, we perform the mult (matrix[i]*quant) first, instead of, e.g.,
584 :     ; (coeff[i]*matrix[i]). This is less prone to overflow if coeff[] are not
585 :     ; checked. Input ranges are: coeff in [-127,127], inter_matrix in [1..255],a
586 :     ; and quant in [1..31].
587 :     ;
588 :     ; The original loop is:
589 :     ;
590 :     %if 0
591 : edgomez 1.1.2.2 movq mm0, [ecx+8*eax + 8*16] ; mm0 = coeff[i]
592 :     pxor mm1, mm1
593 :     pcmpgtw mm1, mm0
594 :     pxor mm0, mm1 ; change sign if negative
595 :     psubw mm0, mm1 ; -> mm0 = abs(coeff[i]), mm1 = sign of coeff[i]
596 :    
597 :     movq mm2, mm7 ; mm2 = quant
598 :     pmullw mm2, [intra_matrix + 8*eax + 8*16 ] ; matrix[i]*quant.
599 :    
600 :     movq mm6, mm2
601 :     pmulhw mm2, mm0 ; high of coeff*(matrix*quant) (should be 0 if no overflow)
602 :     pmullw mm0, mm6 ; low of coeff*(matrix*quant)
603 :    
604 :     pxor mm5, mm5
605 :     pcmpgtw mm2, mm5 ; otherflow?
606 :     psrlw mm2, 5 ; =0 if no clamp, 2047 otherwise
607 :     psrlw mm0, 5
608 :     paddw mm0, mm1 ; start restoring sign
609 :     por mm0, mm2 ; saturate to 2047 if needed
610 :     pxor mm0, mm1 ; finish negating back
611 : edgomez 1.1.2.1
612 : edgomez 1.1.2.2 movq [edx + 8*eax + 8*16], mm0 ; data[i]
613 :     add eax, 1
614 : edgomez 1.1.2.1 %endif
615 :    
616 :     ;********************************************************************
617 :    
618 :     align 16
619 :     cglobal dequant_mpeg_intra_mmx
620 :     dequant_mpeg_intra_mmx:
621 :    
622 : edgomez 1.1.2.2 mov edx, [esp+4] ; data
623 :     mov ecx, [esp+8] ; coeff
624 :     mov eax, [esp+12] ; quant
625 :    
626 :     movq mm7, [mmx_mul_quant + eax*8 - 8]
627 :     mov eax, -16 ; to keep aligned, we regularly process coeff[0]
628 :     psllw mm7, 2 ; << 2. See comment.
629 :     pxor mm6, mm6 ; this is a NOP
630 : edgomez 1.1.2.1
631 :     align 16
632 :     .loop
633 : edgomez 1.1.2.2 movq mm0, [ecx+8*eax + 8*16] ; mm0 = c = coeff[i]
634 :     movq mm3, [ecx+8*eax + 8*16 +8]; mm3 = c' = coeff[i+1]
635 :     pxor mm1, mm1
636 :     pxor mm4, mm4
637 :     pcmpgtw mm1, mm0 ; mm1 = sgn(c)
638 :     movq mm2, mm7 ; mm2 = quant
639 : edgomez 1.1.2.1
640 : edgomez 1.1.2.2 pcmpgtw mm4, mm3 ; mm4 = sgn(c')
641 :     pmullw mm2, [intra_matrix + 8*eax + 8*16 ] ; matrix[i]*quant
642 : edgomez 1.1.2.1
643 : edgomez 1.1.2.2 pxor mm0, mm1 ; negate if negative
644 :     pxor mm3, mm4 ; negate if negative
645 : edgomez 1.1.2.1
646 : edgomez 1.1.2.2 psubw mm0, mm1
647 :     psubw mm3, mm4
648 : edgomez 1.1.2.1
649 :     ; we're short on register, here. Poor pairing...
650 :    
651 : edgomez 1.1.2.2 movq mm5, mm2
652 :     pmullw mm2, mm0 ; low of coeff*(matrix*quant)
653 : edgomez 1.1.2.1
654 : edgomez 1.1.2.2 pmulhw mm0, mm5 ; high of coeff*(matrix*quant)
655 :     movq mm5, mm7 ; mm2 = quant
656 : edgomez 1.1.2.1
657 : edgomez 1.1.2.2 pmullw mm5, [intra_matrix + 8*eax + 8*16 +8] ; matrix[i+1]*quant
658 : edgomez 1.1.2.1
659 : edgomez 1.1.2.2 movq mm6, mm5
660 :     add eax,2 ; z-flag will be tested later
661 : edgomez 1.1.2.1
662 : edgomez 1.1.2.2 pmullw mm6, mm3 ; low of coeff*(matrix*quant)
663 :     pmulhw mm3, mm5 ; high of coeff*(matrix*quant)
664 : edgomez 1.1.2.1
665 : edgomez 1.1.2.2 pcmpgtw mm0, [zero]
666 :     paddusw mm2, mm0
667 :     psrlw mm2, 5
668 : edgomez 1.1.2.1
669 : edgomez 1.1.2.2 pcmpgtw mm3, [zero]
670 :     paddusw mm6, mm3
671 :     psrlw mm6, 5
672 : edgomez 1.1.2.1
673 : edgomez 1.1.2.2 pxor mm2, mm1 ; start negating back
674 :     pxor mm6, mm4 ; start negating back
675 : edgomez 1.1.2.1
676 : edgomez 1.1.2.2 psubusw mm1, mm0
677 :     psubusw mm4, mm3
678 : edgomez 1.1.2.1
679 : edgomez 1.1.2.2 psubw mm2, mm1 ; finish negating back
680 :     psubw mm6, mm4 ; finish negating back
681 : edgomez 1.1.2.1
682 : edgomez 1.1.2.2 movq [edx + 8*eax + 8*16 -2*8 ], mm2 ; data[i]
683 :     movq [edx + 8*eax + 8*16 -2*8 +8], mm6 ; data[i+1]
684 : edgomez 1.1.2.1
685 : edgomez 1.1.2.2 jnz near .loop
686 : edgomez 1.1.2.1
687 :     ; deal with DC
688 :    
689 : edgomez 1.1.2.2 movd mm0, [ecx]
690 :     pmullw mm0, [esp+16] ; dcscalar
691 :     movq mm2, [mmx_32767_minus_2047]
692 :     paddsw mm0, mm2
693 :     psubsw mm0, mm2
694 :     movq mm2, [mmx_32768_minus_2048]
695 :     psubsw mm0, mm2
696 :     paddsw mm0, mm2
697 :     movd eax, mm0
698 :     mov [edx], ax
699 :    
700 :     xor eax, eax
701 :     ret
702 : edgomez 1.1.2.1
703 :     ;===========================================================================
704 :     ;
705 : edgomez 1.1.2.2 ; uint32_t dequant_mpeg_inter_mmx(int16_t * data,
706 :     ; const int16_t * const coeff,
707 :     ; const uint32_t quant);
708 : edgomez 1.1.2.1 ;
709 :     ;===========================================================================
710 :    
711 :     ; Note: We use (2*c + sgn(c) - sgn(-c)) as multiplier
712 :     ; so we handle the 3 cases: c<0, c==0, and c>0 in one shot.
713 :     ; sgn(x) is the result of 'pcmpgtw 0,x': 0 if x>=0, -1 if x<0.
714 :     ; It's mixed with the extraction of the absolute value.
715 :    
716 :     align 16
717 :     cglobal dequant_mpeg_inter_mmx
718 :     dequant_mpeg_inter_mmx:
719 :    
720 : edgomez 1.1.2.2 mov edx, [esp+ 4] ; data
721 :     mov ecx, [esp+ 8] ; coeff
722 :     mov eax, [esp+12] ; quant
723 :     movq mm7, [mmx_mul_quant + eax*8 - 8]
724 :     mov eax, -16
725 :     paddw mm7, mm7 ; << 1
726 :     pxor mm6, mm6 ; mismatch sum
727 : edgomez 1.1.2.1
728 :     align 16
729 :     .loop
730 : edgomez 1.1.2.2 movq mm0, [ecx+8*eax + 8*16 ] ; mm0 = coeff[i]
731 :     movq mm2, [ecx+8*eax + 8*16 +8] ; mm2 = coeff[i+1]
732 :     add eax, 2
733 :    
734 :     pxor mm1, mm1
735 :     pxor mm3, mm3
736 :     pcmpgtw mm1, mm0 ; mm1 = sgn(c) (preserved)
737 :     pcmpgtw mm3, mm2 ; mm3 = sgn(c') (preserved)
738 :     paddsw mm0, mm1 ; c += sgn(c)
739 :     paddsw mm2, mm3 ; c += sgn(c')
740 :     paddw mm0, mm0 ; c *= 2
741 :     paddw mm2, mm2 ; c'*= 2
742 :    
743 :     pxor mm4, mm4
744 :     pxor mm5, mm5
745 :     psubw mm4, mm0 ; -c
746 :     psubw mm5, mm2 ; -c'
747 :     psraw mm4, 16 ; mm4 = sgn(-c)
748 :     psraw mm5, 16 ; mm5 = sgn(-c')
749 :     psubsw mm0, mm4 ; c -= sgn(-c)
750 :     psubsw mm2, mm5 ; c' -= sgn(-c')
751 :     pxor mm0, mm1 ; finish changing sign if needed
752 :     pxor mm2, mm3 ; finish changing sign if needed
753 : edgomez 1.1.2.1
754 :     ; we're short on register, here. Poor pairing...
755 :    
756 : edgomez 1.1.2.2 movq mm4, mm7 ; (matrix*quant)
757 :     pmullw mm4, [inter_matrix + 8*eax + 8*16 -2*8]
758 :     movq mm5, mm4
759 :     pmulhw mm5, mm0 ; high of c*(matrix*quant)
760 :     pmullw mm0, mm4 ; low of c*(matrix*quant)
761 :    
762 :     movq mm4, mm7 ; (matrix*quant)
763 :     pmullw mm4, [inter_matrix + 8*eax + 8*16 -2*8 + 8]
764 :    
765 :     pcmpgtw mm5, [zero]
766 :     paddusw mm0, mm5
767 :     psrlw mm0, 5
768 :     pxor mm0, mm1 ; start restoring sign
769 :     psubusw mm1, mm5
770 :    
771 :     movq mm5, mm4
772 :     pmulhw mm5, mm2 ; high of c*(matrix*quant)
773 :     pmullw mm2, mm4 ; low of c*(matrix*quant)
774 :     psubw mm0, mm1 ; finish restoring sign
775 :    
776 :     pcmpgtw mm5, [zero]
777 :     paddusw mm2, mm5
778 :     psrlw mm2, 5
779 :     pxor mm2, mm3 ; start restoring sign
780 :     psubusw mm3, mm5
781 :     psubw mm2, mm3 ; finish restoring sign
782 :    
783 :     pxor mm6, mm0 ; mismatch control
784 :     movq [edx + 8*eax + 8*16 -2*8 ], mm0 ; data[i]
785 :     pxor mm6, mm2 ; mismatch control
786 :     movq [edx + 8*eax + 8*16 -2*8 +8], mm2 ; data[i+1]
787 : edgomez 1.1.2.1
788 : edgomez 1.1.2.2 jnz near .loop
789 : edgomez 1.1.2.1
790 :     ; mismatch control
791 :    
792 : edgomez 1.1.2.2 movq mm0, mm6
793 :     psrlq mm0, 48
794 :     movq mm1, mm6
795 :     movq mm2, mm6
796 :     psrlq mm1, 32
797 :     pxor mm6, mm0
798 :     psrlq mm2, 16
799 :     pxor mm6, mm1
800 :     pxor mm6, mm2
801 :     movd eax, mm6
802 :     and eax, 1
803 :     xor eax, 1
804 :     xor word [edx + 2*63], ax
805 : edgomez 1.1.2.1
806 : edgomez 1.1.2.2 xor eax, eax
807 :     ret

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