這個問題與ARM匯編語言有關。
我的問題是是否可以使用宏來替換 ASM 代碼中的立即值來移位暫存器值,這樣我就不必對數字進行硬編碼。
我不確定上面的問題是否有意義,所以我將提供一個帶有一些asm代碼的示例:
因此很少有指令,例如(https://developer.arm.com/documentation/dui0473/m/arm-and-thumb-instructions/ror)ror中的指令,其中可以使用暫存器值來旋轉我們希望的價值:ARM
#define rotate(number, ptr) ({ \
asm volatile( \
"ror %[output], %[output], %1\n" \
: [output]" r"(ptr) \ // this is the in/output
: "r"(number)); \ // this is the rotator
})
現在,讓我們來看看orr指令在ARM(https://developer.arm.com/documentation/dui0473/m/arm-and-thumb-instructions/orr)。
語法如下: ORR{S}{cond} Rd, Rn, Operand2
whereOperand2是一個靈活的運算元,這意味著它可以是一個constant或a register with optional shift(來源:https : //www.keil.com/support/man/docs/armasm/armasm_dom1361289851539.htm)
所以這樣的事情會起作用:
#define orr_test(ptr) ({ \
uint64_t __result; \
asm volatile (\
"orr %0, %1, #4 << 60\n"\
: "=r" (__result) : "r" (ptr)); \
__result; \
})
但是,我質疑是否可以用宏替換#4該行"orr %0, %0, #4 << 60\n"\中的內容,以便我不必硬編碼#4. 我認為這是不可能的(因為如果管理不當可能會導致大問題),但我仍然想問,因為我在網上找不到任何相關資訊。
如果我上面提到的任何內容不清楚,請告訴我;謝謝。
編輯(根據要求):
這基本上是我希望在偽代碼方面是可能的:
#define orr_test(ptr, number) ({ \
uint64_t __result; \
asm volatile (\
"orr %0, %1, %[num] << 60\n"\
: "=r" (__result) : "r" (ptr), [num]"r"(number)); \
__result; \
})
換句話說,#4我希望使用宏來確定要移動的數字,而不是使用 shift進行硬編碼。
uj5u.com熱心網友回復:
ARM64orr立即數指令采用位掩碼立即數,有關說明,請參閱ARMv8 A64 程式集中的立即數范圍。GCC對這種型別的運算元有一個約束:L.
所以我會寫:
#define MASK (4UL << 60)
inline uint64_t set_bit(uint64_t x) {
uint64_t result;
asm("orr %0, %1, %2"
: "=r" (result)
: "r" (x), "L" (MASK));
return result;
}
試試神馬
我做了一些其他修復/改進:
您同時使用
%0的目標運算元和第一個源運算元orr,這僅在編譯器幸運地為xand選擇了相同的暫存器時才有效result,而它不需要這樣做。您應該在x此處使用與輸入匹配的運算元%1。如果編譯器認為有利,它仍然可以自由地為兩者選擇相同的暫存器(在其他不合適的設定中,您可以使用&修飾符抑制它)。盡可能使用行內函式而不是宏。
請注意,如果您將 的值更改MASK為不可立即編碼為位掩碼的值,例如#define MASK (4UL << 60 | 1),您將收到編譯器錯誤。如果您希望它繼續作業,您可以將L約束更改為Lr。如果運算式MASK是一個編譯時常量,并且其值適合位掩碼立即數,編譯器將繼續發出立即數。如果沒有,它會發出額外的代碼來將值加載到暫存器中,然后orr用暫存器運算元發出。 試試看。
(當然,這個例子對于行內匯編來說是愚蠢的。GCC為 C 等價物生成了非常好的代碼return x | MASK;。但我認為它是一些更復雜代碼的例子。即便如此,你可以考慮是否|可以將操作分解,并且只是用作任何真正需要在 asm 中的輸入。像往常一樣,始終考慮不使用行內 asm是否可能適用。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/384827.html
