我得到了一些包含无符号字符的向量,这些字符表示来自一个帧的像素。我让这个功能在没有MMX改进的情况下工作,但我感到沮丧的是,MMX没有工作.所以:
我需要添加两个没有符号的字符(需要以16位的形式完成和,而不是8位,因为无符号字符从0到255,如已知的那样),然后除以2(右移1)。到目前为止,我所做的代码如下所示,但是值是错误的,adds_pu16不添加16位,只添加8:
MM0 = _mm_setzero_si64(); //all zeros
MM1 = TO_M64(lv1+k); //first 8 unsigned chars
MM2 = TO_M64(lv2+k); //second 8 unsigned chars
MM3 =_mm_unpacklo_pi8(MM0,MM1); //get first 4chars from MM1 and add Zeros
MM4 =_mm_unpackhi_pi8(MM0,MM1); //get last 4chars from MM1 and add Zeros
MM5 =_mm_unpacklo_pi8(MM0,MM2); //same as above for line 2
MM6 =_mm_unpackhi_pi8(MM0,MM2);
MM1 = _mm_adds_pu16(MM3,MM5); //add both chars as a 16bit sum (255+255 max range)
MM2 = _mm_adds_pu16(MM4,MM6);
MM3 = _mm_srai_pi16(MM1,1); //right shift (division by 2)
MM4 = _mm_srai_pi16(MM2,1);
MM1 = _mm_packs_pi16(MM3,MM4); //pack the 2 MMX registers into one
v2 = TO_UCHAR(MM1); //put results in the destination array新的发展:谢谢你的king_nak!我写了一个我想要做的事情的简单版本:
int main()
{
char A[8]={255,155,2,3,4,5,6,7};
char B[8]={255,155,2,3,4,5,6,7};
char C[8];
char D[8];
char R[8];
__m64* pA=(__m64*) A;
__m64* pB=(__m64*) B;
__m64* pC=(__m64*) C;
__m64* pD=(__m64*) D;
__m64* pR=(__m64*) R;
_mm_empty();
__m64 MM0 = _mm_setzero_si64();
__m64 MM1 = _mm_unpacklo_pi8(*pA,MM0);
__m64 MM2 = _mm_unpackhi_pi8(*pA,MM0);
__m64 MM3 = _mm_unpacklo_pi8(*pB,MM0);
__m64 MM4 = _mm_unpackhi_pi8(*pB,MM0);
__m64 MM5 = _mm_add_pi16(MM1,MM3);
__m64 MM6 = _mm_add_pi16(MM2,MM4);
printf("SUM:\n");
*pC= _mm_add_pi16(MM1,MM3);
*pD= _mm_add_pi16(MM2,MM4);
for(int i=0; i<8; i++) printf("\t%d ", (C[i])); printf("\n");
for(int i=0; i<8; i++) printf("\t%d ", D[i]); printf("\n");
printf("DIV:\n");
*pC= _mm_srai_pi16(MM5,1);
*pD= _mm_srai_pi16(MM6,1);
for(int i=0; i<8; i++) printf("\t%d ", (C[i])); printf("\n");
for(int i=0; i<8; i++) printf("\t%d ", D[i]); printf("\n");
MM1= _mm_srai_pi16(MM5,1);
MM2= _mm_srai_pi16(MM6,1);
printf("Final Result:\n");
*pR= _mm_packs_pi16(MM1,MM2);
for(int i=0; i<8; i++) printf("\t%d ", (R[i])); printf("\n");
return(0);
}其结果是:
总数:
-2 1 54 1 4 0 6 0
8 0 10 0 12 0 14 0 DIV:
-1 0 -101 0 2 0 3 0
4 0 5 0 6 0 7 0 最终结果:
127 127 2 3 4 5 6 7 好的,小的数字是可以的,而给出127的大数字是错误的。这是个问题,我做错了什么?
发布于 2011-06-29 14:59:26
我想我发现了一个问题:解压指令的论点是错误的。如果你把这些寄存器作为一个整体来看,它看起来就像单个字符是零延伸到空头,但实际上,它们是零垫。在每一种情况下,只需在mm0和另一个寄存器之间交换,它就会正常工作。
另外,您不需要饱和添加,正常的PADDW就足够了。您将得到的最大值是0xff+0xff=0x01fe,它不一定是饱和的。
编辑:,更重要的是,PACKSSWB并不完全按照您的要求来做。PACKUSWB是正确的指令,饱和度会给你带来错误的结果。
这里有一个解决方案(也用逻辑移位代替了转移,并在某些地方使用了不同的伪寄存器):
mm0=pxor(mm0,mm0) =[00,00,00,00,00,00,00,00]
mm1 =[a0,10,ff,18,7f,f0,ff,cc]
mm2 =[c0,20,ff,00,70,26,ff,01]
mm3=punpcklbw(mm1,mm0) =[00a0,0010,00ff,0018]
mm4=punpckhbw(mm1,mm0) =[007f,00f0,00ff,00cc]
mm5=punpcklbw(mm2,mm0) =[00c0,0020,00ff,0000]
mm6=punpckhbw(mm2,mm0) =[0070,0026,00ff,0001]
mm5=paddw(mm3,mm5) =[0160,0030,01fe,0018]
mm6=paddw(mm4,mm6) =[00ef,0116,01fe,00cd]
mm3=psrlwi(mm5,1) =[00b0,0018,00ff,000c]
mm4=psrlwi(mm6,1) =[0077,008b,00ff,0066]
mm1=packuswb(mm3,mm4) =[b0,18,ff,0c,77,8b,ff,66]发布于 2011-06-29 11:59:45
您应该在_mm_unpacklo_pi8调用中切换操作数。当您这样做时,值字节位于单词的较高字节(例如,AB和00打包到AB00中)。在加法和移位之后,值将大于0x7F,因此pack指令已饱和到该值。
通过切换操作数,对像00AB这样的值进行计算,结果将适合于一个有符号的字节。
UPATE:
在您的附加信息之后,我发现问题在于_mm_packs_pi16。这是程序集指令packsswb,它将饱和有符号字节。例如,值> 127将设置为127。(255+255)>>1是255,(155+155)>>1是155.
使用_mm_packs_pu16代替。这将这些值视为无符号字节,并得到所需的结果(255/155)。
https://stackoverflow.com/questions/6519913
复制相似问题