Go to the documentation of this file.
21 #include "../swscale_internal.h"
27 #define RET 0xC3 // near return opcode for x86
28 #define PREFETCH "prefetchnta"
59 "movq (%%"FF_REG_d
", %%"FF_REG_a
"), %%mm3 \n\t"
60 "movd (%%"FF_REG_c
", %%"FF_REG_S
"), %%mm0 \n\t"
61 "movd 1(%%"FF_REG_c
", %%"FF_REG_S
"), %%mm1 \n\t"
62 "punpcklbw %%mm7, %%mm1 \n\t"
63 "punpcklbw %%mm7, %%mm0 \n\t"
64 "pshufw $0xFF, %%mm1, %%mm1 \n\t"
66 "pshufw $0xFF, %%mm0, %%mm0 \n\t"
68 "psubw %%mm1, %%mm0 \n\t"
69 "movl 8(%%"FF_REG_b
", %%"FF_REG_a
"), %%esi \n\t"
70 "pmullw %%mm3, %%mm0 \n\t"
71 "psllw $7, %%mm1 \n\t"
72 "paddw %%mm1, %%mm0 \n\t"
74 "movq %%mm0, (%%"FF_REG_D
", %%"FF_REG_a
") \n\t"
76 "add $8, %%"FF_REG_a
" \n\t"
90 :
"=r" (fragmentA),
"=r" (imm8OfPShufW1A),
"=r" (imm8OfPShufW2A),
91 "=r" (fragmentLengthA)
98 "movq (%%"FF_REG_d
", %%"FF_REG_a
"), %%mm3 \n\t"
99 "movd (%%"FF_REG_c
", %%"FF_REG_S
"), %%mm0 \n\t"
100 "punpcklbw %%mm7, %%mm0 \n\t"
101 "pshufw $0xFF, %%mm0, %%mm1 \n\t"
103 "pshufw $0xFF, %%mm0, %%mm0 \n\t"
105 "psubw %%mm1, %%mm0 \n\t"
106 "movl 8(%%"FF_REG_b
", %%"FF_REG_a
"), %%esi \n\t"
107 "pmullw %%mm3, %%mm0 \n\t"
108 "psllw $7, %%mm1 \n\t"
109 "paddw %%mm1, %%mm0 \n\t"
111 "movq %%mm0, (%%"FF_REG_D
", %%"FF_REG_a
") \n\t"
113 "add $8, %%"FF_REG_a
" \n\t"
127 :
"=r" (fragmentB),
"=r" (imm8OfPShufW1B),
"=r" (imm8OfPShufW2B),
128 "=r" (fragmentLengthB)
134 for (
i = 0;
i < dstW / numSplits;
i++) {
139 int b = ((xpos + xInc) >> 16) - xx;
140 int c = ((xpos + xInc * 2) >> 16) - xx;
141 int d = ((xpos + xInc * 3) >> 16) - xx;
142 int inc = (d + 1 < 4);
144 x86_reg imm8OfPShufW1 =
inc ? imm8OfPShufW1B : imm8OfPShufW1A;
145 x86_reg imm8OfPShufW2 =
inc ? imm8OfPShufW2B : imm8OfPShufW2A;
146 x86_reg fragmentLength =
inc ? fragmentLengthB : fragmentLengthA;
147 int maxShift = 3 - (d +
inc);
151 filter[
i] = ((xpos & 0xFFFF) ^ 0xFFFF) >> 9;
152 filter[
i + 1] = (((xpos + xInc) & 0xFFFF) ^ 0xFFFF) >> 9;
153 filter[
i + 2] = (((xpos + xInc * 2) & 0xFFFF) ^ 0xFFFF) >> 9;
154 filter[
i + 3] = (((xpos + xInc * 3) & 0xFFFF) ^ 0xFFFF) >> 9;
155 filterPos[
i / 2] = xx;
157 memcpy(filterCode + fragmentPos,
fragment, fragmentLength);
159 filterCode[fragmentPos + imm8OfPShufW1] = (
a +
inc) |
163 filterCode[fragmentPos + imm8OfPShufW2] =
a | (
b << 2) |
167 if (
i + 4 -
inc >= dstW)
169 else if ((filterPos[
i / 2] & 3) <= maxShift)
170 shift = filterPos[
i / 2] & 3;
173 filterCode[fragmentPos + imm8OfPShufW1] += 0x55 *
shift;
174 filterCode[fragmentPos + imm8OfPShufW2] += 0x55 *
shift;
175 filterPos[
i / 2] -=
shift;
179 fragmentPos += fragmentLength;
182 filterCode[fragmentPos] =
RET;
187 filterPos[((
i / 2) + 1) & (~1)] = xpos >> 16;
189 return fragmentPos + 1;
193 int dstWidth,
const uint8_t *
src,
196 int32_t *filterPos =
c->hLumFilterPos;
197 int16_t *
filter =
c->hLumFilter;
198 void *mmxextFilterCode =
c->lumMmxextFilterCode;
203 #if !HAVE_EBX_AVAILABLE
210 "mov -8(%%rsp), %%"FF_REG_a
" \n\t"
211 "mov %%"FF_REG_a
", %5 \n\t"
213 #if !HAVE_EBX_AVAILABLE
214 "mov %%"FF_REG_b
", %5 \n\t"
217 "pxor %%mm7, %%mm7 \n\t"
218 "mov %0, %%"FF_REG_c
" \n\t"
219 "mov %1, %%"FF_REG_D
" \n\t"
220 "mov %2, %%"FF_REG_d
" \n\t"
221 "mov %3, %%"FF_REG_b
" \n\t"
222 "xor %%"FF_REG_a
", %%"FF_REG_a
" \n\t"
228 #define CALL_MMXEXT_FILTER_CODE \
229 "movl (%%"FF_REG_b"), %%esi \n\t"\
231 "movl (%%"FF_REG_b", %%"FF_REG_a"), %%esi \n\t"\
232 "add %%"FF_REG_S", %%"FF_REG_c" \n\t"\
233 "add %%"FF_REG_a", %%"FF_REG_D" \n\t"\
234 "xor %%"FF_REG_a", %%"FF_REG_a" \n\t"\
237 #define CALL_MMXEXT_FILTER_CODE \
238 "movl (%%"FF_REG_b"), %%esi \n\t"\
240 "addl (%%"FF_REG_b", %%"FF_REG_a"), %%"FF_REG_c" \n\t"\
241 "add %%"FF_REG_a", %%"FF_REG_D" \n\t"\
242 "xor %%"FF_REG_a", %%"FF_REG_a" \n\t"\
256 "mov %5, %%"FF_REG_a
" \n\t"
257 "mov %%"FF_REG_a
", -8(%%rsp) \n\t"
259 #if !HAVE_EBX_AVAILABLE
260 "mov %5, %%"FF_REG_b
" \n\t"
264 "m" (mmxextFilterCode)
268 #if !HAVE_EBX_AVAILABLE
272 :
"%"FF_REG_a,
"%"FF_REG_c,
"%"FF_REG_d,
"%"FF_REG_S,
"%"FF_REG_D
278 for (
i=dstWidth-1; (
i*xInc)>>16 >=srcW-1;
i--)
283 int dstWidth,
const uint8_t *
src1,
284 const uint8_t *
src2,
int srcW,
int xInc)
286 int32_t *filterPos =
c->hChrFilterPos;
287 int16_t *
filter =
c->hChrFilter;
288 void *mmxextFilterCode =
c->chrMmxextFilterCode;
293 #if !HAVE_EBX_AVAILABLE
299 "mov -8(%%rsp), %%"FF_REG_a
" \n\t"
300 "mov %%"FF_REG_a
", %7 \n\t"
302 #if !HAVE_EBX_AVAILABLE
303 "mov %%"FF_REG_b
", %7 \n\t"
306 "pxor %%mm7, %%mm7 \n\t"
307 "mov %0, %%"FF_REG_c
" \n\t"
308 "mov %1, %%"FF_REG_D
" \n\t"
309 "mov %2, %%"FF_REG_d
" \n\t"
310 "mov %3, %%"FF_REG_b
" \n\t"
311 "xor %%"FF_REG_a
", %%"FF_REG_a
" \n\t"
320 "xor %%"FF_REG_a
", %%"FF_REG_a
" \n\t"
321 "mov %5, %%"FF_REG_c
" \n\t"
322 "mov %6, %%"FF_REG_D
" \n\t"
333 "mov %7, %%"FF_REG_a
" \n\t"
334 "mov %%"FF_REG_a
", -8(%%rsp) \n\t"
336 #if !HAVE_EBX_AVAILABLE
337 "mov %7, %%"FF_REG_b
" \n\t"
340 ::
"m" (
src1),
"m" (dst1),
"m" (
filter),
"m" (filterPos),
341 "m" (mmxextFilterCode),
"m" (
src2),
"m"(dst2)
345 #if !HAVE_EBX_AVAILABLE
349 :
"%"FF_REG_a,
"%"FF_REG_c,
"%"FF_REG_d,
"%"FF_REG_S,
"%"FF_REG_D
355 for (
i=dstWidth-1; (
i*xInc)>>16 >=srcW-1;
i--) {
356 dst1[
i] =
src1[srcW-1]*128;
357 dst2[
i] =
src2[srcW-1]*128;
#define CALL_MMXEXT_FILTER_CODE
void(* filter)(uint8_t *src, int stride, int qscale)
void ff_hcscale_fast_mmxext(SwsInternal *c, int16_t *dst1, int16_t *dst2, int dstWidth, const uint8_t *src1, const uint8_t *src2, int srcW, int xInc)
av_cold int ff_init_hscaler_mmxext(int dstW, int xInc, uint8_t *filterCode, int16_t *filter, int32_t *filterPos, int numSplits)
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
static int inc(int num, int period)
#define DECLARE_ALIGNED(n, t, v)
static int shift(int a, int b)
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
#define i(width, name, range_min, range_max)
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
void ff_hyscale_fast_mmxext(SwsInternal *c, int16_t *dst, int dstWidth, const uint8_t *src, int srcW, int xInc)
__asm__(".macro parse_r var r\n\t" "\\var = -1\n\t" _IFC_REG(0) _IFC_REG(1) _IFC_REG(2) _IFC_REG(3) _IFC_REG(4) _IFC_REG(5) _IFC_REG(6) _IFC_REG(7) _IFC_REG(8) _IFC_REG(9) _IFC_REG(10) _IFC_REG(11) _IFC_REG(12) _IFC_REG(13) _IFC_REG(14) _IFC_REG(15) _IFC_REG(16) _IFC_REG(17) _IFC_REG(18) _IFC_REG(19) _IFC_REG(20) _IFC_REG(21) _IFC_REG(22) _IFC_REG(23) _IFC_REG(24) _IFC_REG(25) _IFC_REG(26) _IFC_REG(27) _IFC_REG(28) _IFC_REG(29) _IFC_REG(30) _IFC_REG(31) ".iflt \\var\n\t" ".error \"Unable to parse register name \\r\"\n\t" ".endif\n\t" ".endm")