[svn] / branches / dev-api-4 / xvidcore / src / quant / x86_asm / quantize_mpeg_mmx.asm Repository:
ViewVC logotype

Annotation of /branches/dev-api-4/xvidcore/src/quant/x86_asm/quantize_mpeg_mmx.asm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1198 - (view) (download)

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

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