Home | History | Annotate | Download | only in simd
      1 ;
      2 ; jidctflt.asm - floating-point IDCT (3DNow! & MMX)
      3 ;
      4 ; Copyright 2009 Pierre Ossman <ossman (a] cendio.se> for Cendio AB
      5 ;
      6 ; Based on the x86 SIMD extension for IJG JPEG library
      7 ; Copyright (C) 1999-2006, MIYASAKA Masaru.
      8 ; For conditions of distribution and use, see copyright notice in jsimdext.inc
      9 ;
     10 ; This file should be assembled with NASM (Netwide Assembler),
     11 ; can *not* be assembled with Microsoft's MASM or any compatible
     12 ; assembler (including Borland's Turbo Assembler).
     13 ; NASM is available from http://nasm.sourceforge.net/ or
     14 ; http://sourceforge.net/project/showfiles.php?group_id=6208
     15 ;
     16 ; This file contains a floating-point implementation of the inverse DCT
     17 ; (Discrete Cosine Transform). The following code is based directly on
     18 ; the IJG's original jidctflt.c; see the jidctflt.c for more details.
     19 ;
     20 ; [TAB8]
     21 
     22 %include "jsimdext.inc"
     23 %include "jdct.inc"
     24 
     25 ; --------------------------------------------------------------------------
     26         SECTION SEG_CONST
     27 
     28         alignz  16
     29         global  EXTN(jconst_idct_float_3dnow)
     30 
     31 EXTN(jconst_idct_float_3dnow):
     32 
     33 PD_1_414        times 2 dd  1.414213562373095048801689
     34 PD_1_847        times 2 dd  1.847759065022573512256366
     35 PD_1_082        times 2 dd  1.082392200292393968799446
     36 PD_2_613        times 2 dd  2.613125929752753055713286
     37 PD_RNDINT_MAGIC times 2 dd  100663296.0 ; (float)(0x00C00000 << 3)
     38 PB_CENTERJSAMP  times 8 db  CENTERJSAMPLE
     39 
     40         alignz  16
     41 
     42 ; --------------------------------------------------------------------------
     43         SECTION SEG_TEXT
     44         BITS    32
     45 ;
     46 ; Perform dequantization and inverse DCT on one block of coefficients.
     47 ;
     48 ; GLOBAL(void)
     49 ; jsimd_idct_float_3dnow (void *dct_table, JCOEFPTR coef_block,
     50 ;                         JSAMPARRAY output_buf, JDIMENSION output_col)
     51 ;
     52 
     53 %define dct_table(b)    (b)+8           ; void *dct_table
     54 %define coef_block(b)   (b)+12          ; JCOEFPTR coef_block
     55 %define output_buf(b)   (b)+16          ; JSAMPARRAY output_buf
     56 %define output_col(b)   (b)+20          ; JDIMENSION output_col
     57 
     58 %define original_ebp    ebp+0
     59 %define wk(i)           ebp-(WK_NUM-(i))*SIZEOF_MMWORD  ; mmword wk[WK_NUM]
     60 %define WK_NUM          2
     61 %define workspace       wk(0)-DCTSIZE2*SIZEOF_FAST_FLOAT
     62                                         ; FAST_FLOAT workspace[DCTSIZE2]
     63 
     64         align   16
     65         global  EXTN(jsimd_idct_float_3dnow)
     66 
     67 EXTN(jsimd_idct_float_3dnow):
     68         push    ebp
     69         mov     eax,esp                         ; eax = original ebp
     70         sub     esp, byte 4
     71         and     esp, byte (-SIZEOF_MMWORD)      ; align to 64 bits
     72         mov     [esp],eax
     73         mov     ebp,esp                         ; ebp = aligned ebp
     74         lea     esp, [workspace]
     75         push    ebx
     76 ;       push    ecx             ; need not be preserved
     77 ;       push    edx             ; need not be preserved
     78         push    esi
     79         push    edi
     80 
     81         get_GOT ebx             ; get GOT address
     82 
     83         ; ---- Pass 1: process columns from input, store into work array.
     84 
     85 ;       mov     eax, [original_ebp]
     86         mov     edx, POINTER [dct_table(eax)]           ; quantptr
     87         mov     esi, JCOEFPTR [coef_block(eax)]         ; inptr
     88         lea     edi, [workspace]                        ; FAST_FLOAT *wsptr
     89         mov     ecx, DCTSIZE/2                          ; ctr
     90         alignx  16,7
     91 .columnloop:
     92 %ifndef NO_ZERO_COLUMN_TEST_FLOAT_3DNOW
     93         mov     eax, DWORD [DWBLOCK(1,0,esi,SIZEOF_JCOEF)]
     94         or      eax, DWORD [DWBLOCK(2,0,esi,SIZEOF_JCOEF)]
     95         jnz     short .columnDCT
     96 
     97         pushpic ebx             ; save GOT address
     98         mov     ebx, DWORD [DWBLOCK(3,0,esi,SIZEOF_JCOEF)]
     99         mov     eax, DWORD [DWBLOCK(4,0,esi,SIZEOF_JCOEF)]
    100         or      ebx, DWORD [DWBLOCK(5,0,esi,SIZEOF_JCOEF)]
    101         or      eax, DWORD [DWBLOCK(6,0,esi,SIZEOF_JCOEF)]
    102         or      ebx, DWORD [DWBLOCK(7,0,esi,SIZEOF_JCOEF)]
    103         or      eax,ebx
    104         poppic  ebx             ; restore GOT address
    105         jnz     short .columnDCT
    106 
    107         ; -- AC terms all zero
    108 
    109         movd      mm0, DWORD [DWBLOCK(0,0,esi,SIZEOF_JCOEF)]
    110 
    111         punpcklwd mm0,mm0
    112         psrad     mm0,(DWORD_BIT-WORD_BIT)
    113         pi2fd     mm0,mm0
    114 
    115         pfmul     mm0, MMWORD [MMBLOCK(0,0,edx,SIZEOF_FLOAT_MULT_TYPE)]
    116 
    117         movq      mm1,mm0
    118         punpckldq mm0,mm0
    119         punpckhdq mm1,mm1
    120 
    121         movq    MMWORD [MMBLOCK(0,0,edi,SIZEOF_FAST_FLOAT)], mm0
    122         movq    MMWORD [MMBLOCK(0,1,edi,SIZEOF_FAST_FLOAT)], mm0
    123         movq    MMWORD [MMBLOCK(0,2,edi,SIZEOF_FAST_FLOAT)], mm0
    124         movq    MMWORD [MMBLOCK(0,3,edi,SIZEOF_FAST_FLOAT)], mm0
    125         movq    MMWORD [MMBLOCK(1,0,edi,SIZEOF_FAST_FLOAT)], mm1
    126         movq    MMWORD [MMBLOCK(1,1,edi,SIZEOF_FAST_FLOAT)], mm1
    127         movq    MMWORD [MMBLOCK(1,2,edi,SIZEOF_FAST_FLOAT)], mm1
    128         movq    MMWORD [MMBLOCK(1,3,edi,SIZEOF_FAST_FLOAT)], mm1
    129         jmp     near .nextcolumn
    130         alignx  16,7
    131 %endif
    132 .columnDCT:
    133 
    134         ; -- Even part
    135 
    136         movd      mm0, DWORD [DWBLOCK(0,0,esi,SIZEOF_JCOEF)]
    137         movd      mm1, DWORD [DWBLOCK(2,0,esi,SIZEOF_JCOEF)]
    138         movd      mm2, DWORD [DWBLOCK(4,0,esi,SIZEOF_JCOEF)]
    139         movd      mm3, DWORD [DWBLOCK(6,0,esi,SIZEOF_JCOEF)]
    140 
    141         punpcklwd mm0,mm0
    142         punpcklwd mm1,mm1
    143         psrad     mm0,(DWORD_BIT-WORD_BIT)
    144         psrad     mm1,(DWORD_BIT-WORD_BIT)
    145         pi2fd     mm0,mm0
    146         pi2fd     mm1,mm1
    147 
    148         pfmul     mm0, MMWORD [MMBLOCK(0,0,edx,SIZEOF_FLOAT_MULT_TYPE)]
    149         pfmul     mm1, MMWORD [MMBLOCK(2,0,edx,SIZEOF_FLOAT_MULT_TYPE)]
    150 
    151         punpcklwd mm2,mm2
    152         punpcklwd mm3,mm3
    153         psrad     mm2,(DWORD_BIT-WORD_BIT)
    154         psrad     mm3,(DWORD_BIT-WORD_BIT)
    155         pi2fd     mm2,mm2
    156         pi2fd     mm3,mm3
    157 
    158         pfmul     mm2, MMWORD [MMBLOCK(4,0,edx,SIZEOF_FLOAT_MULT_TYPE)]
    159         pfmul     mm3, MMWORD [MMBLOCK(6,0,edx,SIZEOF_FLOAT_MULT_TYPE)]
    160 
    161         movq    mm4,mm0
    162         movq    mm5,mm1
    163         pfsub   mm0,mm2                 ; mm0=tmp11
    164         pfsub   mm1,mm3
    165         pfadd   mm4,mm2                 ; mm4=tmp10
    166         pfadd   mm5,mm3                 ; mm5=tmp13
    167 
    168         pfmul   mm1,[GOTOFF(ebx,PD_1_414)]
    169         pfsub   mm1,mm5                 ; mm1=tmp12
    170 
    171         movq    mm6,mm4
    172         movq    mm7,mm0
    173         pfsub   mm4,mm5                 ; mm4=tmp3
    174         pfsub   mm0,mm1                 ; mm0=tmp2
    175         pfadd   mm6,mm5                 ; mm6=tmp0
    176         pfadd   mm7,mm1                 ; mm7=tmp1
    177 
    178         movq    MMWORD [wk(1)], mm4     ; tmp3
    179         movq    MMWORD [wk(0)], mm0     ; tmp2
    180 
    181         ; -- Odd part
    182 
    183         movd      mm2, DWORD [DWBLOCK(1,0,esi,SIZEOF_JCOEF)]
    184         movd      mm3, DWORD [DWBLOCK(3,0,esi,SIZEOF_JCOEF)]
    185         movd      mm5, DWORD [DWBLOCK(5,0,esi,SIZEOF_JCOEF)]
    186         movd      mm1, DWORD [DWBLOCK(7,0,esi,SIZEOF_JCOEF)]
    187 
    188         punpcklwd mm2,mm2
    189         punpcklwd mm3,mm3
    190         psrad     mm2,(DWORD_BIT-WORD_BIT)
    191         psrad     mm3,(DWORD_BIT-WORD_BIT)
    192         pi2fd     mm2,mm2
    193         pi2fd     mm3,mm3
    194 
    195         pfmul     mm2, MMWORD [MMBLOCK(1,0,edx,SIZEOF_FLOAT_MULT_TYPE)]
    196         pfmul     mm3, MMWORD [MMBLOCK(3,0,edx,SIZEOF_FLOAT_MULT_TYPE)]
    197 
    198         punpcklwd mm5,mm5
    199         punpcklwd mm1,mm1
    200         psrad     mm5,(DWORD_BIT-WORD_BIT)
    201         psrad     mm1,(DWORD_BIT-WORD_BIT)
    202         pi2fd     mm5,mm5
    203         pi2fd     mm1,mm1
    204 
    205         pfmul     mm5, MMWORD [MMBLOCK(5,0,edx,SIZEOF_FLOAT_MULT_TYPE)]
    206         pfmul     mm1, MMWORD [MMBLOCK(7,0,edx,SIZEOF_FLOAT_MULT_TYPE)]
    207 
    208         movq    mm4,mm2
    209         movq    mm0,mm5
    210         pfadd   mm2,mm1                 ; mm2=z11
    211         pfadd   mm5,mm3                 ; mm5=z13
    212         pfsub   mm4,mm1                 ; mm4=z12
    213         pfsub   mm0,mm3                 ; mm0=z10
    214 
    215         movq    mm1,mm2
    216         pfsub   mm2,mm5
    217         pfadd   mm1,mm5                 ; mm1=tmp7
    218 
    219         pfmul   mm2,[GOTOFF(ebx,PD_1_414)]      ; mm2=tmp11
    220 
    221         movq    mm3,mm0
    222         pfadd   mm0,mm4
    223         pfmul   mm0,[GOTOFF(ebx,PD_1_847)]      ; mm0=z5
    224         pfmul   mm3,[GOTOFF(ebx,PD_2_613)]      ; mm3=(z10 * 2.613125930)
    225         pfmul   mm4,[GOTOFF(ebx,PD_1_082)]      ; mm4=(z12 * 1.082392200)
    226         pfsubr  mm3,mm0                 ; mm3=tmp12
    227         pfsub   mm4,mm0                 ; mm4=tmp10
    228 
    229         ; -- Final output stage
    230 
    231         pfsub   mm3,mm1                 ; mm3=tmp6
    232         movq    mm5,mm6
    233         movq    mm0,mm7
    234         pfadd   mm6,mm1                 ; mm6=data0=(00 01)
    235         pfadd   mm7,mm3                 ; mm7=data1=(10 11)
    236         pfsub   mm5,mm1                 ; mm5=data7=(70 71)
    237         pfsub   mm0,mm3                 ; mm0=data6=(60 61)
    238         pfsub   mm2,mm3                 ; mm2=tmp5
    239 
    240         movq      mm1,mm6               ; transpose coefficients
    241         punpckldq mm6,mm7               ; mm6=(00 10)
    242         punpckhdq mm1,mm7               ; mm1=(01 11)
    243         movq      mm3,mm0               ; transpose coefficients
    244         punpckldq mm0,mm5               ; mm0=(60 70)
    245         punpckhdq mm3,mm5               ; mm3=(61 71)
    246 
    247         movq    MMWORD [MMBLOCK(0,0,edi,SIZEOF_FAST_FLOAT)], mm6
    248         movq    MMWORD [MMBLOCK(1,0,edi,SIZEOF_FAST_FLOAT)], mm1
    249         movq    MMWORD [MMBLOCK(0,3,edi,SIZEOF_FAST_FLOAT)], mm0
    250         movq    MMWORD [MMBLOCK(1,3,edi,SIZEOF_FAST_FLOAT)], mm3
    251 
    252         movq    mm7, MMWORD [wk(0)]     ; mm7=tmp2
    253         movq    mm5, MMWORD [wk(1)]     ; mm5=tmp3
    254 
    255         pfadd   mm4,mm2                 ; mm4=tmp4
    256         movq    mm6,mm7
    257         movq    mm1,mm5
    258         pfadd   mm7,mm2                 ; mm7=data2=(20 21)
    259         pfadd   mm5,mm4                 ; mm5=data4=(40 41)
    260         pfsub   mm6,mm2                 ; mm6=data5=(50 51)
    261         pfsub   mm1,mm4                 ; mm1=data3=(30 31)
    262 
    263         movq      mm0,mm7               ; transpose coefficients
    264         punpckldq mm7,mm1               ; mm7=(20 30)
    265         punpckhdq mm0,mm1               ; mm0=(21 31)
    266         movq      mm3,mm5               ; transpose coefficients
    267         punpckldq mm5,mm6               ; mm5=(40 50)
    268         punpckhdq mm3,mm6               ; mm3=(41 51)
    269 
    270         movq    MMWORD [MMBLOCK(0,1,edi,SIZEOF_FAST_FLOAT)], mm7
    271         movq    MMWORD [MMBLOCK(1,1,edi,SIZEOF_FAST_FLOAT)], mm0
    272         movq    MMWORD [MMBLOCK(0,2,edi,SIZEOF_FAST_FLOAT)], mm5
    273         movq    MMWORD [MMBLOCK(1,2,edi,SIZEOF_FAST_FLOAT)], mm3
    274 
    275 .nextcolumn:
    276         add     esi, byte 2*SIZEOF_JCOEF                ; coef_block
    277         add     edx, byte 2*SIZEOF_FLOAT_MULT_TYPE      ; quantptr
    278         add     edi, byte 2*DCTSIZE*SIZEOF_FAST_FLOAT   ; wsptr
    279         dec     ecx                                     ; ctr
    280         jnz     near .columnloop
    281 
    282         ; -- Prefetch the next coefficient block
    283 
    284         prefetch [esi + (DCTSIZE2-8)*SIZEOF_JCOEF + 0*32]
    285         prefetch [esi + (DCTSIZE2-8)*SIZEOF_JCOEF + 1*32]
    286         prefetch [esi + (DCTSIZE2-8)*SIZEOF_JCOEF + 2*32]
    287         prefetch [esi + (DCTSIZE2-8)*SIZEOF_JCOEF + 3*32]
    288 
    289         ; ---- Pass 2: process rows from work array, store into output array.
    290 
    291         mov     eax, [original_ebp]
    292         lea     esi, [workspace]                        ; FAST_FLOAT *wsptr
    293         mov     edi, JSAMPARRAY [output_buf(eax)]       ; (JSAMPROW *)
    294         mov     eax, JDIMENSION [output_col(eax)]
    295         mov     ecx, DCTSIZE/2                          ; ctr
    296         alignx  16,7
    297 .rowloop:
    298 
    299         ; -- Even part
    300 
    301         movq    mm0, MMWORD [MMBLOCK(0,0,esi,SIZEOF_FAST_FLOAT)]
    302         movq    mm1, MMWORD [MMBLOCK(2,0,esi,SIZEOF_FAST_FLOAT)]
    303         movq    mm2, MMWORD [MMBLOCK(4,0,esi,SIZEOF_FAST_FLOAT)]
    304         movq    mm3, MMWORD [MMBLOCK(6,0,esi,SIZEOF_FAST_FLOAT)]
    305 
    306         movq    mm4,mm0
    307         movq    mm5,mm1
    308         pfsub   mm0,mm2                 ; mm0=tmp11
    309         pfsub   mm1,mm3
    310         pfadd   mm4,mm2                 ; mm4=tmp10
    311         pfadd   mm5,mm3                 ; mm5=tmp13
    312 
    313         pfmul   mm1,[GOTOFF(ebx,PD_1_414)]
    314         pfsub   mm1,mm5                 ; mm1=tmp12
    315 
    316         movq    mm6,mm4
    317         movq    mm7,mm0
    318         pfsub   mm4,mm5                 ; mm4=tmp3
    319         pfsub   mm0,mm1                 ; mm0=tmp2
    320         pfadd   mm6,mm5                 ; mm6=tmp0
    321         pfadd   mm7,mm1                 ; mm7=tmp1
    322 
    323         movq    MMWORD [wk(1)], mm4     ; tmp3
    324         movq    MMWORD [wk(0)], mm0     ; tmp2
    325 
    326         ; -- Odd part
    327 
    328         movq    mm2, MMWORD [MMBLOCK(1,0,esi,SIZEOF_FAST_FLOAT)]
    329         movq    mm3, MMWORD [MMBLOCK(3,0,esi,SIZEOF_FAST_FLOAT)]
    330         movq    mm5, MMWORD [MMBLOCK(5,0,esi,SIZEOF_FAST_FLOAT)]
    331         movq    mm1, MMWORD [MMBLOCK(7,0,esi,SIZEOF_FAST_FLOAT)]
    332 
    333         movq    mm4,mm2
    334         movq    mm0,mm5
    335         pfadd   mm2,mm1                 ; mm2=z11
    336         pfadd   mm5,mm3                 ; mm5=z13
    337         pfsub   mm4,mm1                 ; mm4=z12
    338         pfsub   mm0,mm3                 ; mm0=z10
    339 
    340         movq    mm1,mm2
    341         pfsub   mm2,mm5
    342         pfadd   mm1,mm5                 ; mm1=tmp7
    343 
    344         pfmul   mm2,[GOTOFF(ebx,PD_1_414)]      ; mm2=tmp11
    345 
    346         movq    mm3,mm0
    347         pfadd   mm0,mm4
    348         pfmul   mm0,[GOTOFF(ebx,PD_1_847)]      ; mm0=z5
    349         pfmul   mm3,[GOTOFF(ebx,PD_2_613)]      ; mm3=(z10 * 2.613125930)
    350         pfmul   mm4,[GOTOFF(ebx,PD_1_082)]      ; mm4=(z12 * 1.082392200)
    351         pfsubr  mm3,mm0                 ; mm3=tmp12
    352         pfsub   mm4,mm0                 ; mm4=tmp10
    353 
    354         ; -- Final output stage
    355 
    356         pfsub   mm3,mm1                 ; mm3=tmp6
    357         movq    mm5,mm6
    358         movq    mm0,mm7
    359         pfadd   mm6,mm1                 ; mm6=data0=(00 10)
    360         pfadd   mm7,mm3                 ; mm7=data1=(01 11)
    361         pfsub   mm5,mm1                 ; mm5=data7=(07 17)
    362         pfsub   mm0,mm3                 ; mm0=data6=(06 16)
    363         pfsub   mm2,mm3                 ; mm2=tmp5
    364 
    365         movq    mm1,[GOTOFF(ebx,PD_RNDINT_MAGIC)]       ; mm1=[PD_RNDINT_MAGIC]
    366         pcmpeqd mm3,mm3
    367         psrld   mm3,WORD_BIT            ; mm3={0xFFFF 0x0000 0xFFFF 0x0000}
    368 
    369         pfadd   mm6,mm1                 ; mm6=roundint(data0/8)=(00 ** 10 **)
    370         pfadd   mm7,mm1                 ; mm7=roundint(data1/8)=(01 ** 11 **)
    371         pfadd   mm0,mm1                 ; mm0=roundint(data6/8)=(06 ** 16 **)
    372         pfadd   mm5,mm1                 ; mm5=roundint(data7/8)=(07 ** 17 **)
    373 
    374         pand    mm6,mm3                 ; mm6=(00 -- 10 --)
    375         pslld   mm7,WORD_BIT            ; mm7=(-- 01 -- 11)
    376         pand    mm0,mm3                 ; mm0=(06 -- 16 --)
    377         pslld   mm5,WORD_BIT            ; mm5=(-- 07 -- 17)
    378         por     mm6,mm7                 ; mm6=(00 01 10 11)
    379         por     mm0,mm5                 ; mm0=(06 07 16 17)
    380 
    381         movq    mm1, MMWORD [wk(0)]     ; mm1=tmp2
    382         movq    mm3, MMWORD [wk(1)]     ; mm3=tmp3
    383 
    384         pfadd   mm4,mm2                 ; mm4=tmp4
    385         movq    mm7,mm1
    386         movq    mm5,mm3
    387         pfadd   mm1,mm2                 ; mm1=data2=(02 12)
    388         pfadd   mm3,mm4                 ; mm3=data4=(04 14)
    389         pfsub   mm7,mm2                 ; mm7=data5=(05 15)
    390         pfsub   mm5,mm4                 ; mm5=data3=(03 13)
    391 
    392         movq    mm2,[GOTOFF(ebx,PD_RNDINT_MAGIC)]       ; mm2=[PD_RNDINT_MAGIC]
    393         pcmpeqd mm4,mm4
    394         psrld   mm4,WORD_BIT            ; mm4={0xFFFF 0x0000 0xFFFF 0x0000}
    395 
    396         pfadd   mm3,mm2                 ; mm3=roundint(data4/8)=(04 ** 14 **)
    397         pfadd   mm7,mm2                 ; mm7=roundint(data5/8)=(05 ** 15 **)
    398         pfadd   mm1,mm2                 ; mm1=roundint(data2/8)=(02 ** 12 **)
    399         pfadd   mm5,mm2                 ; mm5=roundint(data3/8)=(03 ** 13 **)
    400 
    401         pand    mm3,mm4                 ; mm3=(04 -- 14 --)
    402         pslld   mm7,WORD_BIT            ; mm7=(-- 05 -- 15)
    403         pand    mm1,mm4                 ; mm1=(02 -- 12 --)
    404         pslld   mm5,WORD_BIT            ; mm5=(-- 03 -- 13)
    405         por     mm3,mm7                 ; mm3=(04 05 14 15)
    406         por     mm1,mm5                 ; mm1=(02 03 12 13)
    407 
    408         movq      mm2,[GOTOFF(ebx,PB_CENTERJSAMP)]      ; mm2=[PB_CENTERJSAMP]
    409 
    410         packsswb  mm6,mm3               ; mm6=(00 01 10 11 04 05 14 15)
    411         packsswb  mm1,mm0               ; mm1=(02 03 12 13 06 07 16 17)
    412         paddb     mm6,mm2
    413         paddb     mm1,mm2
    414 
    415         movq      mm4,mm6               ; transpose coefficients(phase 2)
    416         punpcklwd mm6,mm1               ; mm6=(00 01 02 03 10 11 12 13)
    417         punpckhwd mm4,mm1               ; mm4=(04 05 06 07 14 15 16 17)
    418 
    419         movq      mm7,mm6               ; transpose coefficients(phase 3)
    420         punpckldq mm6,mm4               ; mm6=(00 01 02 03 04 05 06 07)
    421         punpckhdq mm7,mm4               ; mm7=(10 11 12 13 14 15 16 17)
    422 
    423         pushpic ebx                     ; save GOT address
    424 
    425         mov     edx, JSAMPROW [edi+0*SIZEOF_JSAMPROW]
    426         mov     ebx, JSAMPROW [edi+1*SIZEOF_JSAMPROW]
    427         movq    MMWORD [edx+eax*SIZEOF_JSAMPLE], mm6
    428         movq    MMWORD [ebx+eax*SIZEOF_JSAMPLE], mm7
    429 
    430         poppic  ebx                     ; restore GOT address
    431 
    432         add     esi, byte 2*SIZEOF_FAST_FLOAT   ; wsptr
    433         add     edi, byte 2*SIZEOF_JSAMPROW
    434         dec     ecx                             ; ctr
    435         jnz     near .rowloop
    436 
    437         femms           ; empty MMX/3DNow! state
    438 
    439         pop     edi
    440         pop     esi
    441 ;       pop     edx             ; need not be preserved
    442 ;       pop     ecx             ; need not be preserved
    443         pop     ebx
    444         mov     esp,ebp         ; esp <- aligned ebp
    445         pop     esp             ; esp <- original ebp
    446         pop     ebp
    447         ret
    448 
    449 ; For some reason, the OS X linker does not honor the request to align the
    450 ; segment unless we do this.
    451         align   16
    452