可以替代Arm64中缺少的SSAT和USAT指令吗?

时间:2018-11-13 10:46:05

标签: assembly arm arm64

我们正在将主要应用程序从Arm32移植到Arm64。我们的算法经常使用SSATUSAT指令。它们非常有用,可以执行任意大小的左移或右移,然后将有符号或无符号饱和到任意位数。这对于图像处理算法非常有用,因为我们可以执行一些数学运算来生成32位整数结果,然后从中获取所需的任何位(饱和到输出图像的位深度的最大值/最小值),一条指令。

这些指令在Arm64中已经莫名其妙地消失了,我们找到的最接近的替代方法是SQSHRN / UQSHRN / SQSHLN / UQSHLN,它们执行移位并饱和,但是它们执行的饱和度受到更大的限制(USAT可以饱和到任何宽度,甚至7位;新指令只能饱和到输入宽度的一半,例如,对于32位输入,则为16位。需要额外的处理才能获得所需的结果。

有人可以解释为什么删除了这些指令,以及有效移植使用它们的现有代码的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

-更新-使用非汇编代码时,正确测试的时间明显变慢,我将继续寻找其他方法

我比较了以下汇编代码:

#define __arm_ssat(src, bits)   asm("ssat %[srcr], %[satv], %[srcr]"    :[srcr]"+r"(src):[satv]"I"(bits));

与此:

#define MAX_SIGNED_NUM(bits) ((1 << (bits -1)) -1)
#define __arm_ssat(src, bits)   {src = ((src > MAX_SIGNED_NUM(bits)) ? MAX_SIGNED_NUM(bits) : src);}

在32位设备上运行此--UPDATED TEST-时:

volatile  void assert_ssat_asm(int* buf, size_t loops){
    int64_t num = buf[0];
    int64_t num_a = buf[1];
    int64_t num_b = buf[2];
    int sum = 0;
    struct timeval tmv1; gettimeofday(&tmv1,NULL);
    for (int i = 0; i < loops; ++i){
        __arm_ssat(num, 8);
        sum+=num;
        assert( 127 == num);
        num = buf[0];

        __arm_ssat(num, 16);
        sum+=num;
        assert(32767 == num);

        __arm_ssat(num_a, 8);
        sum+=num;
        assert( 127 == num_a);
        num_a = buf[1];

        __arm_ssat(num_a, 16);
        sum+=num;
        assert( 690 == num_a);

        __arm_ssat(num_b, 8);
        sum+=num;
        assert( 127 == num_b);
        num_b = buf[2];

        __arm_ssat(num_b, 16);
        sum+=num;
        assert( 32767 == num_b);
    }
    struct timeval tmv2; gettimeofday(&tmv2,NULL);
    int tdiff_usec = (tmv2.tv_sec*1000000 + tmv2.tv_usec) - (tmv1.tv_sec*1000000 + tmv1.tv_usec);

    printf("%d\n", sum);
    printf("ran %d times, total time: %d,  average time asm: %.7f\n", loops, tdiff_usec, (double)tdiff_usec/loops);
}
int main ()
{
    int buf[] = { 69000, 690, 64000 };
    test_ssat(buf, 1000000);
}

我得到了那些结果:

  

运行1000000次循环,平均时间调节:0.0210270

     

运行1000000循环,平均时间汇编:0.0057960