2015-07-20 199 views
1

我正在尝试制作一些内联汇编以测试ARM上旋转的性能。代码是C++代码库的一部分,所以旋转是模板专业化。代码如下,但它的生成信息对我来说没有多大意义。32位字旋转的ARM内联汇编

ARM Assembly Language,指令大致为:

# rotate - rotate instruction 
# dst - output operand 
# lhs - value to be rotated 
# rhs - rotate amount (immediate or register) 
<rotate> <dst>, <lhs>, <rhs> 

他们不作出了很多的意义,因为(我),比如我用g来约束输出寄存器,这只是一个通用目的寄存器,每Simple Contraints。 ARM应该有很多,并且Machine Specific Constraints似乎没有改变约束的行为。

我不知道接近这一点的最好办法,所以我要问三个问题:使用常数或立即值时

  1. 如何编码的旋转?
  2. 如何使用通过寄存器传递的值对旋转进行编码?
  3. 如何将拇指模式改变内联汇编

arm-linux-androideabi-g++ -DNDEBUG -g2 -Os -pipe -fPIC -mfloat-abi=softfp 
-mfpu=vfpv3-d16 -mthumb --sysroot=/opt/android-ndk-r10e/platforms/android-21/arch-arm 
-I/opt/android-ndk-r10e/sources/cxx-stl/stlport/stlport/ -c camellia.cpp 
In file included from seckey.h:9:0, 
      from camellia.h:9, 
      from camellia.cpp:14: 
misc.h: In function 'T CryptoPP::rotlFixed(T, unsigned int) [with T = unsigned int]': 
misc.h:1121:71: error: matching constraint not valid in output operand 
    __asm__ ("rol %2, %0, %1" : "=g2" (z) : "g0" (x), "M1" ((int)(y%32))); 
                    ^
misc.h:1121:71: error: matching constraint references invalid operand number 
misc.h: In function 'T CryptoPP::rotrFixed(T, unsigned int) [with T = unsigned int]': 
misc.h:1129:71: error: matching constraint not valid in output operand 
    __asm__ ("ror %2, %0, %1" : "=g2" (z) : "g0" (x), "M1" ((int)(y%32))); 
                    ^
misc.h:1129:71: error: matching constraint references invalid operand number 
misc.h: In function 'T CryptoPP::rotlVariable(T, unsigned int) [with T = unsigned int]': 
misc.h:1137:72: error: matching constraint not valid in output operand 
    __asm__ ("rol %2, %0, %1" : "=g2" (z) : "g0" (x), "g1" ((int)(y%32))); 
                     ^
misc.h:1137:72: error: matching constraint references invalid operand number 
misc.h: In function 'T CryptoPP::rotrVariable(T, unsigned int) [with T = unsigned int]': 
misc.h:1145:72: error: matching constraint not valid in output operand 
    __asm__ ("ror %2, %0, %1" : "=g2" (z) : "g0" (x), "g1" ((int)(y%32))); 
                     ^
misc.h:1145:72: error: matching constraint references invalid operand number 
misc.h: In function 'T CryptoPP::rotrFixed(T, unsigned int) [with T = unsigned int]': 
misc.h:1129:71: error: matching constraint not valid in output operand 
    __asm__ ("ror %2, %0, %1" : "=g2" (z) : "g0" (x), "M1" ((int)(y%32))); 
                    ^
misc.h:1129:71: error: invalid lvalue in asm output 0 
misc.h:1129:71: error: matching constraint references invalid operand number 
misc.h: In function 'T CryptoPP::rotlFixed(T, unsigned int) [with T = unsigned int]': 
misc.h:1121:71: error: matching constraint not valid in output operand 
    __asm__ ("rol %2, %0, %1" : "=g2" (z) : "g0" (x), "M1" ((int)(y%32))); 
                    ^
misc.h:1121:71: error: invalid lvalue in asm output 0 
misc.h:1121:71: error: matching constraint references invalid operand number 

// ROL #n Rotate left immediate 
template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y) 
{ 
    int z; 
    __asm__ ("rol %2, %0, %1" : "=g2" (z) : "g0" (x), "M1" ((int)(y%32))); 
    return static_cast<word32>(z); 
} 

// ROR #n Rotate right immediate 
template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y) 
{ 
    int z; 
    __asm__ ("ror %2, %0, %1" : "=g2" (z) : "g0" (x), "M1" ((int)(y%32))); 
    return static_cast<word32>(z); 
} 

// ROR rn Rotate left by a register 
template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y) 
{ 
    int z; 
    __asm__ ("rol %2, %0, %1" : "=g2" (z) : "g0" (x), "g1" ((int)(y%32))); 
    return static_cast<word32>(z); 
} 

// ROR rn Rotate right by a register 
template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y) 
{ 
    int z; 
    __asm__ ("ror %2, %0, %1" : "=g2" (z) : "g0" (x), "g1" ((int)(y%32))); 
    return static_cast<word32>(z); 
} 

template<> inline word32 rotlMod<word32>(word32 x, unsigned int y) 
{ 
    return rotlVariable<word32>(x, y); 
} 

template<> inline word32 rotrMod<word32>(word32 x, unsigned int y) 
{ 
    return rotrVariable<word32>(x, y); 
} 
+0

什么你想达到与'g2'和'M1'? '2'和'1'是匹配的约束,似乎没有道理,编译器也不喜欢它们。 – Jester

+0

@Jester - '2'是输出操作数的数字。它需要在一个寄存器中,因此'g2'。对于'1',这是'rhs'或'shift amount'。立即,它需要被限制到即时值,因此'M1'。 – jww

+0

请注意,GCC非常聪明,可以提取'x << y | x >>(32-y)'成语并发出单个'ror'指令,前提是参数是无符号的。 – Notlikethat

回答

1

首先,ARM没有(ROL)向左旋转,需要模拟通过ROR

其次,由于某种原因,M约束接受0到32,但ROL只在处理立即数时才接受0到31。

第三,g约束过于笼统,因为它也允许ROR不接受的内存操作数。改用r代替。

这是我想出了:

// Rotate right 
inline word32 rotr(word32 x, unsigned int y) 
{ 
    int z; 
    if (__builtin_constant_p(y)) 
    { 
     y &= 31; 
     if (y != 0) // this should be optimized away by the compiler 
     { 
      __asm__ ("ror %0, %1, %2" : "=r" (z) : "r" (x), "M" (y)); 
     } 
    } else { 
     __asm__ ("ror %0, %1, %2" : "=r" (z) : "r" (x), "r" (y)); 
    } 
    return static_cast<word32>(z); 
} 

// Rotate left 
inline word32 rotl(word32 x, unsigned int y) 
{ 
    int z; 
    if (__builtin_constant_p(y)) 
    { 
     y &= 31; 
     if (y != 0) // this should be optimized away by the compiler 
     { 
      __asm__ ("ror %0, %1, %2" : "=r" (z) : "r" (x), "M" (32 - y)); 
     } 
    } else { 
     __asm__ ("ror %0, %1, %2" : "=r" (z) : "r" (x), "r" (32 - y)); 
    } 
    return static_cast<word32>(z); 
} 
+0

*“其次,M约束...” - 是的,我真的想要***我简单的约束,但我无法让它工作。 – jww