2015-07-20 181 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