| Index: simd/jdsample-mmx.asm
 | 
| diff --git a/simd/jdsample-mmx.asm b/simd/jdsample-mmx.asm
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..c9e2b8bafdfd45e8a257483136fd530d94197890
 | 
| --- /dev/null
 | 
| +++ b/simd/jdsample-mmx.asm
 | 
| @@ -0,0 +1,737 @@
 | 
| +;
 | 
| +; jdsample.asm - upsampling (MMX)
 | 
| +;
 | 
| +; Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
 | 
| +;
 | 
| +; Based on
 | 
| +; x86 SIMD extension for IJG JPEG library
 | 
| +; Copyright (C) 1999-2006, MIYASAKA Masaru.
 | 
| +; For conditions of distribution and use, see copyright notice in jsimdext.inc
 | 
| +;
 | 
| +; This file should be assembled with NASM (Netwide Assembler),
 | 
| +; can *not* be assembled with Microsoft's MASM or any compatible
 | 
| +; assembler (including Borland's Turbo Assembler).
 | 
| +; NASM is available from http://nasm.sourceforge.net/ or
 | 
| +; http://sourceforge.net/project/showfiles.php?group_id=6208
 | 
| +;
 | 
| +; [TAB8]
 | 
| +
 | 
| +%include "jsimdext.inc"
 | 
| +
 | 
| +; --------------------------------------------------------------------------
 | 
| +        SECTION SEG_CONST
 | 
| +
 | 
| +        alignz  16
 | 
| +        global  EXTN(jconst_fancy_upsample_mmx)
 | 
| +
 | 
| +EXTN(jconst_fancy_upsample_mmx):
 | 
| +
 | 
| +PW_ONE          times 4 dw  1
 | 
| +PW_TWO          times 4 dw  2
 | 
| +PW_THREE        times 4 dw  3
 | 
| +PW_SEVEN        times 4 dw  7
 | 
| +PW_EIGHT        times 4 dw  8
 | 
| +
 | 
| +        alignz  16
 | 
| +
 | 
| +; --------------------------------------------------------------------------
 | 
| +        SECTION SEG_TEXT
 | 
| +        BITS    32
 | 
| +;
 | 
| +; Fancy processing for the common case of 2:1 horizontal and 1:1 vertical.
 | 
| +;
 | 
| +; The upsampling algorithm is linear interpolation between pixel centers,
 | 
| +; also known as a "triangle filter".  This is a good compromise between
 | 
| +; speed and visual quality.  The centers of the output pixels are 1/4 and 3/4
 | 
| +; of the way between input pixel centers.
 | 
| +;
 | 
| +; GLOBAL(void)
 | 
| +; jsimd_h2v1_fancy_upsample_mmx (int max_v_samp_factor,
 | 
| +;                                JDIMENSION downsampled_width,
 | 
| +;                                JSAMPARRAY input_data,
 | 
| +;                                JSAMPARRAY *output_data_ptr);
 | 
| +;
 | 
| +
 | 
| +%define max_v_samp(b)           (b)+8           ; int max_v_samp_factor
 | 
| +%define downsamp_width(b)       (b)+12          ; JDIMENSION downsampled_width
 | 
| +%define input_data(b)           (b)+16          ; JSAMPARRAY input_data
 | 
| +%define output_data_ptr(b)      (b)+20          ; JSAMPARRAY *output_data_ptr
 | 
| +
 | 
| +        align   16
 | 
| +        global  EXTN(jsimd_h2v1_fancy_upsample_mmx)
 | 
| +
 | 
| +EXTN(jsimd_h2v1_fancy_upsample_mmx):
 | 
| +        push    ebp
 | 
| +        mov     ebp,esp
 | 
| +        pushpic ebx
 | 
| +;       push    ecx             ; need not be preserved
 | 
| +;       push    edx             ; need not be preserved
 | 
| +        push    esi
 | 
| +        push    edi
 | 
| +
 | 
| +        get_GOT ebx             ; get GOT address
 | 
| +
 | 
| +        mov     eax, JDIMENSION [downsamp_width(ebp)]  ; colctr
 | 
| +        test    eax,eax
 | 
| +        jz      near .return
 | 
| +
 | 
| +        mov     ecx, INT [max_v_samp(ebp)]      ; rowctr
 | 
| +        test    ecx,ecx
 | 
| +        jz      near .return
 | 
| +
 | 
| +        mov     esi, JSAMPARRAY [input_data(ebp)]       ; input_data
 | 
| +        mov     edi, POINTER [output_data_ptr(ebp)]
 | 
| +        mov     edi, JSAMPARRAY [edi]                   ; output_data
 | 
| +        alignx  16,7
 | 
| +.rowloop:
 | 
| +        push    eax                     ; colctr
 | 
| +        push    edi
 | 
| +        push    esi
 | 
| +
 | 
| +        mov     esi, JSAMPROW [esi]     ; inptr
 | 
| +        mov     edi, JSAMPROW [edi]     ; outptr
 | 
| +
 | 
| +        test    eax, SIZEOF_MMWORD-1
 | 
| +        jz      short .skip
 | 
| +        mov     dl, JSAMPLE [esi+(eax-1)*SIZEOF_JSAMPLE]
 | 
| +        mov     JSAMPLE [esi+eax*SIZEOF_JSAMPLE], dl    ; insert a dummy sample
 | 
| +.skip:
 | 
| +        pxor    mm0,mm0                 ; mm0=(all 0's)
 | 
| +        pcmpeqb mm7,mm7
 | 
| +        psrlq   mm7,(SIZEOF_MMWORD-1)*BYTE_BIT
 | 
| +        pand    mm7, MMWORD [esi+0*SIZEOF_MMWORD]
 | 
| +
 | 
| +        add     eax, byte SIZEOF_MMWORD-1
 | 
| +        and     eax, byte -SIZEOF_MMWORD
 | 
| +        cmp     eax, byte SIZEOF_MMWORD
 | 
| +        ja      short .columnloop
 | 
| +        alignx  16,7
 | 
| +
 | 
| +.columnloop_last:
 | 
| +        pcmpeqb mm6,mm6
 | 
| +        psllq   mm6,(SIZEOF_MMWORD-1)*BYTE_BIT
 | 
| +        pand    mm6, MMWORD [esi+0*SIZEOF_MMWORD]
 | 
| +        jmp     short .upsample
 | 
| +        alignx  16,7
 | 
| +
 | 
| +.columnloop:
 | 
| +        movq    mm6, MMWORD [esi+1*SIZEOF_MMWORD]
 | 
| +        psllq   mm6,(SIZEOF_MMWORD-1)*BYTE_BIT
 | 
| +
 | 
| +.upsample:
 | 
| +        movq    mm1, MMWORD [esi+0*SIZEOF_MMWORD]
 | 
| +        movq    mm2,mm1
 | 
| +        movq    mm3,mm1                 ; mm1=( 0 1 2 3 4 5 6 7)
 | 
| +        psllq   mm2,BYTE_BIT            ; mm2=( - 0 1 2 3 4 5 6)
 | 
| +        psrlq   mm3,BYTE_BIT            ; mm3=( 1 2 3 4 5 6 7 -)
 | 
| +
 | 
| +        por     mm2,mm7                 ; mm2=(-1 0 1 2 3 4 5 6)
 | 
| +        por     mm3,mm6                 ; mm3=( 1 2 3 4 5 6 7 8)
 | 
| +
 | 
| +        movq    mm7,mm1
 | 
| +        psrlq   mm7,(SIZEOF_MMWORD-1)*BYTE_BIT  ; mm7=( 7 - - - - - - -)
 | 
| +
 | 
| +        movq      mm4,mm1
 | 
| +        punpcklbw mm1,mm0               ; mm1=( 0 1 2 3)
 | 
| +        punpckhbw mm4,mm0               ; mm4=( 4 5 6 7)
 | 
| +        movq      mm5,mm2
 | 
| +        punpcklbw mm2,mm0               ; mm2=(-1 0 1 2)
 | 
| +        punpckhbw mm5,mm0               ; mm5=( 3 4 5 6)
 | 
| +        movq      mm6,mm3
 | 
| +        punpcklbw mm3,mm0               ; mm3=( 1 2 3 4)
 | 
| +        punpckhbw mm6,mm0               ; mm6=( 5 6 7 8)
 | 
| +
 | 
| +        pmullw  mm1,[GOTOFF(ebx,PW_THREE)]
 | 
| +        pmullw  mm4,[GOTOFF(ebx,PW_THREE)]
 | 
| +        paddw   mm2,[GOTOFF(ebx,PW_ONE)]
 | 
| +        paddw   mm5,[GOTOFF(ebx,PW_ONE)]
 | 
| +        paddw   mm3,[GOTOFF(ebx,PW_TWO)]
 | 
| +        paddw   mm6,[GOTOFF(ebx,PW_TWO)]
 | 
| +
 | 
| +        paddw   mm2,mm1
 | 
| +        paddw   mm5,mm4
 | 
| +        psrlw   mm2,2                   ; mm2=OutLE=( 0  2  4  6)
 | 
| +        psrlw   mm5,2                   ; mm5=OutHE=( 8 10 12 14)
 | 
| +        paddw   mm3,mm1
 | 
| +        paddw   mm6,mm4
 | 
| +        psrlw   mm3,2                   ; mm3=OutLO=( 1  3  5  7)
 | 
| +        psrlw   mm6,2                   ; mm6=OutHO=( 9 11 13 15)
 | 
| +
 | 
| +        psllw   mm3,BYTE_BIT
 | 
| +        psllw   mm6,BYTE_BIT
 | 
| +        por     mm2,mm3                 ; mm2=OutL=( 0  1  2  3  4  5  6  7)
 | 
| +        por     mm5,mm6                 ; mm5=OutH=( 8  9 10 11 12 13 14 15)
 | 
| +
 | 
| +        movq    MMWORD [edi+0*SIZEOF_MMWORD], mm2
 | 
| +        movq    MMWORD [edi+1*SIZEOF_MMWORD], mm5
 | 
| +
 | 
| +        sub     eax, byte SIZEOF_MMWORD
 | 
| +        add     esi, byte 1*SIZEOF_MMWORD       ; inptr
 | 
| +        add     edi, byte 2*SIZEOF_MMWORD       ; outptr
 | 
| +        cmp     eax, byte SIZEOF_MMWORD
 | 
| +        ja      near .columnloop
 | 
| +        test    eax,eax
 | 
| +        jnz     near .columnloop_last
 | 
| +
 | 
| +        pop     esi
 | 
| +        pop     edi
 | 
| +        pop     eax
 | 
| +
 | 
| +        add     esi, byte SIZEOF_JSAMPROW       ; input_data
 | 
| +        add     edi, byte SIZEOF_JSAMPROW       ; output_data
 | 
| +        dec     ecx                             ; rowctr
 | 
| +        jg      near .rowloop
 | 
| +
 | 
| +        emms            ; empty MMX state
 | 
| +
 | 
| +.return:
 | 
| +        pop     edi
 | 
| +        pop     esi
 | 
| +;       pop     edx             ; need not be preserved
 | 
| +;       pop     ecx             ; need not be preserved
 | 
| +        poppic  ebx
 | 
| +        pop     ebp
 | 
| +        ret
 | 
| +
 | 
| +; --------------------------------------------------------------------------
 | 
| +;
 | 
| +; Fancy processing for the common case of 2:1 horizontal and 2:1 vertical.
 | 
| +; Again a triangle filter; see comments for h2v1 case, above.
 | 
| +;
 | 
| +; GLOBAL(void)
 | 
| +; jsimd_h2v2_fancy_upsample_mmx (int max_v_samp_factor,
 | 
| +;                                JDIMENSION downsampled_width,
 | 
| +;                                JSAMPARRAY input_data,
 | 
| +;                                JSAMPARRAY *output_data_ptr);
 | 
| +;
 | 
| +
 | 
| +%define max_v_samp(b)           (b)+8           ; int max_v_samp_factor
 | 
| +%define downsamp_width(b)       (b)+12          ; JDIMENSION downsampled_width
 | 
| +%define input_data(b)           (b)+16          ; JSAMPARRAY input_data
 | 
| +%define output_data_ptr(b)      (b)+20          ; JSAMPARRAY *output_data_ptr
 | 
| +
 | 
| +%define original_ebp    ebp+0
 | 
| +%define wk(i)           ebp-(WK_NUM-(i))*SIZEOF_MMWORD  ; mmword wk[WK_NUM]
 | 
| +%define WK_NUM          4
 | 
| +%define gotptr          wk(0)-SIZEOF_POINTER    ; void *gotptr
 | 
| +
 | 
| +        align   16
 | 
| +        global  EXTN(jsimd_h2v2_fancy_upsample_mmx)
 | 
| +
 | 
| +EXTN(jsimd_h2v2_fancy_upsample_mmx):
 | 
| +        push    ebp
 | 
| +        mov     eax,esp                         ; eax = original ebp
 | 
| +        sub     esp, byte 4
 | 
| +        and     esp, byte (-SIZEOF_MMWORD)      ; align to 64 bits
 | 
| +        mov     [esp],eax
 | 
| +        mov     ebp,esp                         ; ebp = aligned ebp
 | 
| +        lea     esp, [wk(0)]
 | 
| +        pushpic eax             ; make a room for GOT address
 | 
| +        push    ebx
 | 
| +;       push    ecx             ; need not be preserved
 | 
| +;       push    edx             ; need not be preserved
 | 
| +        push    esi
 | 
| +        push    edi
 | 
| +
 | 
| +        get_GOT ebx                     ; get GOT address
 | 
| +        movpic  POINTER [gotptr], ebx   ; save GOT address
 | 
| +
 | 
| +        mov     edx,eax                         ; edx = original ebp
 | 
| +        mov     eax, JDIMENSION [downsamp_width(edx)]  ; colctr
 | 
| +        test    eax,eax
 | 
| +        jz      near .return
 | 
| +
 | 
| +        mov     ecx, INT [max_v_samp(edx)]      ; rowctr
 | 
| +        test    ecx,ecx
 | 
| +        jz      near .return
 | 
| +
 | 
| +        mov     esi, JSAMPARRAY [input_data(edx)]       ; input_data
 | 
| +        mov     edi, POINTER [output_data_ptr(edx)]
 | 
| +        mov     edi, JSAMPARRAY [edi]                   ; output_data
 | 
| +        alignx  16,7
 | 
| +.rowloop:
 | 
| +        push    eax                                     ; colctr
 | 
| +        push    ecx
 | 
| +        push    edi
 | 
| +        push    esi
 | 
| +
 | 
| +        mov     ecx, JSAMPROW [esi-1*SIZEOF_JSAMPROW]   ; inptr1(above)
 | 
| +        mov     ebx, JSAMPROW [esi+0*SIZEOF_JSAMPROW]   ; inptr0
 | 
| +        mov     esi, JSAMPROW [esi+1*SIZEOF_JSAMPROW]   ; inptr1(below)
 | 
| +        mov     edx, JSAMPROW [edi+0*SIZEOF_JSAMPROW]   ; outptr0
 | 
| +        mov     edi, JSAMPROW [edi+1*SIZEOF_JSAMPROW]   ; outptr1
 | 
| +
 | 
| +        test    eax, SIZEOF_MMWORD-1
 | 
| +        jz      short .skip
 | 
| +        push    edx
 | 
| +        mov     dl, JSAMPLE [ecx+(eax-1)*SIZEOF_JSAMPLE]
 | 
| +        mov     JSAMPLE [ecx+eax*SIZEOF_JSAMPLE], dl
 | 
| +        mov     dl, JSAMPLE [ebx+(eax-1)*SIZEOF_JSAMPLE]
 | 
| +        mov     JSAMPLE [ebx+eax*SIZEOF_JSAMPLE], dl
 | 
| +        mov     dl, JSAMPLE [esi+(eax-1)*SIZEOF_JSAMPLE]
 | 
| +        mov     JSAMPLE [esi+eax*SIZEOF_JSAMPLE], dl    ; insert a dummy sample
 | 
| +        pop     edx
 | 
| +.skip:
 | 
| +        ; -- process the first column block
 | 
| +
 | 
| +        movq    mm0, MMWORD [ebx+0*SIZEOF_MMWORD]       ; mm0=row[ 0][0]
 | 
| +        movq    mm1, MMWORD [ecx+0*SIZEOF_MMWORD]       ; mm1=row[-1][0]
 | 
| +        movq    mm2, MMWORD [esi+0*SIZEOF_MMWORD]       ; mm2=row[+1][0]
 | 
| +
 | 
| +        pushpic ebx
 | 
| +        movpic  ebx, POINTER [gotptr]   ; load GOT address
 | 
| +
 | 
| +        pxor      mm3,mm3               ; mm3=(all 0's)
 | 
| +        movq      mm4,mm0
 | 
| +        punpcklbw mm0,mm3               ; mm0=row[ 0][0]( 0 1 2 3)
 | 
| +        punpckhbw mm4,mm3               ; mm4=row[ 0][0]( 4 5 6 7)
 | 
| +        movq      mm5,mm1
 | 
| +        punpcklbw mm1,mm3               ; mm1=row[-1][0]( 0 1 2 3)
 | 
| +        punpckhbw mm5,mm3               ; mm5=row[-1][0]( 4 5 6 7)
 | 
| +        movq      mm6,mm2
 | 
| +        punpcklbw mm2,mm3               ; mm2=row[+1][0]( 0 1 2 3)
 | 
| +        punpckhbw mm6,mm3               ; mm6=row[+1][0]( 4 5 6 7)
 | 
| +
 | 
| +        pmullw  mm0,[GOTOFF(ebx,PW_THREE)]
 | 
| +        pmullw  mm4,[GOTOFF(ebx,PW_THREE)]
 | 
| +
 | 
| +        pcmpeqb mm7,mm7
 | 
| +        psrlq   mm7,(SIZEOF_MMWORD-2)*BYTE_BIT
 | 
| +
 | 
| +        paddw   mm1,mm0                 ; mm1=Int0L=( 0 1 2 3)
 | 
| +        paddw   mm5,mm4                 ; mm5=Int0H=( 4 5 6 7)
 | 
| +        paddw   mm2,mm0                 ; mm2=Int1L=( 0 1 2 3)
 | 
| +        paddw   mm6,mm4                 ; mm6=Int1H=( 4 5 6 7)
 | 
| +
 | 
| +        movq    MMWORD [edx+0*SIZEOF_MMWORD], mm1       ; temporarily save
 | 
| +        movq    MMWORD [edx+1*SIZEOF_MMWORD], mm5       ; the intermediate data
 | 
| +        movq    MMWORD [edi+0*SIZEOF_MMWORD], mm2
 | 
| +        movq    MMWORD [edi+1*SIZEOF_MMWORD], mm6
 | 
| +
 | 
| +        pand    mm1,mm7                 ; mm1=( 0 - - -)
 | 
| +        pand    mm2,mm7                 ; mm2=( 0 - - -)
 | 
| +
 | 
| +        movq    MMWORD [wk(0)], mm1
 | 
| +        movq    MMWORD [wk(1)], mm2
 | 
| +
 | 
| +        poppic  ebx
 | 
| +
 | 
| +        add     eax, byte SIZEOF_MMWORD-1
 | 
| +        and     eax, byte -SIZEOF_MMWORD
 | 
| +        cmp     eax, byte SIZEOF_MMWORD
 | 
| +        ja      short .columnloop
 | 
| +        alignx  16,7
 | 
| +
 | 
| +.columnloop_last:
 | 
| +        ; -- process the last column block
 | 
| +
 | 
| +        pushpic ebx
 | 
| +        movpic  ebx, POINTER [gotptr]   ; load GOT address
 | 
| +
 | 
| +        pcmpeqb mm1,mm1
 | 
| +        psllq   mm1,(SIZEOF_MMWORD-2)*BYTE_BIT
 | 
| +        movq    mm2,mm1
 | 
| +
 | 
| +        pand    mm1, MMWORD [edx+1*SIZEOF_MMWORD]       ; mm1=( - - - 7)
 | 
| +        pand    mm2, MMWORD [edi+1*SIZEOF_MMWORD]       ; mm2=( - - - 7)
 | 
| +
 | 
| +        movq    MMWORD [wk(2)], mm1
 | 
| +        movq    MMWORD [wk(3)], mm2
 | 
| +
 | 
| +        jmp     short .upsample
 | 
| +        alignx  16,7
 | 
| +
 | 
| +.columnloop:
 | 
| +        ; -- process the next column block
 | 
| +
 | 
| +        movq    mm0, MMWORD [ebx+1*SIZEOF_MMWORD]       ; mm0=row[ 0][1]
 | 
| +        movq    mm1, MMWORD [ecx+1*SIZEOF_MMWORD]       ; mm1=row[-1][1]
 | 
| +        movq    mm2, MMWORD [esi+1*SIZEOF_MMWORD]       ; mm2=row[+1][1]
 | 
| +
 | 
| +        pushpic ebx
 | 
| +        movpic  ebx, POINTER [gotptr]   ; load GOT address
 | 
| +
 | 
| +        pxor      mm3,mm3               ; mm3=(all 0's)
 | 
| +        movq      mm4,mm0
 | 
| +        punpcklbw mm0,mm3               ; mm0=row[ 0][1]( 0 1 2 3)
 | 
| +        punpckhbw mm4,mm3               ; mm4=row[ 0][1]( 4 5 6 7)
 | 
| +        movq      mm5,mm1
 | 
| +        punpcklbw mm1,mm3               ; mm1=row[-1][1]( 0 1 2 3)
 | 
| +        punpckhbw mm5,mm3               ; mm5=row[-1][1]( 4 5 6 7)
 | 
| +        movq      mm6,mm2
 | 
| +        punpcklbw mm2,mm3               ; mm2=row[+1][1]( 0 1 2 3)
 | 
| +        punpckhbw mm6,mm3               ; mm6=row[+1][1]( 4 5 6 7)
 | 
| +
 | 
| +        pmullw  mm0,[GOTOFF(ebx,PW_THREE)]
 | 
| +        pmullw  mm4,[GOTOFF(ebx,PW_THREE)]
 | 
| +
 | 
| +        paddw   mm1,mm0                 ; mm1=Int0L=( 0 1 2 3)
 | 
| +        paddw   mm5,mm4                 ; mm5=Int0H=( 4 5 6 7)
 | 
| +        paddw   mm2,mm0                 ; mm2=Int1L=( 0 1 2 3)
 | 
| +        paddw   mm6,mm4                 ; mm6=Int1H=( 4 5 6 7)
 | 
| +
 | 
| +        movq    MMWORD [edx+2*SIZEOF_MMWORD], mm1       ; temporarily save
 | 
| +        movq    MMWORD [edx+3*SIZEOF_MMWORD], mm5       ; the intermediate data
 | 
| +        movq    MMWORD [edi+2*SIZEOF_MMWORD], mm2
 | 
| +        movq    MMWORD [edi+3*SIZEOF_MMWORD], mm6
 | 
| +
 | 
| +        psllq   mm1,(SIZEOF_MMWORD-2)*BYTE_BIT  ; mm1=( - - - 0)
 | 
| +        psllq   mm2,(SIZEOF_MMWORD-2)*BYTE_BIT  ; mm2=( - - - 0)
 | 
| +
 | 
| +        movq    MMWORD [wk(2)], mm1
 | 
| +        movq    MMWORD [wk(3)], mm2
 | 
| +
 | 
| +.upsample:
 | 
| +        ; -- process the upper row
 | 
| +
 | 
| +        movq    mm7, MMWORD [edx+0*SIZEOF_MMWORD]       ; mm7=Int0L=( 0 1 2 3)
 | 
| +        movq    mm3, MMWORD [edx+1*SIZEOF_MMWORD]       ; mm3=Int0H=( 4 5 6 7)
 | 
| +
 | 
| +        movq    mm0,mm7
 | 
| +        movq    mm4,mm3
 | 
| +        psrlq   mm0,2*BYTE_BIT                  ; mm0=( 1 2 3 -)
 | 
| +        psllq   mm4,(SIZEOF_MMWORD-2)*BYTE_BIT  ; mm4=( - - - 4)
 | 
| +        movq    mm5,mm7
 | 
| +        movq    mm6,mm3
 | 
| +        psrlq   mm5,(SIZEOF_MMWORD-2)*BYTE_BIT  ; mm5=( 3 - - -)
 | 
| +        psllq   mm6,2*BYTE_BIT                  ; mm6=( - 4 5 6)
 | 
| +
 | 
| +        por     mm0,mm4                         ; mm0=( 1 2 3 4)
 | 
| +        por     mm5,mm6                         ; mm5=( 3 4 5 6)
 | 
| +
 | 
| +        movq    mm1,mm7
 | 
| +        movq    mm2,mm3
 | 
| +        psllq   mm1,2*BYTE_BIT                  ; mm1=( - 0 1 2)
 | 
| +        psrlq   mm2,2*BYTE_BIT                  ; mm2=( 5 6 7 -)
 | 
| +        movq    mm4,mm3
 | 
| +        psrlq   mm4,(SIZEOF_MMWORD-2)*BYTE_BIT  ; mm4=( 7 - - -)
 | 
| +
 | 
| +        por     mm1, MMWORD [wk(0)]             ; mm1=(-1 0 1 2)
 | 
| +        por     mm2, MMWORD [wk(2)]             ; mm2=( 5 6 7 8)
 | 
| +
 | 
| +        movq    MMWORD [wk(0)], mm4
 | 
| +
 | 
| +        pmullw  mm7,[GOTOFF(ebx,PW_THREE)]
 | 
| +        pmullw  mm3,[GOTOFF(ebx,PW_THREE)]
 | 
| +        paddw   mm1,[GOTOFF(ebx,PW_EIGHT)]
 | 
| +        paddw   mm5,[GOTOFF(ebx,PW_EIGHT)]
 | 
| +        paddw   mm0,[GOTOFF(ebx,PW_SEVEN)]
 | 
| +        paddw   mm2,[GOTOFF(ebx,PW_SEVEN)]
 | 
| +
 | 
| +        paddw   mm1,mm7
 | 
| +        paddw   mm5,mm3
 | 
| +        psrlw   mm1,4                   ; mm1=Out0LE=( 0  2  4  6)
 | 
| +        psrlw   mm5,4                   ; mm5=Out0HE=( 8 10 12 14)
 | 
| +        paddw   mm0,mm7
 | 
| +        paddw   mm2,mm3
 | 
| +        psrlw   mm0,4                   ; mm0=Out0LO=( 1  3  5  7)
 | 
| +        psrlw   mm2,4                   ; mm2=Out0HO=( 9 11 13 15)
 | 
| +
 | 
| +        psllw   mm0,BYTE_BIT
 | 
| +        psllw   mm2,BYTE_BIT
 | 
| +        por     mm1,mm0                 ; mm1=Out0L=( 0  1  2  3  4  5  6  7)
 | 
| +        por     mm5,mm2                 ; mm5=Out0H=( 8  9 10 11 12 13 14 15)
 | 
| +
 | 
| +        movq    MMWORD [edx+0*SIZEOF_MMWORD], mm1
 | 
| +        movq    MMWORD [edx+1*SIZEOF_MMWORD], mm5
 | 
| +
 | 
| +        ; -- process the lower row
 | 
| +
 | 
| +        movq    mm6, MMWORD [edi+0*SIZEOF_MMWORD]       ; mm6=Int1L=( 0 1 2 3)
 | 
| +        movq    mm4, MMWORD [edi+1*SIZEOF_MMWORD]       ; mm4=Int1H=( 4 5 6 7)
 | 
| +
 | 
| +        movq    mm7,mm6
 | 
| +        movq    mm3,mm4
 | 
| +        psrlq   mm7,2*BYTE_BIT                  ; mm7=( 1 2 3 -)
 | 
| +        psllq   mm3,(SIZEOF_MMWORD-2)*BYTE_BIT  ; mm3=( - - - 4)
 | 
| +        movq    mm0,mm6
 | 
| +        movq    mm2,mm4
 | 
| +        psrlq   mm0,(SIZEOF_MMWORD-2)*BYTE_BIT  ; mm0=( 3 - - -)
 | 
| +        psllq   mm2,2*BYTE_BIT                  ; mm2=( - 4 5 6)
 | 
| +
 | 
| +        por     mm7,mm3                         ; mm7=( 1 2 3 4)
 | 
| +        por     mm0,mm2                         ; mm0=( 3 4 5 6)
 | 
| +
 | 
| +        movq    mm1,mm6
 | 
| +        movq    mm5,mm4
 | 
| +        psllq   mm1,2*BYTE_BIT                  ; mm1=( - 0 1 2)
 | 
| +        psrlq   mm5,2*BYTE_BIT                  ; mm5=( 5 6 7 -)
 | 
| +        movq    mm3,mm4
 | 
| +        psrlq   mm3,(SIZEOF_MMWORD-2)*BYTE_BIT  ; mm3=( 7 - - -)
 | 
| +
 | 
| +        por     mm1, MMWORD [wk(1)]             ; mm1=(-1 0 1 2)
 | 
| +        por     mm5, MMWORD [wk(3)]             ; mm5=( 5 6 7 8)
 | 
| +
 | 
| +        movq    MMWORD [wk(1)], mm3
 | 
| +
 | 
| +        pmullw  mm6,[GOTOFF(ebx,PW_THREE)]
 | 
| +        pmullw  mm4,[GOTOFF(ebx,PW_THREE)]
 | 
| +        paddw   mm1,[GOTOFF(ebx,PW_EIGHT)]
 | 
| +        paddw   mm0,[GOTOFF(ebx,PW_EIGHT)]
 | 
| +        paddw   mm7,[GOTOFF(ebx,PW_SEVEN)]
 | 
| +        paddw   mm5,[GOTOFF(ebx,PW_SEVEN)]
 | 
| +
 | 
| +        paddw   mm1,mm6
 | 
| +        paddw   mm0,mm4
 | 
| +        psrlw   mm1,4                   ; mm1=Out1LE=( 0  2  4  6)
 | 
| +        psrlw   mm0,4                   ; mm0=Out1HE=( 8 10 12 14)
 | 
| +        paddw   mm7,mm6
 | 
| +        paddw   mm5,mm4
 | 
| +        psrlw   mm7,4                   ; mm7=Out1LO=( 1  3  5  7)
 | 
| +        psrlw   mm5,4                   ; mm5=Out1HO=( 9 11 13 15)
 | 
| +
 | 
| +        psllw   mm7,BYTE_BIT
 | 
| +        psllw   mm5,BYTE_BIT
 | 
| +        por     mm1,mm7                 ; mm1=Out1L=( 0  1  2  3  4  5  6  7)
 | 
| +        por     mm0,mm5                 ; mm0=Out1H=( 8  9 10 11 12 13 14 15)
 | 
| +
 | 
| +        movq    MMWORD [edi+0*SIZEOF_MMWORD], mm1
 | 
| +        movq    MMWORD [edi+1*SIZEOF_MMWORD], mm0
 | 
| +
 | 
| +        poppic  ebx
 | 
| +
 | 
| +        sub     eax, byte SIZEOF_MMWORD
 | 
| +        add     ecx, byte 1*SIZEOF_MMWORD       ; inptr1(above)
 | 
| +        add     ebx, byte 1*SIZEOF_MMWORD       ; inptr0
 | 
| +        add     esi, byte 1*SIZEOF_MMWORD       ; inptr1(below)
 | 
| +        add     edx, byte 2*SIZEOF_MMWORD       ; outptr0
 | 
| +        add     edi, byte 2*SIZEOF_MMWORD       ; outptr1
 | 
| +        cmp     eax, byte SIZEOF_MMWORD
 | 
| +        ja      near .columnloop
 | 
| +        test    eax,eax
 | 
| +        jnz     near .columnloop_last
 | 
| +
 | 
| +        pop     esi
 | 
| +        pop     edi
 | 
| +        pop     ecx
 | 
| +        pop     eax
 | 
| +
 | 
| +        add     esi, byte 1*SIZEOF_JSAMPROW     ; input_data
 | 
| +        add     edi, byte 2*SIZEOF_JSAMPROW     ; output_data
 | 
| +        sub     ecx, byte 2                     ; rowctr
 | 
| +        jg      near .rowloop
 | 
| +
 | 
| +        emms            ; empty MMX state
 | 
| +
 | 
| +.return:
 | 
| +        pop     edi
 | 
| +        pop     esi
 | 
| +;       pop     edx             ; need not be preserved
 | 
| +;       pop     ecx             ; need not be preserved
 | 
| +        pop     ebx
 | 
| +        mov     esp,ebp         ; esp <- aligned ebp
 | 
| +        pop     esp             ; esp <- original ebp
 | 
| +        pop     ebp
 | 
| +        ret
 | 
| +
 | 
| +; --------------------------------------------------------------------------
 | 
| +;
 | 
| +; Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
 | 
| +; It's still a box filter.
 | 
| +;
 | 
| +; GLOBAL(void)
 | 
| +; jsimd_h2v1_upsample_mmx (int max_v_samp_factor,
 | 
| +;                          JDIMENSION output_width,
 | 
| +;                          JSAMPARRAY input_data,
 | 
| +;                          JSAMPARRAY *output_data_ptr);
 | 
| +;
 | 
| +
 | 
| +%define max_v_samp(b)           (b)+8           ; int max_v_samp_factor
 | 
| +%define output_width(b)         (b)+12          ; JDIMENSION output_width
 | 
| +%define input_data(b)           (b)+16          ; JSAMPARRAY input_data
 | 
| +%define output_data_ptr(b)      (b)+20          ; JSAMPARRAY *output_data_ptr
 | 
| +
 | 
| +        align   16
 | 
| +        global  EXTN(jsimd_h2v1_upsample_mmx)
 | 
| +
 | 
| +EXTN(jsimd_h2v1_upsample_mmx):
 | 
| +        push    ebp
 | 
| +        mov     ebp,esp
 | 
| +;       push    ebx             ; unused
 | 
| +;       push    ecx             ; need not be preserved
 | 
| +;       push    edx             ; need not be preserved
 | 
| +        push    esi
 | 
| +        push    edi
 | 
| +
 | 
| +        mov     edx, JDIMENSION [output_width(ebp)]
 | 
| +        add     edx, byte (2*SIZEOF_MMWORD)-1
 | 
| +        and     edx, byte -(2*SIZEOF_MMWORD)
 | 
| +        jz      short .return
 | 
| +
 | 
| +        mov     ecx, INT [max_v_samp(ebp)]      ; rowctr
 | 
| +        test    ecx,ecx
 | 
| +        jz      short .return
 | 
| +
 | 
| +        mov     esi, JSAMPARRAY [input_data(ebp)]       ; input_data
 | 
| +        mov     edi, POINTER [output_data_ptr(ebp)]
 | 
| +        mov     edi, JSAMPARRAY [edi]                   ; output_data
 | 
| +        alignx  16,7
 | 
| +.rowloop:
 | 
| +        push    edi
 | 
| +        push    esi
 | 
| +
 | 
| +        mov     esi, JSAMPROW [esi]             ; inptr
 | 
| +        mov     edi, JSAMPROW [edi]             ; outptr
 | 
| +        mov     eax,edx                         ; colctr
 | 
| +        alignx  16,7
 | 
| +.columnloop:
 | 
| +
 | 
| +        movq    mm0, MMWORD [esi+0*SIZEOF_MMWORD]
 | 
| +
 | 
| +        movq      mm1,mm0
 | 
| +        punpcklbw mm0,mm0
 | 
| +        punpckhbw mm1,mm1
 | 
| +
 | 
| +        movq    MMWORD [edi+0*SIZEOF_MMWORD], mm0
 | 
| +        movq    MMWORD [edi+1*SIZEOF_MMWORD], mm1
 | 
| +
 | 
| +        sub     eax, byte 2*SIZEOF_MMWORD
 | 
| +        jz      short .nextrow
 | 
| +
 | 
| +        movq    mm2, MMWORD [esi+1*SIZEOF_MMWORD]
 | 
| +
 | 
| +        movq      mm3,mm2
 | 
| +        punpcklbw mm2,mm2
 | 
| +        punpckhbw mm3,mm3
 | 
| +
 | 
| +        movq    MMWORD [edi+2*SIZEOF_MMWORD], mm2
 | 
| +        movq    MMWORD [edi+3*SIZEOF_MMWORD], mm3
 | 
| +
 | 
| +        sub     eax, byte 2*SIZEOF_MMWORD
 | 
| +        jz      short .nextrow
 | 
| +
 | 
| +        add     esi, byte 2*SIZEOF_MMWORD       ; inptr
 | 
| +        add     edi, byte 4*SIZEOF_MMWORD       ; outptr
 | 
| +        jmp     short .columnloop
 | 
| +        alignx  16,7
 | 
| +
 | 
| +.nextrow:
 | 
| +        pop     esi
 | 
| +        pop     edi
 | 
| +
 | 
| +        add     esi, byte SIZEOF_JSAMPROW       ; input_data
 | 
| +        add     edi, byte SIZEOF_JSAMPROW       ; output_data
 | 
| +        dec     ecx                             ; rowctr
 | 
| +        jg      short .rowloop
 | 
| +
 | 
| +        emms            ; empty MMX state
 | 
| +
 | 
| +.return:
 | 
| +        pop     edi
 | 
| +        pop     esi
 | 
| +;       pop     edx             ; need not be preserved
 | 
| +;       pop     ecx             ; need not be preserved
 | 
| +;       pop     ebx             ; unused
 | 
| +        pop     ebp
 | 
| +        ret
 | 
| +
 | 
| +; --------------------------------------------------------------------------
 | 
| +;
 | 
| +; Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
 | 
| +; It's still a box filter.
 | 
| +;
 | 
| +; GLOBAL(void)
 | 
| +; jsimd_h2v2_upsample_mmx (int max_v_samp_factor,
 | 
| +;                          JDIMENSION output_width,
 | 
| +;                          JSAMPARRAY input_data,
 | 
| +;                          JSAMPARRAY *output_data_ptr);
 | 
| +;
 | 
| +
 | 
| +%define max_v_samp(b)           (b)+8           ; int max_v_samp_factor
 | 
| +%define output_width(b)         (b)+12          ; JDIMENSION output_width
 | 
| +%define input_data(b)           (b)+16          ; JSAMPARRAY input_data
 | 
| +%define output_data_ptr(b)      (b)+20          ; JSAMPARRAY *output_data_ptr
 | 
| +
 | 
| +        align   16
 | 
| +        global  EXTN(jsimd_h2v2_upsample_mmx)
 | 
| +
 | 
| +EXTN(jsimd_h2v2_upsample_mmx):
 | 
| +        push    ebp
 | 
| +        mov     ebp,esp
 | 
| +        push    ebx
 | 
| +;       push    ecx             ; need not be preserved
 | 
| +;       push    edx             ; need not be preserved
 | 
| +        push    esi
 | 
| +        push    edi
 | 
| +
 | 
| +        mov     edx, JDIMENSION [output_width(ebp)]
 | 
| +        add     edx, byte (2*SIZEOF_MMWORD)-1
 | 
| +        and     edx, byte -(2*SIZEOF_MMWORD)
 | 
| +        jz      near .return
 | 
| +
 | 
| +        mov     ecx, INT [max_v_samp(ebp)]      ; rowctr
 | 
| +        test    ecx,ecx
 | 
| +        jz      short .return
 | 
| +
 | 
| +        mov     esi, JSAMPARRAY [input_data(ebp)]       ; input_data
 | 
| +        mov     edi, POINTER [output_data_ptr(ebp)]
 | 
| +        mov     edi, JSAMPARRAY [edi]                   ; output_data
 | 
| +        alignx  16,7
 | 
| +.rowloop:
 | 
| +        push    edi
 | 
| +        push    esi
 | 
| +
 | 
| +        mov     esi, JSAMPROW [esi]                     ; inptr
 | 
| +        mov     ebx, JSAMPROW [edi+0*SIZEOF_JSAMPROW]   ; outptr0
 | 
| +        mov     edi, JSAMPROW [edi+1*SIZEOF_JSAMPROW]   ; outptr1
 | 
| +        mov     eax,edx                                 ; colctr
 | 
| +        alignx  16,7
 | 
| +.columnloop:
 | 
| +
 | 
| +        movq    mm0, MMWORD [esi+0*SIZEOF_MMWORD]
 | 
| +
 | 
| +        movq      mm1,mm0
 | 
| +        punpcklbw mm0,mm0
 | 
| +        punpckhbw mm1,mm1
 | 
| +
 | 
| +        movq    MMWORD [ebx+0*SIZEOF_MMWORD], mm0
 | 
| +        movq    MMWORD [ebx+1*SIZEOF_MMWORD], mm1
 | 
| +        movq    MMWORD [edi+0*SIZEOF_MMWORD], mm0
 | 
| +        movq    MMWORD [edi+1*SIZEOF_MMWORD], mm1
 | 
| +
 | 
| +        sub     eax, byte 2*SIZEOF_MMWORD
 | 
| +        jz      short .nextrow
 | 
| +
 | 
| +        movq    mm2, MMWORD [esi+1*SIZEOF_MMWORD]
 | 
| +
 | 
| +        movq      mm3,mm2
 | 
| +        punpcklbw mm2,mm2
 | 
| +        punpckhbw mm3,mm3
 | 
| +
 | 
| +        movq    MMWORD [ebx+2*SIZEOF_MMWORD], mm2
 | 
| +        movq    MMWORD [ebx+3*SIZEOF_MMWORD], mm3
 | 
| +        movq    MMWORD [edi+2*SIZEOF_MMWORD], mm2
 | 
| +        movq    MMWORD [edi+3*SIZEOF_MMWORD], mm3
 | 
| +
 | 
| +        sub     eax, byte 2*SIZEOF_MMWORD
 | 
| +        jz      short .nextrow
 | 
| +
 | 
| +        add     esi, byte 2*SIZEOF_MMWORD       ; inptr
 | 
| +        add     ebx, byte 4*SIZEOF_MMWORD       ; outptr0
 | 
| +        add     edi, byte 4*SIZEOF_MMWORD       ; outptr1
 | 
| +        jmp     short .columnloop
 | 
| +        alignx  16,7
 | 
| +
 | 
| +.nextrow:
 | 
| +        pop     esi
 | 
| +        pop     edi
 | 
| +
 | 
| +        add     esi, byte 1*SIZEOF_JSAMPROW     ; input_data
 | 
| +        add     edi, byte 2*SIZEOF_JSAMPROW     ; output_data
 | 
| +        sub     ecx, byte 2                     ; rowctr
 | 
| +        jg      short .rowloop
 | 
| +
 | 
| +        emms            ; empty MMX state
 | 
| +
 | 
| +.return:
 | 
| +        pop     edi
 | 
| +        pop     esi
 | 
| +;       pop     edx             ; need not be preserved
 | 
| +;       pop     ecx             ; need not be preserved
 | 
| +        pop     ebx
 | 
| +        pop     ebp
 | 
| +        ret
 | 
| +
 | 
| +; For some reason, the OS X linker does not honor the request to align the
 | 
| +; segment unless we do this.
 | 
| +        align   16
 | 
| 
 |