📄 mmx_gcc.cpp
字号:
// multiply-add mm0*mm6 and mm1*mm7, store results into mm0 and mm1 // divide mm0 and mm1 by 512 (=right-shift by overlapDividerBits) // pack the result into mm0 and store into [edx] // // Load [eax+8] into mm2 and mm3 // Load [ebx+8] into mm4 // unpack words of mm2, mm3 and mm4 into mm2 and mm3 // multiply-add mm2*mm6 and mm3*mm7, store results into mm2 and mm3 // divide mm2 and mm3 by 512 (=right-shift by overlapDividerBits) // pack the result into mm2 and store into [edx+8] "movq (%%eax), %%mm0\n\t" // mm0 = m1l m1r m0l m0r "add $16, %%edx\n\t" "movq (%%ebx), %%mm3\n\t" // mm3 = i1l i1r i0l i0r "movq %%mm0, %%mm1\n\t" // mm1 = m1l m1r m0l m0r "movq 8(%%eax), %%mm2\n\t" // mm2 = m3l m3r m2l m2r "punpcklwd %%mm3, %%mm0\n\t" // mm0 = i0l m0l i0r m0r "movq 8(%%ebx), %%mm4\n\t" // mm4 = i3l i3r i2l i2r "punpckhwd %%mm3, %%mm1\n\t" // mm1 = i1l m1l i1r m1r "movq %%mm2, %%mm3\n\t" // mm3 = m3l m3r m2l m2r "punpcklwd %%mm4, %%mm2\n\t" // mm2 = i2l m2l i2r m2r "pmaddwd %%mm6, %%mm0\n\t" // mm0 = i0l*m63+m0l*m62 i0r*m61+m0r*m60 "punpckhwd %%mm4, %%mm3\n\t" // mm3 = i3l m3l i3r m3r "movd %%esi, %%mm4\n\t" // mm4 = overlapDividerBits "pmaddwd %%mm7, %%mm1\n\t" // mm1 = i1l*m73+m1l*m72 i1r*m71+m1r*m70 "paddw %%mm5, %%mm6\n\t" "paddw %%mm5, %%mm7\n\t" "psrad %%mm4, %%mm0\n\t" // mmo >>= overlapDividerBits "pmaddwd %%mm6, %%mm2\n\t" // mm2 = i2l*m63+m2l*m62 i2r*m61+m2r*m60 "psrad %%mm4, %%mm1\n\t" // mm1 >>= overlapDividerBits "pmaddwd %%mm7, %%mm3\n\t" // mm3 = i3l*m73+m3l*m72 i3r*m71+m3r*m70 "psrad %%mm4, %%mm2\n\t" // mm2 >>= overlapDividerBits "packssdw %%mm1, %%mm0\n\t" // mm0 = mm1h mm1l mm0h mm0l "psrad %%mm4, %%mm3\n\t" // mm3 >>= overlapDividerBits "add $16, %%eax\n\t" "paddw %%mm5, %%mm6\n\t" "packssdw %%mm3, %%mm2\n\t" // mm2 = mm2h mm2l mm3h mm3l "paddw %%mm5, %%mm7\n\t" "movq %%mm0, -16(%%edx)\n\t" "add $16, %%ebx\n\t" "movq %%mm2, -8(%%edx)\n\t" "dec %%ecx\n\t" "jnz 2b\n\t" "emms\n\t" "movl %0, %%esi\n\t" : "+rim" (shadow_esi)/* output */ : "rim" (local_overlapLength), "rim" (local_overlapDividerBits), "rim" (output), "rim" (input), "rim" (local_midBuffer) /* input */ : "%edi", "%ecx", "%edx", "%eax", "%ebx" /* regs */ );#else throw runtime_error("MMX not supported");#endif}////////////////////////////////////////////////////////////////////////////////// implementation of MMX optimized functions of class 'FIRFilter'////////////////////////////////////////////////////////////////////////////////#include "FIRFilter.h"FIRFilterMMX::FIRFilterMMX() : FIRFilter(){ filterCoeffsUnalign = NULL;}FIRFilterMMX::~FIRFilterMMX(){ delete[] filterCoeffsUnalign;}// (overloaded) Calculates filter coefficients for MMX routinevoid FIRFilterMMX::setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor){#ifdef __i386__ uint i; FIRFilter::setCoefficients(coeffs, newLength, uResultDivFactor); // Ensure that filter coeffs array is aligned to 16-byte boundary delete[] filterCoeffsUnalign; filterCoeffsUnalign = new short[2 * newLength + 8]; filterCoeffsAlign = (short *)(((uint)filterCoeffsUnalign + 15) & -16); // rearrange the filter coefficients for mmx routines for (i = 0;i < length; i += 4) { filterCoeffsAlign[2 * i + 0] = coeffs[i + 0]; filterCoeffsAlign[2 * i + 1] = coeffs[i + 2]; filterCoeffsAlign[2 * i + 2] = coeffs[i + 0]; filterCoeffsAlign[2 * i + 3] = coeffs[i + 2]; filterCoeffsAlign[2 * i + 4] = coeffs[i + 1]; filterCoeffsAlign[2 * i + 5] = coeffs[i + 3]; filterCoeffsAlign[2 * i + 6] = coeffs[i + 1]; filterCoeffsAlign[2 * i + 7] = coeffs[i + 3]; }#else throw runtime_error("MMX not supported");#endif}// mmx-optimized version of the filter routine for stereo sounduint FIRFilterMMX::evaluateFilterStereo(short *dest, const short *src, const uint numSamples) const{#ifdef __i386__ // Create stack copies of the needed member variables for asm routines : uint local_length = length; uint local_lengthDiv8 = lengthDiv8; uint local_resultDivider = resultDivFactor; short *local_filterCoeffs = (short*)filterCoeffsAlign; short *local_src = (short *)src; asm volatile( "\n\t" // Load (num_samples-aa_filter_length)/2 to edi as a i // Load a pointer to samples to esi // Load a pointer to destination to edx "movl %0, %%edi\n\t" "subl %2, %%edi\n\t" "movl %3, %%edx\n\t" "sar $1, %%edi\n" // Load filter length/8 to ecx // Load pointer to samples from esi to ebx // Load counter from edi to ecx // Load [ebx] to mm3 // Load pointer to filter coefficients to eax "3:\n\t" "movl %1, %%ebx\n\t" "pxor %%mm0, %%mm0\n\t" "movl %4, %%ecx\n\t" "pxor %%mm7, %%mm7\n\t" "movq (%%ebx), %%mm1\n\t" // mm1 = l1 r1 l0 r0 "movl %5, %%eax\n" "4:\n\t" "movq 8(%%ebx), %%mm2\n\t" // mm2 = l3 r3 l2 r2 "movq %%mm1, %%mm4\n\t" // mm4 = l1 r1 l0 r0 "movq 16(%%ebx), %%mm3\n\t" // mm3 = l5 r5 l4 r4 "punpckhwd %%mm2, %%mm1\n\t" // mm1 = l3 l1 r3 r1 "movq %%mm2, %%mm6\n\t" // mm6 = l3 r3 l2 r2 "punpcklwd %%mm2, %%mm4\n\t" // mm4 = l2 l0 r2 r0 "movq (%%eax), %%mm2\n\t" // mm2 = f2 f0 f2 f0 "movq %%mm1, %%mm5\n\t" // mm5 = l3 l1 r3 r1 "punpcklwd %%mm3, %%mm6\n\t" // mm6 = l4 l2 r4 r2 "pmaddwd %%mm2, %%mm4\n\t" // mm4 = l2*f2+l0*f0 r2*f2+r0*f0 "pmaddwd %%mm2, %%mm5\n\t" // mm5 = l3*f2+l1*f0 r3*f2+l1*f0 "movq 8(%%eax), %%mm2\n\t" // mm2 = f3 f1 f3 f1 "paddd %%mm4, %%mm0\n\t" // mm0 += s02*f02 "movq %%mm3, %%mm4\n\t" // mm4 = l1 r1 l0 r0 "pmaddwd %%mm2, %%mm1\n\t" // mm1 = l3*f3+l1*f1 r3*f3+l1*f1 "paddd %%mm5, %%mm7\n\t" // mm7 += s13*f02 "pmaddwd %%mm2, %%mm6\n\t" // mm6 = l4*f3+l2*f1 r4*f3+f4*f1 "movq 24(%%ebx), %%mm2\n\t" // mm2 = l3 r3 l2 r2 "paddd %%mm1, %%mm0\n\t" // mm0 += s31*f31 "movq 32(%%ebx), %%mm1\n\t" // mm1 = l5 r5 l4 r4 "paddd %%mm6, %%mm7\n\t" // mm7 += s42*f31 "punpckhwd %%mm2, %%mm3\n\t" // mm3 = l3 l1 r3 r1 "movq %%mm2, %%mm6\n\t" // mm6 = l3 r3 l2 r2 "punpcklwd %%mm2, %%mm4\n\t" // mm4 = l2 l0 r2 r0 "movq 16(%%eax), %%mm2\n\t" // mm2 = f2 f0 f2 f0 "movq %%mm3, %%mm5\n\t" // mm5 = l3 l1 r3 r1 "punpcklwd %%mm1, %%mm6\n\t" // mm6 = l4 l2 r4 r2 "add $32, %%eax\n\t" "pmaddwd %%mm2, %%mm4\n\t" // mm4 = l2*f2+l0*f0 r2*f2+r0*f0 "add $32, %%ebx\n\t" "pmaddwd %%mm2, %%mm5\n\t" // mm5 = l3*f2+l1*f0 r3*f2+l1*f0 "movq -8(%%eax), %%mm2\n\t" // mm2 = f3 f1 f3 f1 "paddd %%mm4, %%mm0\n\t" // mm0 += s02*f02 "pmaddwd %%mm2, %%mm3\n\t" // mm3 = l3*f3+l1*f1 r3*f3+l1*f1 "paddd %%mm5, %%mm7\n\t" // mm7 += s13*f02 "pmaddwd %%mm2, %%mm6\n\t" // mm6 = l4*f3+l2*f1 r4*f3+f4*f1 "paddd %%mm3, %%mm0\n\t" // mm0 += s31*f31 "paddd %%mm6, %%mm7\n\t" // mm7 += s42*f31 "dec %%ecx\n\t" "jnz 4b\n\t" // Divide mm0 and mm7 by 8192 (= right-shift by 13), // pack and store to [edx] "movd %6, %%mm4\n\t" "psrad %%mm4, %%mm0\n\t" // divide the result "add $8, %%edx\n\t" "psrad %%mm4, %%mm7\n\t" // divide the result "add $8, %1\n\t" "packssdw %%mm7, %%mm0\n\t" "movq %%mm0, -8(%%edx)\n\t" "dec %%edi\n\t" "jnz 3b\n\t" "emms\n\t" : /* output */ : "rim" (numSamples), "rim" (local_src), "rim" (local_length), "rim" (dest), "rim" (local_lengthDiv8), "rim" (local_filterCoeffs), "rim" (local_resultDivider) /* input */ : "%eax", "%ebx", "%ecx", "%edx", "%edi"/*, "%esi"*/ /* regs */ ); return (numSamples & 0xfffffffe) - local_length;#else throw runtime_error("MMX not supported"); return 0;#endif}#endif // ALLOW_MMX
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -