version update
[goodguy/cinelerra.git] / cinelerra-5.1 / mpeg2enc / mblock_sad_mmxe.s
1 ;;; 
2 ;;;  mblock_sad_mmxe.s:  
3 ;;; 
4 ;;; Enhanced MMX optimized Sum Absolute Differences routines for macroblocks
5 ;;; (interpolated, 1-pel, 2*2 sub-sampled pel and 4*4 sub-sampled pel)
6 ;
7 ;  dist1_* Original Copyright (C) 2000 Chris Atenasio <chris@crud.net>
8 ;  Enhancements and rest Copyright (C) 2000 Andrew Stevens <as@comlab.ox.ac.uk>
9
10                 ;; Yes, I tried prefetch-ing.  It makes no difference or makes
11                 ;; stuff *slower*.
12
13 ;
14 ;  This program is free software; you can reaxstribute it and/or
15 ;  modify it under the terms of the GNU General Public License
16 ;  as published by the Free Software Foundation; either version 2
17 ;  of the License, or (at your option) any later version.
18 ;
19 ;  This program is distributed in the hope that it will be useful,
20 ;  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 ;  GNU General Public License for more details.
23 ;
24 ;  You should have received a copy of the GNU General Public License
25 ;  along with this program; if not, write to the Free Software
26 ;  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27 ;
28 ;
29 ;
30
31
32 global dist1_00_mmxe
33
34 ; int dist1_00(char *blk1,char *blk2,int lx,int h,int distlim);
35 ; distlim unused - costs more to check than the savings of
36 ; aborting the computation early from time to time...
37 ; eax = p1
38 ; ebx = p2
39 ; ecx = rowsleft
40 ; edx = lx;
41
42 ; mm0 = distance accumulator
43 ; mm1 = temp
44 ; mm2 = temp
45 ; mm3 = temp
46 ; mm4 = temp
47 ; mm5 = temp
48 ; mm6 = temp
49
50
51 SECTION .text
52 align 32
53 dist1_00_mmxe:
54         push ebp                                        ; save frame pointer
55         mov ebp, esp                            ; link
56
57         push ebx
58         push ecx
59         push edx
60
61         pxor mm0, mm0           ; zero acculumator
62
63         mov eax, [ebp+8]        ; get p1
64 dist1_00_0misalign:             
65         mov ebx, [ebp+12]       ; get p2
66         mov edx, [ebp+16]       ; get lx
67
68         mov ecx, [ebp+20]       ; get rowsleft
69         jmp nextrow00sse
70 align 32
71 nextrow00sse:
72         movq mm4, [eax]         ; load first 8 bytes of p1 (row 1)
73         psadbw mm4, [ebx]       ; compare to first 8 bytes of p2 (row 1)
74         movq mm5, [eax+8]       ; load next 8 bytes of p1 (row 1)
75         add eax, edx            ; update pointer to next row
76         paddd mm0, mm4          ; accumulate difference
77         
78         psadbw mm5, [ebx+8]     ; compare to next 8 bytes of p2 (row 1)
79         add ebx, edx            ; ditto
80         paddd mm0, mm5          ; accumulate difference
81
82
83         movq mm6, [eax]         ; load first 8 bytes of p1 (row 2)
84         psadbw mm6, [ebx]       ; compare to first 8 bytes of p2 (row 2)
85         movq mm4, [eax+8]       ; load next 8 bytes of p1 (row 2)
86         add eax, edx            ; update pointer to next row
87         paddd mm0, mm6          ; accumulate difference
88         
89         psadbw mm4, [ebx+8]     ; compare to next 8 bytes of p2 (row 2)
90         add ebx, edx            ; ditto
91         paddd mm0, mm4          ; accumulate difference
92
93         ;psubd mm2, mm3         ; decrease rowsleft
94         ;movq mm5, mm1          ; copy distlim
95         ;pcmpgtd mm5, mm0       ; distlim > dist?
96         ;pand mm2, mm5          ; mask rowsleft with answer
97         ;movd ecx, mm2          ; move rowsleft to ecx
98
99         ;add eax, edx           ; update pointer to next row
100         ;add ebx, edx           ; ditto
101         
102         ;test ecx, ecx          ; check rowsleft
103         sub  ecx, 2
104         jnz nextrow00sse
105
106         movd eax, mm0           ; store return value
107         
108         pop edx 
109         pop ecx 
110         pop ebx 
111
112         pop ebp 
113         emms
114         ret     
115
116
117                                 
118
119 global dist1_00_Ammxe
120                 ;; This is a special version that only does aligned accesses...
121                 ;; Wonder if it'll make it faster on a P-III
122                 ;; ANSWER:               NO its slower hence no longer used.
123
124 ; int dist1_00(char *blk1,char *blk2,int lx,int h,int distlim);
125 ; distlim unused - costs more to check than the savings of
126 ; aborting the computation early from time to time...
127 ; eax = p1
128 ; ebx = p2
129 ; ecx = rowsleft
130 ; edx = lx;
131
132 ; mm0 = distance accumulator
133 ; mm1 = temp
134 ; mm2 = right shift to adjust for mis-align
135 ; mm3 = left shift to adjust for mis-align
136 ; mm4 = temp
137 ; mm5 = temp
138 ; mm6 = temp
139
140
141 align 32
142 dist1_00_Ammxe:
143         push ebp                                        ; save frame pointer
144         mov ebp, esp                            ; link
145
146         push ebx
147         push ecx
148         push edx
149                 
150         pxor mm0, mm0           ; zero acculumator
151
152         mov eax, [ebp+8]        ; get p1
153         mov ebx, eax
154         and ebx, 7                                      ; Misalignment!
155         cmp ebx, 0
156         jz      near dist1_00_0misalign
157         sub eax, ebx                            ; Align eax
158         mov ecx, 8                                      ; ecx = 8-misalignment
159         sub ecx, ebx
160         shl ebx, 3                                      ; Convert into bit-shifts...
161         shl ecx, 3                                      
162         movd mm2, ebx                           ; mm2 = shift to start msb
163         movd mm3, ecx                           ; mm3 = shift to end lsb
164
165         mov ebx, [ebp+12]       ; get p2
166         mov edx, [ebp+16]       ; get lx
167         mov ecx, [ebp+20]       ; get rowsleft
168         jmp nextrow00ssea
169 align 32
170 nextrow00ssea:
171         movq mm4, [eax]                         ; load first 8 bytes of aligned p1 (row 1)
172         movq mm5, [eax+8]                       ; load next 8 bytes of aligned p1 (row 1)
173         movq mm6, mm5
174         psrlq mm4, mm2                          ; mm4 first 8 bytes of p1 proper
175         psllq mm5, mm3
176         por       mm4, mm5
177         psadbw mm4, [ebx]       ; compare to first 8 bytes of p2 
178
179         movq mm7, [eax+16]                      ; load last 8 bytes of aligned p1
180         add eax, edx            ; update pointer to next row
181         psrlq mm6, mm2                          ; mm6 2nd 8 bytes of p1 proper
182         psllq mm7, mm3
183         por   mm6, mm7
184
185
186         paddd mm0, mm4          ; accumulate difference
187         
188         psadbw mm6, [ebx+8]     ; compare to next 8 bytes of p2 (row 1)
189         add ebx, edx            ; ditto
190         paddd mm0, mm6          ; accumulate difference
191
192         sub  ecx, 1
193         jnz nextrow00ssea
194
195         movd eax, mm0           ; store return value
196
197         pop edx 
198         pop ecx 
199         pop ebx 
200
201         pop ebp 
202         emms
203         ret     
204
205
206 global dist1_01_mmxe
207
208 ; int dist1_01(char *blk1,char *blk2,int lx,int h);
209
210 ; eax = p1
211 ; ebx = p2
212 ; ecx = counter temp
213 ; edx = lx;
214
215 ; mm0 = distance accumulator
216 ; mm1 = distlim
217 ; mm2 = rowsleft
218 ; mm3 = 2 (rows per loop)
219 ; mm4 = temp
220 ; mm5 = temp
221 ; mm6 = temp
222
223
224 align 32
225 dist1_01_mmxe:
226         push ebp        
227         mov ebp, esp
228
229         push ebx
230         push ecx
231         push edx
232
233         pxor mm0, mm0           ; zero acculumator
234
235         mov eax, [ebp+8]        ; get p1
236         mov ebx, [ebp+12]       ; get p2
237         mov edx, [ebp+16]       ; get lx
238
239         mov ecx, [ebp+20]       ; get rowsleft
240         jmp nextrow01           ; snap to it
241 align 32
242 nextrow01:
243         movq mm4, [eax]                         ; load first 8 bytes of p1 (row 1)
244         pavgb mm4, [eax+1]                      ; Interpolate...
245         psadbw mm4, [ebx]                       ; compare to first 8 bytes of p2 (row 1)
246         paddd mm0, mm4                          ; accumulate difference
247
248         movq mm5, [eax+8]                       ; load next 8 bytes of p1 (row 1)
249         pavgb mm5, [eax+9]                      ; Interpolate
250         psadbw mm5, [ebx+8]                     ; compare to next 8 bytes of p2 (row 1)
251         paddd mm0, mm5                          ; accumulate difference
252
253         add eax, edx                            ; update pointer to next row
254         add ebx, edx                            ; ditto
255
256         movq mm6, [eax]                         ; load first 8 bytes of p1 (row 2)
257         pavgb mm6, [eax+1]                      ; Interpolate
258         psadbw mm6, [ebx]       ; compare to first 8 bytes of p2 (row 2)
259         paddd mm0, mm6          ; accumulate difference
260         
261         movq mm7, [eax+8]       ; load next 8 bytes of p1 (row 2)
262         pavgb mm7, [eax+9]
263         psadbw mm7, [ebx+8]     ; compare to next 8 bytes of p2 (row 2)
264         paddd mm0, mm7          ; accumulate difference
265
266         add eax, edx            ; update pointer to next row
267         add ebx, edx            ; ditto
268         
269         sub ecx, 2                      ; check rowsleft
270         jnz nextrow01           ; rinse and repeat
271
272         movd eax, mm0           ; store return value
273         
274         pop edx 
275         pop ecx         
276         pop ebx 
277
278         pop ebp                 ; restore stack pointer
279
280         emms                    ; clear mmx registers
281         ret                     ; we now return you to your regular programming
282
283
284 global dist1_10_mmxe
285
286 ; int dist1_10(char *blk1,char *blk2,int lx,int h);
287
288 ; eax = p1
289 ; ebx = p2
290 ; ecx = counter temp
291 ; edx = lx;
292 ; edi = p1+lx  
293
294 ; mm0 = distance accumulator
295 ; mm2 = rowsleft
296 ; mm3 = 2 (rows per loop)
297 ; mm4 = temp
298 ; mm5 = temp
299 ; mm6 = temp
300
301
302 align 32
303 dist1_10_mmxe:
304         push ebp                ; save stack pointer
305         mov ebp, esp
306
307         push ebx
308         push ecx
309         push edx
310         push edi
311
312         pxor mm0, mm0           ; zero acculumator
313
314         mov eax, [ebp+8]        ; get p1
315         mov ebx, [ebp+12]       ; get p2
316         mov edx, [ebp+16]       ; get lx
317         mov edi, eax
318         add edi, edx
319         mov ecx, [ebp+20]       ; get rowsleft
320         jmp nextrow10           ; snap to it
321 align 32
322 nextrow10:
323         movq mm4, [eax]                         ; load first 8 bytes of p1 (row 1)
324         pavgb mm4, [edi]                        ; Interpolate...
325         psadbw mm4, [ebx]                       ; compare to first 8 bytes of p2 (row 1)
326         paddd mm0, mm4                          ; accumulate difference
327
328         movq mm5, [eax+8]                       ; load next 8 bytes of p1 (row 1)
329         pavgb mm5, [edi+8]                      ; Interpolate
330         psadbw mm5, [ebx+8]                     ; compare to next 8 bytes of p2 (row 1)
331         paddd mm0, mm5                          ; accumulate difference
332
333         add eax, edx                            ; update pointer to next row
334         add ebx, edx                            ; ditto
335         add edi, edx
336
337         movq mm6, [eax]                         ; load first 8 bytes of p1 (row 2)
338         pavgb mm6, [edi]                        ; Interpolate
339         psadbw mm6, [ebx]       ; compare to first 8 bytes of p2 (row 2)
340         paddd mm0, mm6          ; accumulate difference
341         
342         movq mm7, [eax+8]       ; load next 8 bytes of p1 (row 2)
343         pavgb mm7, [edi+8]
344         psadbw mm7, [ebx+8]     ; compare to next 8 bytes of p2 (row 2)
345         paddd mm0, mm7          ; accumulate difference
346
347         psubd mm2, mm3          ; decrease rowsleft
348
349         add eax, edx            ; update pointer to next row
350         add ebx, edx            ; ditto
351         add edi, edx
352         
353         sub ecx, 2                      ; check rowsleft (we're doing 2 at a time)
354         jnz nextrow10           ; rinse and repeat
355
356         movd eax, mm0           ; store return value
357         
358         pop edi
359         pop edx 
360         pop ecx 
361         pop ebx 
362
363         pop ebp                 ; restore stack pointer
364
365         emms                    ; clear mmx registers
366         ret                     ; we now return you to your regular programming
367
368
369 global dist1_11_mmxe
370
371 ; int dist1_11(char *blk1,char *blk2,int lx,int h);
372
373 ; eax = p1
374 ; ebx = p2
375 ; ecx = counter temp
376 ; edx = lx;
377 ; edi = p1+lx  
378
379                   
380 ; mm0 = distance accumulator
381 ; mm2 = rowsleft
382 ; mm3 = 2 (rows per loop)
383 ; mm4 = temp
384 ; mm5 = temp
385 ; mm6 = temp
386
387
388 align 32
389 dist1_11_mmxe:
390         push ebp                ; save stack pointer
391         mov ebp, esp            ; so that we can do this
392
393         push ebx                ; save the pigs
394         push ecx                ; make them squeal
395         push edx                ; lets have pigs for every meal
396         push edi
397
398         pxor mm0, mm0           ; zero acculumator
399
400         mov eax, [ebp+8]        ; get p1
401         mov ebx, [ebp+12]       ; get p2
402         mov edx, [ebp+16]       ; get lx
403         mov edi, eax
404         add edi, edx
405         mov ecx, [ebp+20]       ; get rowsleft
406         jmp nextrow11           ; snap to it
407 align 32
408 nextrow11:
409         movq mm4, [eax]                         ; load first 8 bytes of p1 (row 1)
410         pavgb mm4, [edi]                        ; Interpolate...
411         movq mm5, [eax+1]
412         pavgb mm5, [edi+1]
413         pavgb mm4, mm5
414         psadbw mm4, [ebx]                       ; compare to first 8 bytes of p2 (row 1)
415         paddd mm0, mm4                          ; accumulate difference
416
417         movq mm6, [eax+8]                       ; load next 8 bytes of p1 (row 1)
418         pavgb mm6, [edi+8]                      ; Interpolate
419         movq mm7, [eax+9]
420         pavgb mm7, [edi+9]
421         pavgb mm6, mm7
422         psadbw mm6, [ebx+8]                     ; compare to next 8 bytes of p2 (row 1)
423         paddd mm0, mm6                          ; accumulate difference
424
425         add eax, edx                            ; update pointer to next row
426         add ebx, edx                            ; ditto
427         add edi, edx
428
429         movq mm4, [eax]                         ; load first 8 bytes of p1 (row 1)
430         pavgb mm4, [edi]                        ; Interpolate...
431         movq mm5, [eax+1]
432         pavgb mm5, [edi+1]
433         pavgb mm4, mm5
434         psadbw mm4, [ebx]                       ; compare to first 8 bytes of p2 (row 1)
435         paddd mm0, mm4                          ; accumulate difference
436
437         movq mm6, [eax+8]                       ; load next 8 bytes of p1 (row 1)
438         pavgb mm6, [edi+8]                      ; Interpolate
439         movq mm7, [eax+9]
440         pavgb mm7, [edi+9]
441         pavgb mm6, mm7
442         psadbw mm6, [ebx+8]                     ; compare to next 8 bytes of p2 (row 1)
443         paddd mm0, mm6                          ; accumulate difference
444                 
445         add eax, edx            ; update pointer to next row
446         add ebx, edx            ; ditto
447         add edi, edx
448
449                         
450         sub ecx, 2                              ; check rowsleft
451         jnz near nextrow11                      ; rinse and repeat
452
453         movd eax, mm0                           ; store return value
454         
455         pop edi
456         pop edx 
457         pop ecx         
458         pop ebx                 
459         
460         pop ebp                 ; restore stack pointer
461
462         emms                    ; clear mmx registers
463         ret                     ; we now return you to your regular programming
464
465 global dist22_mmxe
466
467 ; int dist22_mmxe(unsigned char *blk1,unsigned char *blk2,int flx,int fh);
468
469 ; eax = p1
470 ; ebx = p2
471 ; ecx = counter temp
472 ; edx = flx;
473
474 ; mm0 = distance accumulator
475 ; mm2 = rowsleft
476 ; mm3 = 2 (rows per loop)
477 ; mm4 = temp
478 ; mm5 = temp
479 ; mm6 = temp
480
481
482 align 32
483 dist22_mmxe:
484         push ebp                ; save frame pointer
485         mov ebp, esp
486
487         push ebx        
488         push ecx
489         push edx        
490
491         pxor mm0, mm0           ; zero acculumator
492
493         mov eax, [ebp+8]        ; get p1
494         mov ebx, [ebp+12]       ; get p2
495         mov edx, [ebp+16]       ; get lx
496
497         mov ecx, [ebp+20]
498         jmp nextrowfd
499 align 32
500 nextrowfd:
501         movq   mm4, [eax]        ; load first 8 bytes of p1 (row 1) 
502         add eax, edx            ; update pointer to next row
503         psadbw mm4, [ebx]       ; compare to first 8 bytes of p2 (row 1)
504         add ebx, edx            ; ditto
505         paddd  mm0, mm4         ; accumulate difference
506         
507
508         movq mm6, [eax]         ; load first 8 bytes of p1 (row 2)
509         add eax, edx            ; update pointer to next row
510         psadbw mm6, [ebx]       ; compare to first 8 bytes of p2 (row 2)
511         add ebx, edx            ; ditto
512         paddd mm0, mm6          ; accumulate difference
513         
514
515         sub ecx, 2
516         jnz nextrowfd
517
518         movd eax, mm0
519         
520         pop edx 
521         pop ecx 
522         pop ebx 
523
524         pop ebp
525
526         emms
527         ret
528
529
530
531
532
533 global dist44_mmxe
534
535 ; int dist44_mmxe(unsigned char *blk1,unsigned char *blk2,int qlx,int qh);
536
537 ; eax = p1
538 ; ebx = p2
539 ; ecx = temp
540 ; edx = qlx;
541 ; esi = rowsleft
542
543 ; mm0 = distance accumulator left block p1
544 ; mm1 = distance accumulator right block p1
545 ; mm2 = 0
546 ; mm3 = 0
547 ; mm4 = temp
548 ; mm5 = temp
549 ; mm6 = temp
550
551
552 align 32
553 dist44_mmxe:
554         push ebp
555         mov ebp, esp
556
557         push ebx
558         push ecx
559         push edx
560         push esi     
561
562         pxor mm0, mm0           ; zero acculumator
563         pxor mm1, mm1                           
564         pxor mm2, mm2
565         mov eax, [ebp+8]        ; get p1
566         mov ebx, [ebp+12]       ; get p2
567         mov edx, [ebp+16]       ; get qlx
568
569         mov esi, [ebp+20]       ; get rowsleft
570         jmp nextrowqd           ; snap to it
571 align 32
572 nextrowqd: 
573         movq mm4, [eax]                         ; load 8 bytes of p1 (two blocks!)
574         add eax, edx            ; update pointer to next row
575         movq mm6, mm4                             ;
576         mov  ecx, [ebx]       ; load 4 bytes of p2
577     punpcklbw mm4, mm2                  ; mm4 = bytes 0..3 p1 (spaced out)
578         movd mm5, ecx
579         punpcklbw mm5, mm2      ; mm5 = bytes 0..3 p2  (spaced out)
580         psadbw mm4, mm5                 ; compare to left block
581         add ebx, edx            ; ditto
582
583 ;       punpckhbw mm6, mm2          ; mm6 = bytes 4..7 p1 (spaced out)
584
585         paddd mm0, mm4                          ; accumulate difference left block
586
587 ;       psadbw mm6,mm5                          ; compare to right block
588         
589
590 ;       paddd mm1, mm6                          ; accumulate difference right block
591                 
592         sub esi, 1
593         jnz nextrowqd
594
595         movd eax, mm0
596 ;       movd ebx, mm1                           
597 ;       sal  ebx, 16
598 ;       or   eax, ebx
599         
600         pop esi
601         pop edx
602         pop ecx
603         pop ebx
604
605         pop ebp                 ; restore stack pointer
606
607         emms                    ; clear mmx registers
608         ret                     ; we now return you to your regular programming