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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (view) (download)

1 : Isibaar 3 ;/**************************************************************************
2 :     ; *
3 :     ; * XVID MPEG-4 VIDEO CODEC
4 :     ; * mmx quantization/dequantization
5 :     ; *
6 :     ; * This program is an implementation of a part of one or more MPEG-4
7 :     ; * Video tools as specified in ISO/IEC 14496-2 standard. Those intending
8 :     ; * to use this software module in hardware or software products are
9 :     ; * advised that its use may infringe existing patents or copyrights, and
10 :     ; * any such use would be at such party's own risk. The original
11 :     ; * developer of this software module and his/her company, and subsequent
12 :     ; * editors and their companies, will have no liability for use of this
13 :     ; * software or modifications or derivatives thereof.
14 :     ; *
15 :     ; * This program is free software; you can redistribute it and/or modify
16 :     ; * it under the terms of the GNU General Public License as published by
17 :     ; * the Free Software Foundation; either version 2 of the License, or
18 :     ; * (at your option) any later version.
19 :     ; *
20 :     ; * This program is distributed in the hope that it will be useful,
21 :     ; * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 :     ; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 :     ; * GNU General Public License for more details.
24 :     ; *
25 :     ; * You should have received a copy of the GNU General Public License
26 :     ; * along with this program; if not, write to the Free Software
27 :     ; * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 :     ; *
29 :     ; *************************************************************************/
30 :    
31 :     ;/**************************************************************************
32 :     ; *
33 :     ; * History:
34 :     ; *
35 :     ; * 26.12.2001 minor bug fixes, dequant saturate, further optimization
36 :     ; * 19.11.2001 quant_inter_mmx now returns sum of abs. coefficient values
37 :     ; * 04.11.2001 nasm version; (c)2001 peter ross <pross@cs.rmit.edu.au>
38 :     ; *
39 :     ; *************************************************************************/
40 :    
41 :     ; enable dequant saturate [-2048,2047], test purposes only.
42 :     %define SATURATE
43 :    
44 :     ; data/text alignment
45 :     %define ALIGN 8
46 :    
47 :     bits 32
48 :    
49 :     section .data
50 :    
51 :    
52 :     %macro cglobal 1
53 :     %ifdef PREFIX
54 :     global _%1
55 :     %define %1 _%1
56 :     %else
57 :     global %1
58 :     %endif
59 :     %endmacro
60 :    
61 :     plus_one times 4 dw 1
62 :    
63 :     ;===========================================================================
64 :     ;
65 :     ; subtract by Q/2 table
66 :     ;
67 :     ;===========================================================================
68 :    
69 :     %macro MMX_SUB 1
70 :     times 4 dw %1 / 2
71 :     %endmacro
72 :    
73 :     align ALIGN
74 :     mmx_sub
75 :     MMX_SUB 1
76 :     MMX_SUB 2
77 :     MMX_SUB 3
78 :     MMX_SUB 4
79 :     MMX_SUB 5
80 :     MMX_SUB 6
81 :     MMX_SUB 7
82 :     MMX_SUB 8
83 :     MMX_SUB 9
84 :     MMX_SUB 10
85 :     MMX_SUB 11
86 :     MMX_SUB 12
87 :     MMX_SUB 13
88 :     MMX_SUB 14
89 :     MMX_SUB 15
90 :     MMX_SUB 16
91 :     MMX_SUB 17
92 :     MMX_SUB 18
93 :     MMX_SUB 19
94 :     MMX_SUB 20
95 :     MMX_SUB 21
96 :     MMX_SUB 22
97 :     MMX_SUB 23
98 :     MMX_SUB 24
99 :     MMX_SUB 25
100 :     MMX_SUB 26
101 :     MMX_SUB 27
102 :     MMX_SUB 28
103 :     MMX_SUB 29
104 :     MMX_SUB 30
105 :     MMX_SUB 31
106 :    
107 :    
108 :    
109 :     ;===========================================================================
110 :     ;
111 :     ; divide by 2Q table
112 :     ;
113 :     ; use a shift of 16 to take full advantage of _pmulhw_
114 :     ; for q=1, _pmulhw_ will overflow so it is treated seperately
115 :     ; (3dnow2 provides _pmulhuw_ which wont cause overflow)
116 :     ;
117 :     ;===========================================================================
118 :    
119 :     %macro MMX_DIV 1
120 :     times 4 dw (1 << 16) / (%1 * 2) + 1
121 :     %endmacro
122 :    
123 :     align ALIGN
124 :     mmx_div
125 :     MMX_DIV 1
126 :     MMX_DIV 2
127 :     MMX_DIV 3
128 :     MMX_DIV 4
129 :     MMX_DIV 5
130 :     MMX_DIV 6
131 :     MMX_DIV 7
132 :     MMX_DIV 8
133 :     MMX_DIV 9
134 :     MMX_DIV 10
135 :     MMX_DIV 11
136 :     MMX_DIV 12
137 :     MMX_DIV 13
138 :     MMX_DIV 14
139 :     MMX_DIV 15
140 :     MMX_DIV 16
141 :     MMX_DIV 17
142 :     MMX_DIV 18
143 :     MMX_DIV 19
144 :     MMX_DIV 20
145 :     MMX_DIV 21
146 :     MMX_DIV 22
147 :     MMX_DIV 23
148 :     MMX_DIV 24
149 :     MMX_DIV 25
150 :     MMX_DIV 26
151 :     MMX_DIV 27
152 :     MMX_DIV 28
153 :     MMX_DIV 29
154 :     MMX_DIV 30
155 :     MMX_DIV 31
156 :    
157 :    
158 :    
159 :     ;===========================================================================
160 :     ;
161 :     ; add by (odd(Q) ? Q : Q - 1) table
162 :     ;
163 :     ;===========================================================================
164 :    
165 :     %macro MMX_ADD 1
166 :     %if %1 % 2 != 0
167 :     times 4 dw %1
168 :     %else
169 :     times 4 dw %1 - 1
170 :     %endif
171 :     %endmacro
172 :    
173 :     align ALIGN
174 :     mmx_add
175 :     MMX_ADD 1
176 :     MMX_ADD 2
177 :     MMX_ADD 3
178 :     MMX_ADD 4
179 :     MMX_ADD 5
180 :     MMX_ADD 6
181 :     MMX_ADD 7
182 :     MMX_ADD 8
183 :     MMX_ADD 9
184 :     MMX_ADD 10
185 :     MMX_ADD 11
186 :     MMX_ADD 12
187 :     MMX_ADD 13
188 :     MMX_ADD 14
189 :     MMX_ADD 15
190 :     MMX_ADD 16
191 :     MMX_ADD 17
192 :     MMX_ADD 18
193 :     MMX_ADD 19
194 :     MMX_ADD 20
195 :     MMX_ADD 21
196 :     MMX_ADD 22
197 :     MMX_ADD 23
198 :     MMX_ADD 24
199 :     MMX_ADD 25
200 :     MMX_ADD 26
201 :     MMX_ADD 27
202 :     MMX_ADD 28
203 :     MMX_ADD 29
204 :     MMX_ADD 30
205 :     MMX_ADD 31
206 :    
207 :    
208 :     ;===========================================================================
209 :     ;
210 :     ; multiple by 2Q table
211 :     ;
212 :     ;===========================================================================
213 :    
214 :     %macro MMX_MUL 1
215 :     times 4 dw %1 * 2
216 :     %endmacro
217 :    
218 :     align ALIGN
219 :     mmx_mul
220 :     MMX_MUL 1
221 :     MMX_MUL 2
222 :     MMX_MUL 3
223 :     MMX_MUL 4
224 :     MMX_MUL 5
225 :     MMX_MUL 6
226 :     MMX_MUL 7
227 :     MMX_MUL 8
228 :     MMX_MUL 9
229 :     MMX_MUL 10
230 :     MMX_MUL 11
231 :     MMX_MUL 12
232 :     MMX_MUL 13
233 :     MMX_MUL 14
234 :     MMX_MUL 15
235 :     MMX_MUL 16
236 :     MMX_MUL 17
237 :     MMX_MUL 18
238 :     MMX_MUL 19
239 :     MMX_MUL 20
240 :     MMX_MUL 21
241 :     MMX_MUL 22
242 :     MMX_MUL 23
243 :     MMX_MUL 24
244 :     MMX_MUL 25
245 :     MMX_MUL 26
246 :     MMX_MUL 27
247 :     MMX_MUL 28
248 :     MMX_MUL 29
249 :     MMX_MUL 30
250 :     MMX_MUL 31
251 :    
252 :    
253 :     ;===========================================================================
254 :     ;
255 :     ; saturation limits
256 :     ;
257 :     ;===========================================================================
258 :    
259 :     align ALIGN
260 :     mmx_32768_minus_2048 times 4 dw (32768-2048)
261 :     mmx_32767_minus_2047 times 4 dw (32767-2047)
262 :    
263 :    
264 :     section .text
265 :    
266 :    
267 :     ;===========================================================================
268 :     ;
269 :     ; void quant_intra_mmx(int16_t * coeff,
270 :     ; const int16_t const * data,
271 :     ; const uint32_t quant,
272 :     ; const uint32_t dcscalar);
273 :     ;
274 :     ;===========================================================================
275 :    
276 :     align ALIGN
277 :     cglobal quant_intra_mmx
278 :     quant_intra_mmx
279 :    
280 :     push ecx
281 :     push esi
282 :     push edi
283 :    
284 :     mov edi, [esp + 12 + 4] ; coeff
285 :     mov esi, [esp + 12 + 8] ; data
286 :     mov eax, [esp + 12 + 12] ; quant
287 :    
288 :     xor ecx, ecx
289 :     cmp al, 1
290 :     jz .q1loop
291 :    
292 :     movq mm7, [mmx_div + eax * 8 - 8]
293 :     align ALIGN
294 :     .loop
295 :     movq mm0, [esi + 8*ecx] ; mm0 = [1st]
296 :     movq mm3, [esi + 8*ecx + 8] ;
297 :     pxor mm1, mm1 ; mm1 = 0
298 :     pxor mm4, mm4 ;
299 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
300 :     pcmpgtw mm4, mm3 ;
301 :     pxor mm0, mm1 ; mm0 = |mm0|
302 :     pxor mm3, mm4 ;
303 :     psubw mm0, mm1 ; displace
304 :     psubw mm3, mm4 ;
305 :     pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16
306 :     pmulhw mm3, mm7 ;
307 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
308 :     pxor mm3, mm4 ;
309 :     psubw mm0, mm1 ; undisplace
310 :     psubw mm3, mm4 ;
311 :     movq [edi + 8*ecx], mm0
312 :     movq [edi + 8*ecx + 8], mm3
313 :    
314 :     add ecx,2
315 :     cmp ecx,16
316 :     jnz .loop
317 :    
318 :     .done
319 :     ; caclulate data[0] // (int32_t)dcscalar)
320 :    
321 :     mov ecx, [esp + 12 + 16] ; dcscalar
322 :     mov edx, ecx
323 :     movsx eax, word [esi] ; data[0]
324 :     shr edx, 1 ; edx = dcscalar /2
325 :     cmp eax, 0
326 :     jg .gtzero
327 :    
328 :     sub eax, edx
329 :     jmp short .mul
330 :     .gtzero
331 :     add eax, edx
332 :     .mul
333 :     cdq ; expand eax -> edx:eax
334 :     idiv ecx ; eax = edx:eax / dcscalar
335 :    
336 :     mov [edi], ax ; coeff[0] = ax
337 :    
338 :     pop edi
339 :     pop esi
340 :     pop ecx
341 :    
342 :     ret
343 :    
344 :     align ALIGN
345 :     .q1loop
346 :     movq mm0, [esi + 8*ecx] ; mm0 = [1st]
347 :     movq mm3, [esi + 8*ecx + 8] ;
348 :     pxor mm1, mm1 ; mm1 = 0
349 :     pxor mm4, mm4 ;
350 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
351 :     pcmpgtw mm4, mm3 ;
352 :     pxor mm0, mm1 ; mm0 = |mm0|
353 :     pxor mm3, mm4 ;
354 :     psubw mm0, mm1 ; displace
355 :     psubw mm3, mm4 ;
356 :     psrlw mm0, 1 ; mm0 >>= 1 (/2)
357 :     psrlw mm3, 1 ;
358 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
359 :     pxor mm3, mm4 ;
360 :     psubw mm0, mm1 ; undisplace
361 :     psubw mm3, mm4 ;
362 :     movq [edi + 8*ecx], mm0
363 :     movq [edi + 8*ecx + 8], mm3
364 :    
365 :     add ecx,2
366 :     cmp ecx,16
367 :     jnz .q1loop
368 :     jmp short .done
369 :    
370 :    
371 :    
372 :     ;===========================================================================
373 :     ;
374 :     ; uint32_t quant_inter_mmx(int16_t * coeff,
375 :     ; const int16_t const * data,
376 :     ; const uint32_t quant);
377 :     ;
378 :     ;===========================================================================
379 :    
380 :     align ALIGN
381 :     cglobal quant_inter_mmx
382 :     quant_inter_mmx
383 :    
384 :     push ecx
385 :     push esi
386 :     push edi
387 :    
388 :     mov edi, [esp + 12 + 4] ; coeff
389 :     mov esi, [esp + 12 + 8] ; data
390 :     mov eax, [esp + 12 + 12] ; quant
391 :    
392 :     xor ecx, ecx
393 :    
394 :     pxor mm5, mm5 ; sum
395 :     movq mm6, [mmx_sub + eax * 8 - 8] ; sub
396 :    
397 :     cmp al, 1
398 :     jz .q1loop
399 :    
400 :     movq mm7, [mmx_div + eax * 8 - 8] ; divider
401 :    
402 :     align ALIGN
403 :     .loop
404 :     movq mm0, [esi + 8*ecx] ; mm0 = [1st]
405 :     movq mm3, [esi + 8*ecx + 8] ;
406 :     pxor mm1, mm1 ; mm1 = 0
407 :     pxor mm4, mm4 ;
408 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
409 :     pcmpgtw mm4, mm3 ;
410 :     pxor mm0, mm1 ; mm0 = |mm0|
411 :     pxor mm3, mm4 ;
412 :     psubw mm0, mm1 ; displace
413 :     psubw mm3, mm4 ;
414 :     psubusw mm0, mm6 ; mm0 -= sub (unsigned, dont go < 0)
415 :     psubusw mm3, mm6 ;
416 :     pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16
417 :     pmulhw mm3, mm7 ;
418 :     paddw mm5, mm0 ; sum += mm0
419 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
420 :     paddw mm5, mm3 ;
421 :     pxor mm3, mm4 ;
422 :     psubw mm0, mm1 ; undisplace
423 :     psubw mm3, mm4
424 :     movq [edi + 8*ecx], mm0
425 :     movq [edi + 8*ecx + 8], mm3
426 :    
427 :     add ecx, 2
428 :     cmp ecx, 16
429 :     jnz .loop
430 :    
431 :     .done
432 :     pmaddwd mm5, [plus_one]
433 :     movq mm0, mm5
434 :     psrlq mm5, 32
435 :     paddd mm0, mm5
436 :     movd eax, mm0 ; return sum
437 :    
438 :     pop edi
439 :     pop esi
440 :     pop ecx
441 :    
442 :     ret
443 :    
444 :     align ALIGN
445 :     .q1loop
446 :     movq mm0, [esi + 8*ecx] ; mm0 = [1st]
447 :     movq mm3, [esi + 8*ecx+ 8] ;
448 :     pxor mm1, mm1 ; mm1 = 0
449 :     pxor mm4, mm4 ;
450 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
451 :     pcmpgtw mm4, mm3 ;
452 :     pxor mm0, mm1 ; mm0 = |mm0|
453 :     pxor mm3, mm4 ;
454 :     psubw mm0, mm1 ; displace
455 :     psubw mm3, mm4 ;
456 :     psubusw mm0, mm6 ; mm0 -= sub (unsigned, dont go < 0)
457 :     psubusw mm3, mm6 ;
458 :     psrlw mm0, 1 ; mm0 >>= 1 (/2)
459 :     psrlw mm3, 1 ;
460 :     paddw mm5, mm0 ; sum += mm0
461 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
462 :     paddw mm5, mm3 ;
463 :     pxor mm3, mm4 ;
464 :     psubw mm0, mm1 ; undisplace
465 :     psubw mm3, mm4
466 :     movq [edi + 8*ecx], mm0
467 :     movq [edi + 8*ecx + 8], mm3
468 :    
469 :     add ecx,2
470 :     cmp ecx,16
471 :     jnz .q1loop
472 :    
473 :     jmp .done
474 :    
475 :    
476 :    
477 :     ;===========================================================================
478 :     ;
479 :     ; void dequant_intra_mmx(int16_t *data,
480 :     ; const int16_t const *coeff,
481 :     ; const uint32_t quant,
482 :     ; const uint32_t dcscalar);
483 :     ;
484 :     ;===========================================================================
485 :    
486 :     align ALIGN
487 :     cglobal dequant_intra_mmx
488 :     dequant_intra_mmx
489 :    
490 :     push esi
491 :     push edi
492 :    
493 :     mov edi, [esp + 8 + 4] ; data
494 :     mov esi, [esp + 8 + 8] ; coeff
495 :     mov eax, [esp + 8 + 12] ; quant
496 :    
497 :     movq mm6, [mmx_add + eax * 8 - 8]
498 :     movq mm7, [mmx_mul + eax * 8 - 8]
499 :     xor eax, eax
500 :    
501 :     align ALIGN
502 :     .loop
503 :     movq mm0, [esi + 8*eax] ; mm0 = [coeff]
504 :     movq mm3, [esi + 8*eax + 8] ;
505 :     pxor mm1, mm1 ; mm1 = 0
506 :     pxor mm4, mm4 ;
507 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
508 :     pcmpgtw mm4, mm3 ;
509 :     pxor mm2, mm2 ; mm2 = 0
510 :     pxor mm5, mm5 ;
511 :     pcmpeqw mm2, mm0 ; mm2 = (0 == mm0)
512 :     pcmpeqw mm5, mm3 ;
513 :     pandn mm2, mm6 ; mm2 = (iszero ? 0 : add)
514 :     pandn mm5, mm6 ;
515 :     pxor mm0, mm1 ; mm0 = |mm0|
516 :     pxor mm3, mm4 ;
517 :     psubw mm0, mm1 ; displace
518 :     psubw mm3, mm4 ;
519 :     pmullw mm0, mm7 ; mm0 *= 2Q
520 :     pmullw mm3, mm7 ;
521 :     paddw mm0, mm2 ; mm0 += mm2 (add)
522 :     paddw mm3, mm5 ;
523 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
524 :     pxor mm3, mm4 ;
525 :     psubw mm0, mm1 ; undisplace
526 :     psubw mm3, mm4
527 :    
528 :     %ifdef SATURATE
529 :     movq mm2, [mmx_32767_minus_2047]
530 :     movq mm4, [mmx_32768_minus_2048]
531 :     paddsw mm0, mm2
532 :     paddsw mm3, mm2
533 :     psubsw mm0, mm2
534 :     psubsw mm3, mm2
535 :     psubsw mm0, mm4
536 :     psubsw mm3, mm4
537 :     paddsw mm0, mm4
538 :     paddsw mm3, mm4
539 :     %endif
540 :    
541 :     movq [edi + 8*eax], mm0 ; [data] = mm0
542 :     movq [edi + 8*eax + 8], mm3
543 :    
544 :     add eax, 2
545 :     cmp eax, 16
546 :     jnz near .loop
547 :    
548 :     mov ax, [esi] ; ax = data[0]
549 :     imul ax, [esp + 8 + 16] ; eax = data[0] * dcscalar
550 :    
551 :     %ifdef SATURATE
552 :     cmp ax, -2048
553 :     jl .set_n2048
554 :     cmp ax, 2047
555 :     jg .set_2047
556 :     %endif
557 :     mov [edi], ax
558 :    
559 :     pop edi
560 :     pop esi
561 :     ret
562 :    
563 :     %ifdef SATURATE
564 :     align ALIGN
565 :     .set_n2048
566 :     mov word [edi], -2048
567 :     pop edi
568 :     pop esi
569 :     ret
570 :    
571 :     align ALIGN
572 :     .set_2047
573 :     mov word [edi], 2047
574 :     pop edi
575 :     pop esi
576 :     ret
577 :     %endif
578 :    
579 :     ;===========================================================================
580 :     ;
581 :     ; void dequant_inter_mmx(int16_t * data,
582 :     ; const int16_t * const coeff,
583 :     ; const uint32_t quant);
584 :     ;
585 :     ;===========================================================================
586 :    
587 :     align ALIGN
588 :     cglobal dequant_inter_mmx
589 :     dequant_inter_mmx
590 :    
591 :     push esi
592 :     push edi
593 :    
594 :     mov edi, [esp + 8 + 4] ; data
595 :     mov esi, [esp + 8 + 8] ; coeff
596 :     mov eax, [esp + 8 + 12] ; quant
597 :     movq mm6, [mmx_add + eax * 8 - 8]
598 :     movq mm7, [mmx_mul + eax * 8 - 8]
599 :    
600 :     xor eax, eax
601 :    
602 :     align ALIGN
603 :     .loop
604 :     movq mm0, [esi + 8*eax] ; mm0 = [coeff]
605 :     movq mm3, [esi + 8*eax + 8] ;
606 :     pxor mm1, mm1 ; mm1 = 0
607 :     pxor mm4, mm4 ;
608 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
609 :     pcmpgtw mm4, mm3 ;
610 :     pxor mm2, mm2 ; mm2 = 0
611 :     pxor mm5, mm5 ;
612 :     pcmpeqw mm2, mm0 ; mm2 = (0 == mm0)
613 :     pcmpeqw mm5, mm3 ;
614 :     pandn mm2, mm6 ; mm2 = (iszero ? 0 : add)
615 :     pandn mm5, mm6 ;
616 :     pxor mm0, mm1 ; mm0 = |mm0|
617 :     pxor mm3, mm4 ;
618 :     psubw mm0, mm1 ; displace
619 :     psubw mm3, mm4 ;
620 :     pmullw mm0, mm7 ; mm0 *= 2Q
621 :     pmullw mm3, mm7 ;
622 :     paddw mm0, mm2 ; mm0 += mm2 (add)
623 :     paddw mm3, mm5 ;
624 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
625 :     pxor mm3, mm4 ;
626 :     psubw mm0, mm1 ; undisplace
627 :     psubw mm3, mm4
628 :    
629 :     %ifdef SATURATE
630 :     movq mm2, [mmx_32767_minus_2047]
631 :     movq mm4, [mmx_32768_minus_2048]
632 :     paddsw mm0, mm2
633 :     paddsw mm3, mm2
634 :     psubsw mm0, mm2
635 :     psubsw mm3, mm2
636 :     psubsw mm0, mm4
637 :     psubsw mm3, mm4
638 :     paddsw mm0, mm4
639 :     paddsw mm3, mm4
640 :     %endif
641 :    
642 :     movq [edi + 8*eax], mm0
643 :     movq [edi + 8*eax + 8], mm3
644 :    
645 :     add eax, 2
646 :     cmp eax, 16
647 :     jnz near .loop
648 :    
649 :     pop edi
650 :     pop esi
651 :    
652 :     ret

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