1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * This file is part of FFmpeg.
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
10cabdff1aSopenharmony_ci *
11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14cabdff1aSopenharmony_ci * Lesser General Public License for more details.
15cabdff1aSopenharmony_ci *
16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19cabdff1aSopenharmony_ci */
20cabdff1aSopenharmony_ci
21cabdff1aSopenharmony_ci#include "../swscale_internal.h"
22cabdff1aSopenharmony_ci#include "libavutil/attributes.h"
23cabdff1aSopenharmony_ci#include "libavutil/x86/asm.h"
24cabdff1aSopenharmony_ci#include "libavutil/x86/cpu.h"
25cabdff1aSopenharmony_ci#include "libavutil/mem_internal.h"
26cabdff1aSopenharmony_ci
27cabdff1aSopenharmony_ci#define RET 0xC3 // near return opcode for x86
28cabdff1aSopenharmony_ci#define PREFETCH "prefetchnta"
29cabdff1aSopenharmony_ci
30cabdff1aSopenharmony_ci#if HAVE_INLINE_ASM
31cabdff1aSopenharmony_ciav_cold int ff_init_hscaler_mmxext(int dstW, int xInc, uint8_t *filterCode,
32cabdff1aSopenharmony_ci                                       int16_t *filter, int32_t *filterPos,
33cabdff1aSopenharmony_ci                                       int numSplits)
34cabdff1aSopenharmony_ci{
35cabdff1aSopenharmony_ci    uint8_t *fragmentA;
36cabdff1aSopenharmony_ci    x86_reg imm8OfPShufW1A;
37cabdff1aSopenharmony_ci    x86_reg imm8OfPShufW2A;
38cabdff1aSopenharmony_ci    x86_reg fragmentLengthA;
39cabdff1aSopenharmony_ci    uint8_t *fragmentB;
40cabdff1aSopenharmony_ci    x86_reg imm8OfPShufW1B;
41cabdff1aSopenharmony_ci    x86_reg imm8OfPShufW2B;
42cabdff1aSopenharmony_ci    x86_reg fragmentLengthB;
43cabdff1aSopenharmony_ci    int fragmentPos;
44cabdff1aSopenharmony_ci
45cabdff1aSopenharmony_ci    int xpos, i;
46cabdff1aSopenharmony_ci
47cabdff1aSopenharmony_ci    // create an optimized horizontal scaling routine
48cabdff1aSopenharmony_ci    /* This scaler is made of runtime-generated MMXEXT code using specially tuned
49cabdff1aSopenharmony_ci     * pshufw instructions. For every four output pixels, if four input pixels
50cabdff1aSopenharmony_ci     * are enough for the fast bilinear scaling, then a chunk of fragmentB is
51cabdff1aSopenharmony_ci     * used. If five input pixels are needed, then a chunk of fragmentA is used.
52cabdff1aSopenharmony_ci     */
53cabdff1aSopenharmony_ci
54cabdff1aSopenharmony_ci    // code fragment
55cabdff1aSopenharmony_ci
56cabdff1aSopenharmony_ci    __asm__ volatile (
57cabdff1aSopenharmony_ci        "jmp                         9f                 \n\t"
58cabdff1aSopenharmony_ci        // Begin
59cabdff1aSopenharmony_ci        "0:                                             \n\t"
60cabdff1aSopenharmony_ci        "movq    (%%"FF_REG_d", %%"FF_REG_a"), %%mm3    \n\t"
61cabdff1aSopenharmony_ci        "movd    (%%"FF_REG_c", %%"FF_REG_S"), %%mm0    \n\t"
62cabdff1aSopenharmony_ci        "movd   1(%%"FF_REG_c", %%"FF_REG_S"), %%mm1    \n\t"
63cabdff1aSopenharmony_ci        "punpcklbw                %%mm7, %%mm1          \n\t"
64cabdff1aSopenharmony_ci        "punpcklbw                %%mm7, %%mm0          \n\t"
65cabdff1aSopenharmony_ci        "pshufw                   $0xFF, %%mm1, %%mm1   \n\t"
66cabdff1aSopenharmony_ci        "1:                                             \n\t"
67cabdff1aSopenharmony_ci        "pshufw                   $0xFF, %%mm0, %%mm0   \n\t"
68cabdff1aSopenharmony_ci        "2:                                             \n\t"
69cabdff1aSopenharmony_ci        "psubw                    %%mm1, %%mm0          \n\t"
70cabdff1aSopenharmony_ci        "movl   8(%%"FF_REG_b", %%"FF_REG_a"), %%esi    \n\t"
71cabdff1aSopenharmony_ci        "pmullw                   %%mm3, %%mm0          \n\t"
72cabdff1aSopenharmony_ci        "psllw                       $7, %%mm1          \n\t"
73cabdff1aSopenharmony_ci        "paddw                    %%mm1, %%mm0          \n\t"
74cabdff1aSopenharmony_ci
75cabdff1aSopenharmony_ci        "movq                     %%mm0, (%%"FF_REG_D", %%"FF_REG_a") \n\t"
76cabdff1aSopenharmony_ci
77cabdff1aSopenharmony_ci        "add                         $8, %%"FF_REG_a"   \n\t"
78cabdff1aSopenharmony_ci        // End
79cabdff1aSopenharmony_ci        "9:                                             \n\t"
80cabdff1aSopenharmony_ci        "lea       " LOCAL_MANGLE(0b) ", %0             \n\t"
81cabdff1aSopenharmony_ci        "lea       " LOCAL_MANGLE(1b) ", %1             \n\t"
82cabdff1aSopenharmony_ci        "lea       " LOCAL_MANGLE(2b) ", %2             \n\t"
83cabdff1aSopenharmony_ci        "dec                         %1                 \n\t"
84cabdff1aSopenharmony_ci        "dec                         %2                 \n\t"
85cabdff1aSopenharmony_ci        "sub                         %0, %1             \n\t"
86cabdff1aSopenharmony_ci        "sub                         %0, %2             \n\t"
87cabdff1aSopenharmony_ci        "lea       " LOCAL_MANGLE(9b) ", %3             \n\t"
88cabdff1aSopenharmony_ci        "sub                         %0, %3             \n\t"
89cabdff1aSopenharmony_ci
90cabdff1aSopenharmony_ci
91cabdff1aSopenharmony_ci        : "=r" (fragmentA), "=r" (imm8OfPShufW1A), "=r" (imm8OfPShufW2A),
92cabdff1aSopenharmony_ci          "=r" (fragmentLengthA)
93cabdff1aSopenharmony_ci        );
94cabdff1aSopenharmony_ci
95cabdff1aSopenharmony_ci    __asm__ volatile (
96cabdff1aSopenharmony_ci        "jmp                         9f                 \n\t"
97cabdff1aSopenharmony_ci        // Begin
98cabdff1aSopenharmony_ci        "0:                                             \n\t"
99cabdff1aSopenharmony_ci        "movq    (%%"FF_REG_d", %%"FF_REG_a"), %%mm3    \n\t"
100cabdff1aSopenharmony_ci        "movd    (%%"FF_REG_c", %%"FF_REG_S"), %%mm0    \n\t"
101cabdff1aSopenharmony_ci        "punpcklbw                %%mm7, %%mm0          \n\t"
102cabdff1aSopenharmony_ci        "pshufw                   $0xFF, %%mm0, %%mm1   \n\t"
103cabdff1aSopenharmony_ci        "1:                                             \n\t"
104cabdff1aSopenharmony_ci        "pshufw                   $0xFF, %%mm0, %%mm0   \n\t"
105cabdff1aSopenharmony_ci        "2:                                             \n\t"
106cabdff1aSopenharmony_ci        "psubw                    %%mm1, %%mm0          \n\t"
107cabdff1aSopenharmony_ci        "movl   8(%%"FF_REG_b", %%"FF_REG_a"), %%esi    \n\t"
108cabdff1aSopenharmony_ci        "pmullw                   %%mm3, %%mm0          \n\t"
109cabdff1aSopenharmony_ci        "psllw                       $7, %%mm1          \n\t"
110cabdff1aSopenharmony_ci        "paddw                    %%mm1, %%mm0          \n\t"
111cabdff1aSopenharmony_ci
112cabdff1aSopenharmony_ci        "movq                     %%mm0, (%%"FF_REG_D", %%"FF_REG_a") \n\t"
113cabdff1aSopenharmony_ci
114cabdff1aSopenharmony_ci        "add                         $8, %%"FF_REG_a"   \n\t"
115cabdff1aSopenharmony_ci        // End
116cabdff1aSopenharmony_ci        "9:                                             \n\t"
117cabdff1aSopenharmony_ci        "lea       " LOCAL_MANGLE(0b) ", %0             \n\t"
118cabdff1aSopenharmony_ci        "lea       " LOCAL_MANGLE(1b) ", %1             \n\t"
119cabdff1aSopenharmony_ci        "lea       " LOCAL_MANGLE(2b) ", %2             \n\t"
120cabdff1aSopenharmony_ci        "dec                         %1                 \n\t"
121cabdff1aSopenharmony_ci        "dec                         %2                 \n\t"
122cabdff1aSopenharmony_ci        "sub                         %0, %1             \n\t"
123cabdff1aSopenharmony_ci        "sub                         %0, %2             \n\t"
124cabdff1aSopenharmony_ci        "lea       " LOCAL_MANGLE(9b) ", %3             \n\t"
125cabdff1aSopenharmony_ci        "sub                         %0, %3             \n\t"
126cabdff1aSopenharmony_ci
127cabdff1aSopenharmony_ci
128cabdff1aSopenharmony_ci        : "=r" (fragmentB), "=r" (imm8OfPShufW1B), "=r" (imm8OfPShufW2B),
129cabdff1aSopenharmony_ci          "=r" (fragmentLengthB)
130cabdff1aSopenharmony_ci        );
131cabdff1aSopenharmony_ci
132cabdff1aSopenharmony_ci    xpos        = 0; // lumXInc/2 - 0x8000; // difference between pixel centers
133cabdff1aSopenharmony_ci    fragmentPos = 0;
134cabdff1aSopenharmony_ci
135cabdff1aSopenharmony_ci    for (i = 0; i < dstW / numSplits; i++) {
136cabdff1aSopenharmony_ci        int xx = xpos >> 16;
137cabdff1aSopenharmony_ci
138cabdff1aSopenharmony_ci        if ((i & 3) == 0) {
139cabdff1aSopenharmony_ci            int a                  = 0;
140cabdff1aSopenharmony_ci            int b                  = ((xpos + xInc) >> 16) - xx;
141cabdff1aSopenharmony_ci            int c                  = ((xpos + xInc * 2) >> 16) - xx;
142cabdff1aSopenharmony_ci            int d                  = ((xpos + xInc * 3) >> 16) - xx;
143cabdff1aSopenharmony_ci            int inc                = (d + 1 < 4);
144cabdff1aSopenharmony_ci            uint8_t *fragment      = inc ? fragmentB : fragmentA;
145cabdff1aSopenharmony_ci            x86_reg imm8OfPShufW1  = inc ? imm8OfPShufW1B : imm8OfPShufW1A;
146cabdff1aSopenharmony_ci            x86_reg imm8OfPShufW2  = inc ? imm8OfPShufW2B : imm8OfPShufW2A;
147cabdff1aSopenharmony_ci            x86_reg fragmentLength = inc ? fragmentLengthB : fragmentLengthA;
148cabdff1aSopenharmony_ci            int maxShift           = 3 - (d + inc);
149cabdff1aSopenharmony_ci            int shift              = 0;
150cabdff1aSopenharmony_ci
151cabdff1aSopenharmony_ci            if (filterCode) {
152cabdff1aSopenharmony_ci                filter[i]        = ((xpos              & 0xFFFF) ^ 0xFFFF) >> 9;
153cabdff1aSopenharmony_ci                filter[i + 1]    = (((xpos + xInc)     & 0xFFFF) ^ 0xFFFF) >> 9;
154cabdff1aSopenharmony_ci                filter[i + 2]    = (((xpos + xInc * 2) & 0xFFFF) ^ 0xFFFF) >> 9;
155cabdff1aSopenharmony_ci                filter[i + 3]    = (((xpos + xInc * 3) & 0xFFFF) ^ 0xFFFF) >> 9;
156cabdff1aSopenharmony_ci                filterPos[i / 2] = xx;
157cabdff1aSopenharmony_ci
158cabdff1aSopenharmony_ci                memcpy(filterCode + fragmentPos, fragment, fragmentLength);
159cabdff1aSopenharmony_ci
160cabdff1aSopenharmony_ci                filterCode[fragmentPos + imm8OfPShufW1] =  (a + inc)       |
161cabdff1aSopenharmony_ci                                                          ((b + inc) << 2) |
162cabdff1aSopenharmony_ci                                                          ((c + inc) << 4) |
163cabdff1aSopenharmony_ci                                                          ((d + inc) << 6);
164cabdff1aSopenharmony_ci                filterCode[fragmentPos + imm8OfPShufW2] =  a | (b << 2) |
165cabdff1aSopenharmony_ci                                                               (c << 4) |
166cabdff1aSopenharmony_ci                                                               (d << 6);
167cabdff1aSopenharmony_ci
168cabdff1aSopenharmony_ci                if (i + 4 - inc >= dstW)
169cabdff1aSopenharmony_ci                    shift = maxShift;               // avoid overread
170cabdff1aSopenharmony_ci                else if ((filterPos[i / 2] & 3) <= maxShift)
171cabdff1aSopenharmony_ci                    shift = filterPos[i / 2] & 3;   // align
172cabdff1aSopenharmony_ci
173cabdff1aSopenharmony_ci                if (shift && i >= shift) {
174cabdff1aSopenharmony_ci                    filterCode[fragmentPos + imm8OfPShufW1] += 0x55 * shift;
175cabdff1aSopenharmony_ci                    filterCode[fragmentPos + imm8OfPShufW2] += 0x55 * shift;
176cabdff1aSopenharmony_ci                    filterPos[i / 2]                        -= shift;
177cabdff1aSopenharmony_ci                }
178cabdff1aSopenharmony_ci            }
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_ci            fragmentPos += fragmentLength;
181cabdff1aSopenharmony_ci
182cabdff1aSopenharmony_ci            if (filterCode)
183cabdff1aSopenharmony_ci                filterCode[fragmentPos] = RET;
184cabdff1aSopenharmony_ci        }
185cabdff1aSopenharmony_ci        xpos += xInc;
186cabdff1aSopenharmony_ci    }
187cabdff1aSopenharmony_ci    if (filterCode)
188cabdff1aSopenharmony_ci        filterPos[((i / 2) + 1) & (~1)] = xpos >> 16;  // needed to jump to the next part
189cabdff1aSopenharmony_ci
190cabdff1aSopenharmony_ci    return fragmentPos + 1;
191cabdff1aSopenharmony_ci}
192cabdff1aSopenharmony_ci
193cabdff1aSopenharmony_civoid ff_hyscale_fast_mmxext(SwsContext *c, int16_t *dst,
194cabdff1aSopenharmony_ci                                 int dstWidth, const uint8_t *src,
195cabdff1aSopenharmony_ci                                 int srcW, int xInc)
196cabdff1aSopenharmony_ci{
197cabdff1aSopenharmony_ci    int32_t *filterPos = c->hLumFilterPos;
198cabdff1aSopenharmony_ci    int16_t *filter    = c->hLumFilter;
199cabdff1aSopenharmony_ci    void    *mmxextFilterCode = c->lumMmxextFilterCode;
200cabdff1aSopenharmony_ci    int i;
201cabdff1aSopenharmony_ci#if ARCH_X86_64
202cabdff1aSopenharmony_ci    uint64_t retsave;
203cabdff1aSopenharmony_ci#else
204cabdff1aSopenharmony_ci#if !HAVE_EBX_AVAILABLE
205cabdff1aSopenharmony_ci    uint64_t ebxsave;
206cabdff1aSopenharmony_ci#endif
207cabdff1aSopenharmony_ci#endif
208cabdff1aSopenharmony_ci
209cabdff1aSopenharmony_ci    __asm__ volatile(
210cabdff1aSopenharmony_ci#if ARCH_X86_64
211cabdff1aSopenharmony_ci        "mov               -8(%%rsp), %%"FF_REG_a"    \n\t"
212cabdff1aSopenharmony_ci        "mov            %%"FF_REG_a", %5              \n\t"  // retsave
213cabdff1aSopenharmony_ci#else
214cabdff1aSopenharmony_ci#if !HAVE_EBX_AVAILABLE
215cabdff1aSopenharmony_ci        "mov            %%"FF_REG_b", %5              \n\t"  // ebxsave
216cabdff1aSopenharmony_ci#endif
217cabdff1aSopenharmony_ci#endif
218cabdff1aSopenharmony_ci        "pxor                  %%mm7, %%mm7           \n\t"
219cabdff1aSopenharmony_ci        "mov                      %0, %%"FF_REG_c"    \n\t"
220cabdff1aSopenharmony_ci        "mov                      %1, %%"FF_REG_D"    \n\t"
221cabdff1aSopenharmony_ci        "mov                      %2, %%"FF_REG_d"    \n\t"
222cabdff1aSopenharmony_ci        "mov                      %3, %%"FF_REG_b"    \n\t"
223cabdff1aSopenharmony_ci        "xor            %%"FF_REG_a", %%"FF_REG_a"    \n\t" // i
224cabdff1aSopenharmony_ci        PREFETCH"      (%%"FF_REG_c")                 \n\t"
225cabdff1aSopenharmony_ci        PREFETCH"    32(%%"FF_REG_c")                 \n\t"
226cabdff1aSopenharmony_ci        PREFETCH"    64(%%"FF_REG_c")                 \n\t"
227cabdff1aSopenharmony_ci
228cabdff1aSopenharmony_ci#if ARCH_X86_64
229cabdff1aSopenharmony_ci#define CALL_MMXEXT_FILTER_CODE \
230cabdff1aSopenharmony_ci        "movl               (%%"FF_REG_b"), %%esi        \n\t"\
231cabdff1aSopenharmony_ci        "call                          *%4               \n\t"\
232cabdff1aSopenharmony_ci        "movl (%%"FF_REG_b", %%"FF_REG_a"), %%esi        \n\t"\
233cabdff1aSopenharmony_ci        "add                  %%"FF_REG_S", %%"FF_REG_c" \n\t"\
234cabdff1aSopenharmony_ci        "add                  %%"FF_REG_a", %%"FF_REG_D" \n\t"\
235cabdff1aSopenharmony_ci        "xor                  %%"FF_REG_a", %%"FF_REG_a" \n\t"\
236cabdff1aSopenharmony_ci
237cabdff1aSopenharmony_ci#else
238cabdff1aSopenharmony_ci#define CALL_MMXEXT_FILTER_CODE \
239cabdff1aSopenharmony_ci        "movl               (%%"FF_REG_b"), %%esi        \n\t"\
240cabdff1aSopenharmony_ci        "call                          *%4               \n\t"\
241cabdff1aSopenharmony_ci        "addl (%%"FF_REG_b", %%"FF_REG_a"), %%"FF_REG_c" \n\t"\
242cabdff1aSopenharmony_ci        "add                  %%"FF_REG_a", %%"FF_REG_D" \n\t"\
243cabdff1aSopenharmony_ci        "xor                  %%"FF_REG_a", %%"FF_REG_a" \n\t"\
244cabdff1aSopenharmony_ci
245cabdff1aSopenharmony_ci#endif /* ARCH_X86_64 */
246cabdff1aSopenharmony_ci
247cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
248cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
249cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
250cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
251cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
252cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
253cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
254cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
255cabdff1aSopenharmony_ci
256cabdff1aSopenharmony_ci#if ARCH_X86_64
257cabdff1aSopenharmony_ci        "mov                      %5, %%"FF_REG_a" \n\t"
258cabdff1aSopenharmony_ci        "mov            %%"FF_REG_a", -8(%%rsp)    \n\t"
259cabdff1aSopenharmony_ci#else
260cabdff1aSopenharmony_ci#if !HAVE_EBX_AVAILABLE
261cabdff1aSopenharmony_ci        "mov                      %5, %%"FF_REG_b" \n\t"
262cabdff1aSopenharmony_ci#endif
263cabdff1aSopenharmony_ci#endif
264cabdff1aSopenharmony_ci        :: "m" (src), "m" (dst), "m" (filter), "m" (filterPos),
265cabdff1aSopenharmony_ci           "m" (mmxextFilterCode)
266cabdff1aSopenharmony_ci#if ARCH_X86_64
267cabdff1aSopenharmony_ci          ,"m"(retsave)
268cabdff1aSopenharmony_ci#else
269cabdff1aSopenharmony_ci#if !HAVE_EBX_AVAILABLE
270cabdff1aSopenharmony_ci          ,"m" (ebxsave)
271cabdff1aSopenharmony_ci#endif
272cabdff1aSopenharmony_ci#endif
273cabdff1aSopenharmony_ci        : "%"FF_REG_a, "%"FF_REG_c, "%"FF_REG_d, "%"FF_REG_S, "%"FF_REG_D
274cabdff1aSopenharmony_ci#if ARCH_X86_64 || HAVE_EBX_AVAILABLE
275cabdff1aSopenharmony_ci         ,"%"FF_REG_b
276cabdff1aSopenharmony_ci#endif
277cabdff1aSopenharmony_ci    );
278cabdff1aSopenharmony_ci
279cabdff1aSopenharmony_ci    for (i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--)
280cabdff1aSopenharmony_ci        dst[i] = src[srcW-1]*128;
281cabdff1aSopenharmony_ci}
282cabdff1aSopenharmony_ci
283cabdff1aSopenharmony_civoid ff_hcscale_fast_mmxext(SwsContext *c, int16_t *dst1, int16_t *dst2,
284cabdff1aSopenharmony_ci                                 int dstWidth, const uint8_t *src1,
285cabdff1aSopenharmony_ci                                 const uint8_t *src2, int srcW, int xInc)
286cabdff1aSopenharmony_ci{
287cabdff1aSopenharmony_ci    int32_t *filterPos = c->hChrFilterPos;
288cabdff1aSopenharmony_ci    int16_t *filter    = c->hChrFilter;
289cabdff1aSopenharmony_ci    void    *mmxextFilterCode = c->chrMmxextFilterCode;
290cabdff1aSopenharmony_ci    int i;
291cabdff1aSopenharmony_ci#if ARCH_X86_64
292cabdff1aSopenharmony_ci    DECLARE_ALIGNED(8, uint64_t, retsave);
293cabdff1aSopenharmony_ci#else
294cabdff1aSopenharmony_ci#if !HAVE_EBX_AVAILABLE
295cabdff1aSopenharmony_ci    DECLARE_ALIGNED(8, uint64_t, ebxsave);
296cabdff1aSopenharmony_ci#endif
297cabdff1aSopenharmony_ci#endif
298cabdff1aSopenharmony_ci    __asm__ volatile(
299cabdff1aSopenharmony_ci#if ARCH_X86_64
300cabdff1aSopenharmony_ci        "mov          -8(%%rsp), %%"FF_REG_a"    \n\t"
301cabdff1aSopenharmony_ci        "mov       %%"FF_REG_a", %7              \n\t"  // retsave
302cabdff1aSopenharmony_ci#else
303cabdff1aSopenharmony_ci#if !HAVE_EBX_AVAILABLE
304cabdff1aSopenharmony_ci        "mov       %%"FF_REG_b", %7              \n\t"  // ebxsave
305cabdff1aSopenharmony_ci#endif
306cabdff1aSopenharmony_ci#endif
307cabdff1aSopenharmony_ci        "pxor             %%mm7, %%mm7           \n\t"
308cabdff1aSopenharmony_ci        "mov                 %0, %%"FF_REG_c"    \n\t"
309cabdff1aSopenharmony_ci        "mov                 %1, %%"FF_REG_D"    \n\t"
310cabdff1aSopenharmony_ci        "mov                 %2, %%"FF_REG_d"    \n\t"
311cabdff1aSopenharmony_ci        "mov                 %3, %%"FF_REG_b"    \n\t"
312cabdff1aSopenharmony_ci        "xor          %%"FF_REG_a", %%"FF_REG_a" \n\t" // i
313cabdff1aSopenharmony_ci        PREFETCH"   (%%"FF_REG_c")               \n\t"
314cabdff1aSopenharmony_ci        PREFETCH" 32(%%"FF_REG_c")               \n\t"
315cabdff1aSopenharmony_ci        PREFETCH" 64(%%"FF_REG_c")               \n\t"
316cabdff1aSopenharmony_ci
317cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
318cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
319cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
320cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
321cabdff1aSopenharmony_ci        "xor          %%"FF_REG_a", %%"FF_REG_a" \n\t" // i
322cabdff1aSopenharmony_ci        "mov                    %5, %%"FF_REG_c" \n\t" // src2
323cabdff1aSopenharmony_ci        "mov                    %6, %%"FF_REG_D" \n\t" // dst2
324cabdff1aSopenharmony_ci        PREFETCH"   (%%"FF_REG_c")               \n\t"
325cabdff1aSopenharmony_ci        PREFETCH" 32(%%"FF_REG_c")               \n\t"
326cabdff1aSopenharmony_ci        PREFETCH" 64(%%"FF_REG_c")               \n\t"
327cabdff1aSopenharmony_ci
328cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
329cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
330cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
331cabdff1aSopenharmony_ci        CALL_MMXEXT_FILTER_CODE
332cabdff1aSopenharmony_ci
333cabdff1aSopenharmony_ci#if ARCH_X86_64
334cabdff1aSopenharmony_ci        "mov                    %7, %%"FF_REG_a" \n\t"
335cabdff1aSopenharmony_ci        "mov          %%"FF_REG_a", -8(%%rsp)    \n\t"
336cabdff1aSopenharmony_ci#else
337cabdff1aSopenharmony_ci#if !HAVE_EBX_AVAILABLE
338cabdff1aSopenharmony_ci        "mov %7, %%"FF_REG_b"    \n\t"
339cabdff1aSopenharmony_ci#endif
340cabdff1aSopenharmony_ci#endif
341cabdff1aSopenharmony_ci        :: "m" (src1), "m" (dst1), "m" (filter), "m" (filterPos),
342cabdff1aSopenharmony_ci           "m" (mmxextFilterCode), "m" (src2), "m"(dst2)
343cabdff1aSopenharmony_ci#if ARCH_X86_64
344cabdff1aSopenharmony_ci          ,"m"(retsave)
345cabdff1aSopenharmony_ci#else
346cabdff1aSopenharmony_ci#if !HAVE_EBX_AVAILABLE
347cabdff1aSopenharmony_ci          ,"m" (ebxsave)
348cabdff1aSopenharmony_ci#endif
349cabdff1aSopenharmony_ci#endif
350cabdff1aSopenharmony_ci        : "%"FF_REG_a, "%"FF_REG_c, "%"FF_REG_d, "%"FF_REG_S, "%"FF_REG_D
351cabdff1aSopenharmony_ci#if ARCH_X86_64 || HAVE_EBX_AVAILABLE
352cabdff1aSopenharmony_ci         ,"%"FF_REG_b
353cabdff1aSopenharmony_ci#endif
354cabdff1aSopenharmony_ci    );
355cabdff1aSopenharmony_ci
356cabdff1aSopenharmony_ci    for (i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--) {
357cabdff1aSopenharmony_ci        dst1[i] = src1[srcW-1]*128;
358cabdff1aSopenharmony_ci        dst2[i] = src2[srcW-1]*128;
359cabdff1aSopenharmony_ci    }
360cabdff1aSopenharmony_ci}
361cabdff1aSopenharmony_ci#endif //HAVE_INLINE_ASM
362