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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1192 - (view) (download)

1 : edgomez 1192 ;/****************************************************************************
2 : edgomez 1174 ; *
3 :     ; * XVID MPEG-4 VIDEO CODEC
4 : edgomez 1176 ; * - 3dne Quantization/Dequantization -
5 : edgomez 1174 ; *
6 : edgomez 1176 ; * Copyright (C) 2002-2003 Peter Ross <pross@xvid.org>
7 :     ; * 2002 Jaan Kalda
8 : edgomez 1174 ; *
9 :     ; * This program is free software ; you can redistribute it and/or modify
10 :     ; * it under the terms of the GNU General Public License as published by
11 :     ; * the Free Software Foundation ; either version 2 of the License, or
12 :     ; * (at your option) any later version.
13 :     ; *
14 :     ; * This program is distributed in the hope that it will be useful,
15 :     ; * but WITHOUT ANY WARRANTY ; without even the implied warranty of
16 :     ; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 :     ; * GNU General Public License for more details.
18 :     ; *
19 :     ; * You should have received a copy of the GNU General Public License
20 :     ; * along with this program ; if not, write to the Free Software
21 :     ; * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 :     ; *
23 : edgomez 1192 ; * $Id: quantize_mpeg_xmm.asm,v 1.1.2.3 2003-10-28 22:23:03 edgomez Exp $
24 : edgomez 1174 ; *
25 : edgomez 1192 ; ***************************************************************************/
26 : edgomez 1176
27 : edgomez 1174 ; _3dne functions are compatible with iSSE, but are optimized specifically
28 :     ; for K7 pipelines
29 :    
30 :     %define SATURATE
31 :    
32 : edgomez 1192 BITS 32
33 : edgomez 1174
34 : edgomez 1192 %macro cglobal 1
35 : edgomez 1174 %ifdef PREFIX
36 : edgomez 1192 global _%1
37 : edgomez 1174 %define %1 _%1
38 :     %else
39 :     global %1
40 :     %endif
41 :     %endmacro
42 :    
43 : edgomez 1192 %macro cextern 1
44 : edgomez 1174 %ifdef PREFIX
45 : edgomez 1192 extern _%1
46 : edgomez 1174 %define %1 _%1
47 :     %else
48 :     extern %1
49 :     %endif
50 :     %endmacro
51 : edgomez 1176
52 : edgomez 1192 ;=============================================================================
53 : edgomez 1176 ; Local data
54 : edgomez 1192 ;=============================================================================
55 : edgomez 1176
56 : edgomez 1192 SECTION .rodata
57 : edgomez 1176
58 : edgomez 1192 ALIGN 8
59 : edgomez 1176 mmzero:
60 :     dd 0,0
61 :     mmx_one:
62 :     times 4 dw 1
63 : edgomez 1174
64 : edgomez 1192 ;-----------------------------------------------------------------------------
65 :     ; divide by 2Q table
66 :     ;-----------------------------------------------------------------------------
67 : edgomez 1174
68 : edgomez 1192 ALIGN 16
69 : edgomez 1176 mmx_divs: ;i>2
70 : edgomez 1174 %assign i 1
71 :     %rep 31
72 : edgomez 1192 times 4 dw ((1 << 15) / i + 1)
73 : edgomez 1174 %assign i i+1
74 :     %endrep
75 :    
76 : edgomez 1192 ALIGN 16
77 :     mmx_div: ;quant>2
78 :     times 4 dw 65535 ; the div by 2 formula will overflow for the case
79 :     ; quant=1 but we don't care much because quant=1
80 :     ; is handled by a different piece of code that
81 :     ; doesn't use this table.
82 :     %assign quant 2
83 : edgomez 1174 %rep 31
84 : edgomez 1192 times 4 dw ((1 << 16) / quant + 1)
85 :     %assign quant quant+1
86 : edgomez 1174 %endrep
87 :    
88 :    
89 : edgomez 1192 ;-----------------------------------------------------------------------------
90 :     ; intra matrix
91 :     ; (TODO remove dependency on external tables for instance safiness)
92 :     ;-----------------------------------------------------------------------------
93 : edgomez 1174
94 :     %macro FIXX 1
95 :     dw (1 << 16) / (%1) + 1
96 : edgomez 1192 %endmacro
97 : edgomez 1174
98 :     cextern intra_matrix_fixl
99 :     cextern intra_matrix_fix
100 :     cextern intra_matrix1
101 :     cextern intra_matrix
102 :    
103 : edgomez 1192 ;-----------------------------------------------------------------------------
104 : edgomez 1174 ; inter matrix
105 : edgomez 1192 ; (TODO remove dependency on external tables for instance safiness)
106 :     ;-----------------------------------------------------------------------------
107 : edgomez 1174
108 :     cextern inter_matrix1
109 :     cextern inter_matrix
110 :     cextern inter_matrix_fix
111 :     cextern inter_matrix_fixl
112 :    
113 :    
114 : edgomez 1176 %define nop4 db 08Dh, 074h, 026h,0
115 :     %define nop3 add esp, byte 0
116 :     %define nop2 mov esp, esp
117 :     %define nop7 db 08dh, 02ch, 02dh,0,0,0,0
118 :     %define nop6 add ebp, dword 0
119 : edgomez 1174
120 : edgomez 1192 ;-----------------------------------------------------------------------------
121 :     ; quantd table
122 :     ;-----------------------------------------------------------------------------
123 : edgomez 1174
124 : edgomez 1176 %define VM18P 3
125 :     %define VM18Q 4
126 : edgomez 1174
127 : edgomez 1192 ALIGN 16
128 : edgomez 1176 quantd:
129 : edgomez 1174 %assign i 1
130 :     %rep 31
131 :     times 4 dw (((VM18P*i) + (VM18Q/2)) / VM18Q)
132 :     %assign i i+1
133 :     %endrep
134 :    
135 : edgomez 1192 ;-----------------------------------------------------------------------------
136 : edgomez 1174 ; multiple by 2Q table
137 : edgomez 1192 ;-----------------------------------------------------------------------------
138 : edgomez 1174
139 : edgomez 1192 ALIGN 16
140 :     mmx_mul_quant:
141 : edgomez 1174 %assign i 1
142 :     %rep 31
143 :     times 4 dw i
144 :     %assign i i+1
145 :     %endrep
146 :    
147 : edgomez 1192 ;-----------------------------------------------------------------------------
148 :     ; saturation limits
149 :     ;-----------------------------------------------------------------------------
150 : edgomez 1174
151 : edgomez 1192 ALIGN 16
152 : edgomez 1176 mmx_32767_minus_2047:
153 : edgomez 1192 times 4 dw (32767-2047)
154 : edgomez 1176 mmx_32768_minus_2048:
155 :     times 4 dw (32768-2048)
156 :     mmx_2047:
157 :     times 4 dw 2047
158 :     mmx_minus_2048:
159 :     times 4 dw (-2048)
160 :     zero:
161 :     times 4 dw 0
162 : edgomez 1174
163 : edgomez 1176 int_div:
164 : edgomez 1174 dd 0
165 :     %assign i 1
166 : edgomez 1192 %rep 255
167 : edgomez 1174 dd (1 << 17) / ( i) + 1
168 :     %assign i i+1
169 :     %endrep
170 :    
171 : edgomez 1192 ;=============================================================================
172 : edgomez 1176 ; Code
173 : edgomez 1192 ;=============================================================================
174 : edgomez 1176
175 : edgomez 1192 SECTION .text
176 : edgomez 1174
177 : edgomez 1192 cglobal quant_mpeg_intra_xmm
178 :     cglobal quant_mpeg_inter_xmm
179 :     cglobal dequant_mpeg_intra_3dne
180 :     cglobal dequant_mpeg_inter_3dne
181 :    
182 :     ;-----------------------------------------------------------------------------
183 : edgomez 1174 ;
184 : edgomez 1192 ; uint32_t quant_mpeg_intra_xmm(int16_t * coeff,
185 : edgomez 1176 ; const int16_t const * data,
186 :     ; const uint32_t quant,
187 :     ; const uint32_t dcscalar);
188 : edgomez 1174 ;
189 : edgomez 1192 ;-----------------------------------------------------------------------------
190 : edgomez 1174
191 : edgomez 1192 ALIGN 16
192 : edgomez 1174 quant_mpeg_intra_xmm:
193 : edgomez 1192 mov eax, [esp + 8] ; data
194 :     mov ecx, [esp + 12] ; quant
195 :     mov edx, [esp + 4] ; coeff
196 :     push esi
197 :     push edi
198 :     push ebx
199 :     nop
200 :     mov edi, mmzero
201 :     mov esi, -14
202 :     pxor mm0, mm0
203 :     pxor mm3, mm3
204 :     cmp ecx, byte 1
205 :     je near .q1loop
206 :     cmp ecx, byte 19
207 :     jg near .lloop
208 :     nop6
209 :    
210 :     ALIGN 16
211 : edgomez 1174 .loop
212 : edgomez 1192 movq mm1, [eax + 8*esi+112] ; mm0 = [1st]
213 :     psubw mm0, mm1 ;-mm1
214 :     movq mm4, [eax + 8*esi + 120] ;
215 :     psubw mm3, mm4 ;-mm4
216 :     pmaxsw mm0, mm1 ;|src|
217 :     pmaxsw mm3,mm4
218 :     nop2
219 :     psraw mm1, 15 ;sign src
220 :     psraw mm4, 15
221 :     psllw mm0, 4 ;level << 4 ;
222 :     psllw mm3, 4
223 :     paddw mm0, [intra_matrix1 + 8*esi+112]
224 :     paddw mm3, [intra_matrix1 + 8*esi+120]
225 :     movq mm5, [intra_matrix_fixl + 8*esi+112]
226 :     movq mm7, [intra_matrix_fixl + 8*esi+120]
227 :     pmulhuw mm5, mm0
228 :     pmulhuw mm7, mm3
229 :     mov esp, esp
230 :     movq mm2, [intra_matrix + 8*esi+112]
231 :     movq mm6, [intra_matrix + 8*esi+120]
232 :     pmullw mm2, mm5
233 :     pmullw mm6, mm7
234 :     psubw mm0, mm2
235 :     psubw mm3, mm6
236 :     nop4
237 :     movq mm2, [quantd + ecx * 8 - 8]
238 :     movq mm6, [mmx_divs + ecx * 8 - 8]
239 :     paddw mm5, mm2
240 :     paddw mm7, mm2
241 :     mov esp, esp
242 :     pmulhuw mm0, [intra_matrix_fix + 8*esi+112]
243 :     pmulhuw mm3, [intra_matrix_fix + 8*esi+120]
244 :     paddw mm5, mm0
245 :     paddw mm7, mm3
246 :     movq mm0, [edi]
247 :     movq mm3, [edi]
248 :     pmulhuw mm5, mm6 ; mm0 = (mm0 / 2Q) >> 16
249 :     pmulhuw mm7, mm6 ; (level + quantd) / quant (0<quant<32)
250 :     pxor mm5, mm1 ; mm0 *= sign(mm0)
251 :     pxor mm7, mm4 ;
252 :     psubw mm5, mm1 ; undisplace
253 :     psubw mm7, mm4 ;
254 :     movq [edx + 8*esi+112], mm5
255 :     movq [edx + 8*esi +120], mm7
256 :     add esi, byte 2
257 :     jng near .loop
258 : edgomez 1174
259 :     .done
260 :     ; calculate data[0] // (int32_t)dcscalar)
261 : edgomez 1192 mov esi, [esp + 12 + 16] ; dcscalar
262 :     movsx ecx, word [eax]
263 :     mov edi, ecx
264 :     mov edx, [esp + 12 + 16]
265 :     shr edx, 1 ; ebx = dcscalar /2
266 :     sar edi, 31 ; cdq is vectorpath
267 :     xor edx, edi ; ebx = eax V -eax -1
268 :     sub ecx, edi
269 :     add ecx, edx
270 :     mov edx, [dword esp + 12 + 4]
271 :     mov esi, [int_div+4*esi]
272 :     imul ecx, esi
273 :     sar ecx, 17
274 :     lea ebx, [byte ecx + 1]
275 :     cmovs ecx, ebx
276 :     ; idiv cx ; ecx = edi:ecx / dcscalar
277 : edgomez 1174
278 : edgomez 1192 mov ebx, [esp]
279 :     mov edi, [esp+4]
280 :     mov esi, [esp+8]
281 :     add esp, byte 12
282 :     mov [edx], cx ; coeff[0] = ax
283 : edgomez 1174
284 : edgomez 1192 xor eax, eax
285 :     ret
286 :    
287 :     ALIGN 16
288 : edgomez 1174 .q1loop
289 : edgomez 1192 movq mm1, [eax + 8*esi+112] ; mm0 = [1st]
290 :     psubw mm0, mm1 ;-mm1
291 :     movq mm4, [eax + 8*esi+120] ;
292 :     psubw mm3, mm4 ;-mm4
293 :     pmaxsw mm0, mm1 ;|src|
294 :     pmaxsw mm3, mm4
295 :     nop2
296 :     psraw mm1, 15 ;sign src
297 :     psraw mm4, 15
298 :     psllw mm0, 4 ; level << 4
299 :     psllw mm3, 4
300 :     paddw mm0, [intra_matrix1 + 8*esi+112] ;mm0 is to be divided
301 :     paddw mm3, [intra_matrix1 + 8*esi+120] ;intra1 contains fix for division by 1
302 :     movq mm5, [intra_matrix_fixl + 8*esi+112] ;with rounding down
303 :     movq mm7, [intra_matrix_fixl + 8*esi+120]
304 :     pmulhuw mm5, mm0
305 :     pmulhuw mm7, mm3 ;mm7: first approx of division
306 :     mov esp, esp
307 :     movq mm2, [intra_matrix + 8*esi+112]
308 :     movq mm6, [intra_matrix + 8*esi+120] ; divs for q<=16
309 :     pmullw mm2, mm5 ;test value <= original
310 :     pmullw mm6, mm7
311 :     psubw mm0, mm2 ;mismatch
312 :     psubw mm3, mm6
313 :     nop4
314 :     movq mm2, [quantd + ecx * 8 - 8]
315 :     paddw mm5, mm2 ;first approx with quantd
316 :     paddw mm7, mm2
317 :     mov esp, esp
318 :     pmulhuw mm0, [intra_matrix_fix + 8*esi+112] ;correction
319 :     pmulhuw mm3, [intra_matrix_fix + 8*esi+120]
320 :     paddw mm5, mm0 ;final result with quantd
321 :     paddw mm7, mm3
322 :     movq mm0, [edi]
323 :     movq mm3, [edi]
324 :     mov esp, esp
325 :     psrlw mm5, 1 ; (level + quantd) /2 (quant = 1)
326 :     psrlw mm7, 1
327 :     pxor mm5, mm1 ; mm0 *= sign(mm0)
328 :     pxor mm7, mm4 ;
329 :     psubw mm5, mm1 ; undisplace
330 :     psubw mm7, mm4 ;
331 :     movq [edx + 8*esi+112], mm5
332 :     movq [edx + 8*esi +120], mm7
333 :     add esi, byte 2
334 :     jng near .q1loop
335 :     jmp near .done
336 : edgomez 1174
337 : edgomez 1192 ALIGN 8
338 : edgomez 1174 .lloop
339 : edgomez 1192 movq mm1, [eax + 8*esi+112] ; mm0 = [1st]
340 :     psubw mm0, mm1 ;-mm1
341 :     movq mm4, [eax + 8*esi+120]
342 :     psubw mm3, mm4 ;-mm4
343 :     pmaxsw mm0, mm1 ;|src|
344 :     pmaxsw mm3, mm4
345 :     nop2
346 :     psraw mm1, 15 ;sign src
347 :     psraw mm4, 15
348 :     psllw mm0, 4 ; level << 4
349 :     psllw mm3, 4 ;
350 :     paddw mm0, [intra_matrix1 + 8*esi+112] ;mm0 is to be divided intra1 contains fix for division by 1
351 :     paddw mm3, [intra_matrix1 + 8*esi+120]
352 :     movq mm5, [intra_matrix_fixl + 8*esi+112]
353 :     movq mm7, [intra_matrix_fixl + 8*esi+120]
354 :     pmulhuw mm5, mm0
355 :     pmulhuw mm7, mm3 ;mm7: first approx of division
356 :     mov esp, esp
357 :     movq mm2, [intra_matrix + 8*esi+112]
358 :     movq mm6, [intra_matrix + 8*esi+120]
359 :     pmullw mm2, mm5 ;test value <= original
360 :     pmullw mm6, mm7
361 :     psubw mm0, mm2 ;mismatch
362 :     psubw mm3, mm6
363 :     nop4
364 :     movq mm2, [quantd + ecx * 8 - 8]
365 :     movq mm6, [mmx_div + ecx * 8 - 8] ; divs for q<=16
366 :     paddw mm5, mm2 ;first approx with quantd
367 :     paddw mm7, mm2
368 :     mov esp, esp
369 :     pmulhuw mm0, [intra_matrix_fix + 8*esi+112] ;correction
370 :     pmulhuw mm3, [intra_matrix_fix + 8*esi+120]
371 :     paddw mm5, mm0 ;final result with quantd
372 :     paddw mm7, mm3
373 :     movq mm0, [edi]
374 :     movq mm3, [edi]
375 :     mov esp, esp
376 :     pmulhuw mm5, mm6 ; mm0 = (mm0 / 2Q) >> 16
377 :     pmulhuw mm7, mm6 ; (level + quantd) / quant (0<quant<32)
378 :     psrlw mm5, 1 ; (level + quantd) / (2*quant)
379 :     psrlw mm7, 1
380 :     pxor mm5, mm1 ; mm0 *= sign(mm0)
381 :     pxor mm7, mm4 ;
382 :     psubw mm5, mm1 ; undisplace
383 :     psubw mm7, mm4 ;
384 :     movq [edx + 8*esi+112], mm5
385 :     movq [edx + 8*esi +120], mm7
386 :     add esi,byte 2
387 :     jng near .lloop
388 :     jmp near .done
389 : edgomez 1174
390 : edgomez 1192 ;-----------------------------------------------------------------------------
391 : edgomez 1174 ;
392 : edgomez 1176 ; uint32_t quant_mpeg_inter_xmm(int16_t * coeff,
393 :     ; const int16_t const * data,
394 :     ; const uint32_t quant);
395 : edgomez 1174 ;
396 : edgomez 1192 ;-----------------------------------------------------------------------------
397 : edgomez 1174
398 : edgomez 1192 ALIGN 16
399 : edgomez 1174 quant_mpeg_inter_xmm:
400 : edgomez 1192 mov eax, [esp + 8] ; data
401 :     mov ecx, [esp + 12] ; quant
402 :     mov edx, [esp + 4] ; coeff
403 :     push esi
404 :     push edi
405 :     push ebx
406 :     nop
407 :     mov edi, mmzero
408 :     mov esi, -14
409 :     mov ebx, esp
410 :     sub esp, byte 24
411 :     lea ebx, [esp+8]
412 :     and ebx, byte -8 ;ALIGN 8
413 :     pxor mm0, mm0
414 :     pxor mm3, mm3
415 :     movq [byte ebx],mm0
416 :     db 0Fh, 7Fh, 44h, 23h, 8 ;movq [ebx+8],mm0
417 :     cmp ecx, byte 1
418 :     je near .q1loop
419 :     cmp ecx, byte 19
420 :     jg near .lloop
421 :     nop
422 :    
423 :     ALIGN 16
424 : edgomez 1174 .loop
425 : edgomez 1192 movq mm1, [eax + 8*esi+112] ; mm0 = [1st]
426 :     psubw mm0, mm1 ;-mm1
427 :     movq mm4, [eax + 8*esi + 120] ;
428 :     psubw mm3, mm4 ;-mm4
429 :     pmaxsw mm0, mm1 ;|src|
430 :     pmaxsw mm3, mm4
431 :     nop2
432 :     psraw mm1, 15 ;sign src
433 :     psraw mm4, 15
434 :     psllw mm0, 4 ; level << 4
435 :     psllw mm3, 4 ;
436 :     paddw mm0, [inter_matrix1 + 8*esi+112]
437 :     paddw mm3, [inter_matrix1 + 8*esi+120]
438 :     movq mm5, [inter_matrix_fixl + 8*esi+112]
439 :     movq mm7, [inter_matrix_fixl + 8*esi+120]
440 :     pmulhuw mm5, mm0
441 :     pmulhuw mm7, mm3
442 :     mov esp, esp
443 :     movq mm2, [inter_matrix + 8*esi+112]
444 :     movq mm6, [inter_matrix + 8*esi+120]
445 :     pmullw mm2, mm5
446 :     pmullw mm6, mm7
447 :     psubw mm0, mm2
448 :     psubw mm3, mm6
449 :     movq mm2, [byte ebx]
450 :     movq mm6, [mmx_divs + ecx * 8 - 8]
451 :     pmulhuw mm0, [inter_matrix_fix + 8*esi+112]
452 :     pmulhuw mm3, [inter_matrix_fix + 8*esi+120]
453 :     paddw mm2, [ebx+8] ;sum
454 :     paddw mm5, mm0
455 :     paddw mm7, mm3
456 :     movq mm0, [edi]
457 :     movq mm3, [edi]
458 :     pmulhuw mm5, mm6 ; mm0 = (mm0 / 2Q) >> 16
459 :     pmulhuw mm7, mm6 ; (level ) / quant (0<quant<32)
460 :     add esi, byte 2
461 :     paddw mm2, mm5 ;sum += x1
462 :     movq [ebx], mm7 ;store x2
463 :     pxor mm5, mm1 ; mm0 *= sign(mm0)
464 :     pxor mm7, mm4 ;
465 :     psubw mm5, mm1 ; undisplace
466 :     psubw mm7, mm4 ;
467 :     db 0Fh, 7Fh, 54h, 23h, 08 ;movq [ebx+8],mm2 ;store sum
468 :     movq [edx + 8*esi+112-16], mm5
469 :     movq [edx + 8*esi +120-16], mm7
470 :     jng near .loop
471 : edgomez 1174
472 :     .done
473 :     ; calculate data[0] // (int32_t)dcscalar)
474 : edgomez 1192 paddw mm2, [ebx]
475 :     mov ebx, [esp+24]
476 :     mov edi, [esp+4+24]
477 :     mov esi, [esp+8+24]
478 :     add esp, byte 12+24
479 :     pmaddwd mm2, [mmx_one]
480 :     punpckldq mm0, mm2 ;get low dw to mm0:high
481 :     paddd mm0,mm2
482 :     punpckhdq mm0, mm0 ;get result to low
483 :     movd eax, mm0
484 : edgomez 1174
485 : edgomez 1192 ret
486 : edgomez 1174
487 : edgomez 1192 ALIGN 16
488 : edgomez 1174 .q1loop
489 : edgomez 1192 movq mm1, [eax + 8*esi+112] ; mm0 = [1st]
490 :     psubw mm0, mm1 ;-mm1
491 :     movq mm4, [eax + 8*esi+120]
492 :     psubw mm3, mm4 ;-mm4
493 :     pmaxsw mm0, mm1 ;|src|
494 :     pmaxsw mm3, mm4
495 :     nop2
496 :     psraw mm1, 15 ; sign src
497 :     psraw mm4, 15
498 :     psllw mm0, 4 ; level << 4
499 :     psllw mm3, 4
500 :     paddw mm0, [inter_matrix1 + 8*esi+112] ;mm0 is to be divided
501 :     paddw mm3, [inter_matrix1 + 8*esi+120] ; inter1 contains fix for division by 1
502 :     movq mm5, [inter_matrix_fixl + 8*esi+112] ;with rounding down
503 :     movq mm7, [inter_matrix_fixl + 8*esi+120]
504 :     pmulhuw mm5, mm0
505 :     pmulhuw mm7, mm3 ;mm7: first approx of division
506 :     mov esp, esp
507 :     movq mm2, [inter_matrix + 8*esi+112]
508 :     movq mm6, [inter_matrix + 8*esi+120] ; divs for q<=16
509 :     pmullw mm2, mm5 ;test value <= original
510 :     pmullw mm6, mm7
511 :     psubw mm0, mm2 ;mismatch
512 :     psubw mm3, mm6
513 :     movq mm2, [byte ebx]
514 :     pmulhuw mm0, [inter_matrix_fix + 8*esi+112] ;correction
515 :     pmulhuw mm3, [inter_matrix_fix + 8*esi+120]
516 :     paddw mm2, [ebx+8] ;sum
517 :     paddw mm5, mm0 ;final result
518 :     paddw mm7, mm3
519 :     movq mm0, [edi]
520 :     movq mm3, [edi]
521 :     psrlw mm5, 1 ; (level ) /2 (quant = 1)
522 :     psrlw mm7, 1
523 :     add esi, byte 2
524 :     paddw mm2, mm5 ;sum += x1
525 :     movq [ebx], mm7 ;store x2
526 :     pxor mm5, mm1 ; mm0 *= sign(mm0)
527 :     pxor mm7, mm4 ;
528 :     psubw mm5, mm1 ; undisplace
529 :     psubw mm7, mm4 ;
530 :     movq [ebx+8], mm2 ;store sum
531 :     movq [edx + 8*esi+112-16], mm5
532 :     movq [edx + 8*esi +120-16], mm7
533 :     jng near .q1loop
534 :     jmp near .done
535 : edgomez 1174
536 : edgomez 1192 ALIGN 8
537 : edgomez 1174 .lloop
538 : edgomez 1192 movq mm1, [eax + 8*esi+112] ; mm0 = [1st]
539 :     psubw mm0,mm1 ;-mm1
540 :     movq mm4, [eax + 8*esi+120]
541 :     psubw mm3,mm4 ;-mm4
542 :     pmaxsw mm0,mm1 ;|src|
543 :     pmaxsw mm3,mm4
544 :     nop2
545 :     psraw mm1,15 ;sign src
546 :     psraw mm4,15
547 :     psllw mm0, 4 ; level << 4
548 :     psllw mm3, 4 ;
549 :     paddw mm0, [inter_matrix1 + 8*esi+112] ;mm0 is to be divided inter1 contains fix for division by 1
550 :     paddw mm3, [inter_matrix1 + 8*esi+120]
551 :     movq mm5,[inter_matrix_fixl + 8*esi+112]
552 :     movq mm7,[inter_matrix_fixl + 8*esi+120]
553 :     pmulhuw mm5,mm0
554 :     pmulhuw mm7,mm3 ;mm7: first approx of division
555 :     mov esp,esp
556 :     movq mm2,[inter_matrix + 8*esi+112]
557 :     movq mm6,[inter_matrix + 8*esi+120]
558 :     pmullw mm2,mm5 ;test value <= original
559 :     pmullw mm6,mm7
560 :     psubw mm0,mm2 ;mismatch
561 :     psubw mm3,mm6
562 :     movq mm2,[byte ebx]
563 :     movq mm6,[mmx_div + ecx * 8 - 8] ; divs for q<=16
564 :     pmulhuw mm0,[inter_matrix_fix + 8*esi+112] ;correction
565 :     pmulhuw mm3,[inter_matrix_fix + 8*esi+120]
566 :     paddw mm2,[ebx+8] ;sum
567 :     paddw mm5,mm0 ;final result
568 :     paddw mm7,mm3
569 :     movq mm0,[edi]
570 :     movq mm3,[edi]
571 :     pmulhuw mm5, mm6 ; mm0 = (mm0 / 2Q) >> 16
572 :     pmulhuw mm7, mm6 ; (level ) / quant (0<quant<32)
573 :     add esi,byte 2
574 :     psrlw mm5, 1 ; (level ) / (2*quant)
575 :     paddw mm2,mm5 ;sum += x1
576 :     psrlw mm7, 1
577 :     movq [ebx],mm7 ;store x2
578 :     pxor mm5, mm1 ; mm0 *= sign(mm0)
579 :     pxor mm7, mm4 ;
580 :     psubw mm5, mm1 ; undisplace
581 :     psubw mm7, mm4 ;
582 :     db 0Fh, 7Fh, 54h, 23h, 08 ;movq [ebx+8],mm2 ;store sum
583 :     movq [edx + 8*esi+112-16], mm5
584 :     movq [edx + 8*esi +120-16], mm7
585 :     jng near .lloop
586 :     jmp near .done
587 : edgomez 1174
588 :    
589 : edgomez 1192 ;-----------------------------------------------------------------------------
590 : edgomez 1174 ;
591 : edgomez 1176 ; uint32_t dequant_mpeg_intra_3dne(int16_t *data,
592 :     ; const int16_t const *coeff,
593 :     ; const uint32_t quant,
594 :     ; const uint32_t dcscalar);
595 : edgomez 1174 ;
596 : edgomez 1192 ;-----------------------------------------------------------------------------
597 : edgomez 1174
598 :     ; Note: in order to saturate 'easily', we pre-shift the quantifier
599 :     ; by 4. Then, the high-word of (coeff[]*matrix[i]*quant) are used to
600 :     ; build a saturating mask. It is non-zero only when an overflow occured.
601 :     ; We thus avoid packing/unpacking toward double-word.
602 :     ; Moreover, we perform the mult (matrix[i]*quant) first, instead of, e.g.,
603 :     ; (coeff[i]*matrix[i]). This is less prone to overflow if coeff[] are not
604 :     ; checked. Input ranges are: coeff in [-127,127], inter_matrix in [1..255],a
605 : edgomez 1192 ; and quant in [1..31].
606 : edgomez 1174 ;
607 : edgomez 1176
608 : edgomez 1174 %macro DEQUANT4INTRAMMX 1
609 : edgomez 1192 movq mm1, [byte ecx+ 16 * %1] ; mm0 = c = coeff[i]
610 :     movq mm4, [ecx+ 16 * %1 +8] ; mm3 = c' = coeff[i+1]
611 :     psubw mm0, mm1
612 :     psubw mm3, mm4
613 :     pmaxsw mm0, mm1
614 :     pmaxsw mm3, mm4
615 :     psraw mm1, 15
616 :     psraw mm4, 15
617 :     %if %1
618 :     movq mm2, [eax+8] ;preshifted quant
619 :     movq mm7, [eax+8]
620 : edgomez 1174 %endif
621 : edgomez 1192 pmullw mm2, [intra_matrix + 16 * %1 ] ; matrix[i]*quant
622 :     pmullw mm7, [intra_matrix + 16 * %1 +8] ; matrix[i+1]*quant
623 :     movq mm5, mm0
624 :     movq mm6, mm3
625 :     pmulhw mm0, mm2 ; high of coeff*(matrix*quant)
626 :     pmulhw mm3, mm7 ; high of coeff*(matrix*quant)
627 :     pmullw mm2, mm5 ; low of coeff*(matrix*quant)
628 :     pmullw mm7, mm6 ; low of coeff*(matrix*quant)
629 :     pcmpgtw mm0, [eax]
630 :     pcmpgtw mm3, [eax]
631 :     paddusw mm2, mm0
632 :     paddusw mm7, mm3
633 :     psrlw mm2, 5
634 :     psrlw mm7, 5
635 :     pxor mm2, mm1 ; start negating back
636 :     pxor mm7, mm4 ; start negating back
637 :     psubusw mm1, mm0
638 :     psubusw mm4, mm3
639 :     movq mm0, [eax] ;zero
640 :     movq mm3, [eax] ;zero
641 :     psubw mm2, mm1 ; finish negating back
642 :     psubw mm7, mm4 ; finish negating back
643 :     movq [byte edx + 16 * %1], mm2 ; data[i]
644 :     movq [edx + 16 * %1 +8], mm7 ; data[i+1]
645 : edgomez 1174 %endmacro
646 :    
647 : edgomez 1192 ALIGN 16
648 : edgomez 1174 dequant_mpeg_intra_3dne:
649 : edgomez 1192 mov eax, [esp+12] ; quant
650 :     mov ecx, [esp+8] ; coeff
651 :     movq mm7, [mmx_mul_quant + eax*8 - 8]
652 :     psllw mm7, 2 ; << 2. See comment.
653 :     mov edx, [esp+4] ; data
654 :     push ebx
655 :     movsx ebx, word [ecx]
656 :     pxor mm0, mm0
657 :     pxor mm3, mm3
658 :     push esi
659 :     lea eax, [esp-28]
660 :     sub esp, byte 32
661 :     and eax, byte -8 ;points to qword ALIGNed space on stack
662 :     movq [eax], mm0
663 :     movq [eax+8], mm7
664 :     imul ebx, [esp+16+8+32] ; dcscalar
665 :     movq mm2, mm7
666 : edgomez 1174
667 : edgomez 1192 ALIGN 4
668 : edgomez 1174
669 : edgomez 1192 DEQUANT4INTRAMMX 0
670 : edgomez 1174
671 : edgomez 1192 mov esi, -2048
672 :     nop
673 :     cmp ebx, esi
674 : edgomez 1174
675 : edgomez 1192 DEQUANT4INTRAMMX 1
676 : edgomez 1174
677 : edgomez 1192 cmovl ebx, esi
678 :     neg esi
679 :     sub esi, byte 1 ;2047
680 : edgomez 1174
681 : edgomez 1192 DEQUANT4INTRAMMX 2
682 : edgomez 1174
683 : edgomez 1192 cmp ebx, esi
684 :     cmovg ebx, esi
685 :     lea ebp, [byte ebp]
686 : edgomez 1174
687 : edgomez 1192 DEQUANT4INTRAMMX 3
688 : edgomez 1174
689 : edgomez 1192 mov esi, [esp+32]
690 :     mov [byte edx], bx
691 :     mov ebx, [esp+32+4]
692 : edgomez 1174
693 : edgomez 1192 DEQUANT4INTRAMMX 4
694 :     DEQUANT4INTRAMMX 5
695 :     DEQUANT4INTRAMMX 6
696 :     DEQUANT4INTRAMMX 7
697 : edgomez 1174
698 : edgomez 1192 add esp, byte 32+8
699 : edgomez 1174
700 : edgomez 1192 xor eax, eax
701 :     ret
702 :    
703 :     ;-----------------------------------------------------------------------------
704 : edgomez 1174 ;
705 : edgomez 1176 ; uint32_t dequant_mpeg_inter_3dne(int16_t * data,
706 :     ; const int16_t * const coeff,
707 :     ; const uint32_t quant);
708 : edgomez 1174 ;
709 : edgomez 1192 ;-----------------------------------------------------------------------------
710 : edgomez 1174
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 : edgomez 1192 ALIGN 16
717 : edgomez 1174 dequant_mpeg_inter_3dne:
718 : edgomez 1192 mov edx, [esp+ 4] ; data
719 :     mov ecx, [esp+ 8] ; coeff
720 :     mov eax, [esp+12] ; quant
721 :     movq mm7, [mmx_mul_quant + eax*8 - 8]
722 :     mov eax, -14
723 :     paddw mm7, mm7 ; << 1
724 :     pxor mm6, mm6 ; mismatch sum
725 :     push esi
726 :     mov esi, mmzero
727 :     pxor mm1, mm1
728 :     pxor mm3, mm3
729 :     nop
730 :     nop4
731 : edgomez 1174
732 : edgomez 1192 ALIGN 16
733 : edgomez 1174 .loop
734 : edgomez 1192 movq mm0, [ecx+8*eax + 7*16 ] ; mm0 = coeff[i]
735 :     pcmpgtw mm1, mm0 ; mm1 = sgn(c) (preserved)
736 :     movq mm2, [ecx+8*eax + 7*16 +8] ; mm2 = coeff[i+1]
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 : edgomez 1174
743 : edgomez 1192 movq mm4, [esi]
744 :     movq mm5, [esi]
745 :     psubw mm4, mm0 ; -c
746 :     psubw mm5, mm2 ; -c'
747 : edgomez 1174
748 : edgomez 1192 psraw mm4, 16 ; mm4 = sgn(-c)
749 :     psraw mm5, 16 ; mm5 = sgn(-c')
750 :     psubsw mm0, mm4 ; c -= sgn(-c)
751 :     psubsw mm2, mm5 ; c' -= sgn(-c')
752 :     pxor mm0, mm1 ; finish changing sign if needed
753 :     pxor mm2, mm3 ; finish changing sign if needed
754 : edgomez 1174
755 : edgomez 1192 ; we're short on register, here. Poor pairing...
756 : edgomez 1174
757 : edgomez 1192 movq mm4, mm7 ; (matrix*quant)
758 :     nop
759 :     pmullw mm4, [inter_matrix + 8*eax + 7*16]
760 :     movq mm5, mm4
761 :     pmulhw mm5, mm0 ; high of c*(matrix*quant)
762 :     pmullw mm0, mm4 ; low of c*(matrix*quant)
763 : edgomez 1174
764 : edgomez 1192 movq mm4, mm7 ; (matrix*quant)
765 :     pmullw mm4, [inter_matrix + 8*eax + 7*16 + 8]
766 :     add eax, byte 2
767 : edgomez 1174
768 : edgomez 1192 pcmpgtw mm5, [esi]
769 :     paddusw mm0, mm5
770 :     psrlw mm0, 5
771 :     pxor mm0, mm1 ; start restoring sign
772 :     psubusw mm1, mm5
773 : edgomez 1174
774 : edgomez 1192 movq mm5, mm4
775 :     pmulhw mm5, mm2 ; high of c*(matrix*quant)
776 :     pmullw mm2, mm4 ; low of c*(matrix*quant)
777 :     psubw mm0, mm1 ; finish restoring sign
778 : edgomez 1174
779 : edgomez 1192 pcmpgtw mm5, [esi]
780 :     paddusw mm2, mm5
781 :     psrlw mm2, 5
782 :     pxor mm2, mm3 ; start restoring sign
783 :     psubusw mm3, mm5
784 :     psubw mm2, mm3 ; finish restoring sign
785 :     movq mm1, [esi]
786 :     movq mm3, [byte esi]
787 :     pxor mm6, mm0 ; mismatch control
788 :     movq [edx + 8*eax + 7*16 -2*8 ], mm0 ; data[i]
789 :     pxor mm6, mm2 ; mismatch control
790 :     movq [edx + 8*eax + 7*16 -2*8 +8], mm2 ; data[i+1]
791 : edgomez 1174
792 : edgomez 1192 jng .loop
793 :     nop
794 : edgomez 1174
795 : edgomez 1192 ; mismatch control
796 : edgomez 1174
797 : edgomez 1192 pshufw mm0, mm6, 01010101b
798 :     pshufw mm1, mm6, 10101010b
799 :     pshufw mm2, mm6, 11111111b
800 :     pxor mm6, mm0
801 :     pxor mm1, mm2
802 :     pxor mm6, mm1
803 :     movd eax, mm6
804 :     and eax, byte 1
805 :     xor eax, byte 1
806 :     mov esi, [esp]
807 :     add esp, byte 4
808 :     xor word [edx + 2*63], ax
809 : edgomez 1174
810 : edgomez 1192 xor eax, eax
811 :     ret

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