RISC-V 編譯匯編代碼疑問

Hi All.

? ?我這邊使用一些簡(jiǎn)單的代碼驗(yàn)證MounRiver將C語(yǔ)言編譯成匯編的時(shí)候,發(fā)現(xiàn)編譯器在處理字節(jié)和半字加載的時(shí)候經(jīng)常還需要添加左移和右移命令,按照RISCV的spec描述支持lh和hu,lb和lbu指令,應(yīng)該是直接一條指令就能實(shí)現(xiàn)加載和擴(kuò)展,實(shí)際應(yīng)用中編譯中無(wú)論是否是有無(wú)符號(hào)數(shù)加載都采用無(wú)符號(hào)加載然后再左移右移處理(參考下面問題1和問題2),明顯效率比較低,請(qǐng)問是否有配置可以改善,以及為什么編譯器默認(rèn)會(huì)采用這些比較復(fù)雜的匯編?配置不同優(yōu)化等級(jí)結(jié)果還是一樣。謝謝!

測(cè)試代碼:

typedef struct

{

? ? __IO uint16_t? ?Data_U16;

? ? __IO int16_t? ? Data_S16;

? ? __IO uint8_t? ? Data_U8;

? ? __IO int8_t? ? ?Data_S8;

} REG_TypeDef;


#define MCU_REG_BASE? ? (0x10000000)

#define MCU_REG? ? ? ? ?((REG_TypeDef *) MCU_REG_BASE)


volatile uint32_t DataLoad_U32;

volatile int32_t? DataLoad_S32;


int main(void)

{

? ? DataLoad_U32 = MCU_REG->Data_U16;

? ? DataLoad_U32 = MCU_REG->Data_U8;

? ? DataLoad_U32 = MCU_REG->Data_S16;

? ? DataLoad_U32 = MCU_REG->Data_S8;


? ? DataLoad_S32 = MCU_REG->Data_U16;

? ? DataLoad_S32 = MCU_REG->Data_U8;

? ? DataLoad_S32 = MCU_REG->Data_S16;

? ? DataLoad_S32 = MCU_REG->Data_S8;

}

編譯結(jié)果


int main(void)

{

? ? DataLoad_U32 = MCU_REG->Data_U16;

? 18:100007b7? ? ? ? ? luia5,0x10000

? 1c:2396? ? ? ? ? ? ? ? lhua3,0(a5)

? 1e:20000737? ? ? ? ? luia4,0x20000

? 22:00470713? ? ? ? ? addia4,a4,4 # 20000004

? 26:06c2? ? ? ? ? ? ? ? sllia3,a3,0x10

? 28:82c1? ? ? ? ? ? ? ? srlia3,a3,0x10

? 2a:c314? ? ? ? ? ? ? ? swa3,0(a4)

? ? DataLoad_U32 = MCU_REG->Data_U8;

? 2c:23d4? ? ? ? ? ? ? ? lbua3,4(a5)

? ? DataLoad_S32 = MCU_REG->Data_U8;

? ? DataLoad_S32 = MCU_REG->Data_S16;

? ? DataLoad_S32 = MCU_REG->Data_S8;



}

? 2e:4501? ? ? ? ? ? ? ? lia0,0

? ? DataLoad_U32 = MCU_REG->Data_U8;

? 30:0ff6f693? ? ? ? ? andia3,a3,255

? 34:c314? ? ? ? ? ? ? ? swa3,0(a4)

? ? DataLoad_U32 = MCU_REG->Data_S16;

? 36:23b6? ? ? ? ? ? ? ? lhua3,2(a5)

? 38:06c2? ? ? ? ? ? ? ? sllia3,a3,0x10

? 3a:86c1? ? ? ? ? ? ? ? sraia3,a3,0x10

? 3c:c314? ? ? ? ? ? ? ? swa3,0(a4)

? ? DataLoad_U32 = MCU_REG->Data_S8;

? 3e:33d4? ? ? ? ? ? ? ? lbua3,5(a5)

? 40:06e2? ? ? ? ? ? ? ? sllia3,a3,0x18

? 42:86e1? ? ? ? ? ? ? ? sraia3,a3,0x18

? 44:c314? ? ? ? ? ? ? ? swa3,0(a4)

? ? DataLoad_S32 = MCU_REG->Data_U16;

? 46:2396? ? ? ? ? ? ? ? lhua3,0(a5)

? 48:20000737? ? ? ? ? luia4,0x20000

? 4c:00070713? ? ? ? ? mva4,a4

? 50:06c2? ? ? ? ? ? ? ? sllia3,a3,0x10 #疑問點(diǎn)1,前面采用lhu,16位無(wú)符號(hào)數(shù)會(huì)自動(dòng)擴(kuò)展為32位,應(yīng)該不需要左右移

? 52:82c1? ? ? ? ? ? ? ? srlia3,a3,0x10

? 54:c314? ? ? ? ? ? ? ? swa3,0(a4)

? ? DataLoad_S32 = MCU_REG->Data_U8;

? 56:23d4? ? ? ? ? ? ? ? lbua3,4(a5)

? 58:0ff6f693? ? ? ? ? andia3,a3,255

? 5c:c314? ? ? ? ? ? ? ? swa3,0(a4)

? ? DataLoad_S32 = MCU_REG->Data_S16;

? 5e:23b6? ? ? ? ? ? ? ? lhua3,2(a5)? #疑問點(diǎn)2,這里應(yīng)采用lh而不是lhu

? 60:06c2? ? ? ? ? ? ? ? sllia3,a3,0x10

? 62:86c1? ? ? ? ? ? ? ? sraia3,a3,0x10

? 64:c314? ? ? ? ? ? ? ? swa3,0(a4)

? ? DataLoad_S32 = MCU_REG->Data_S8;

? 66:33dc? ? ? ? ? ? ? ? lbua5,5(a5)

? 68:07e2? ? ? ? ? ? ? ? sllia5,a5,0x18

? 6a:87e1? ? ? ? ? ? ? ? sraia5,a5,0x18

? 6c:c31c? ? ? ? ? ? ? ? swa5,0(a4)

}


image.png

您好,關(guān)于第一點(diǎn),volatile關(guān)鍵字防止優(yōu)化,所以左右移沒有被優(yōu)化,第二點(diǎn),GCC目前在內(nèi)存操作時(shí)為了性能不會(huì)用LH。

image.png


1. volatile 關(guān)鍵字會(huì)影響加載這點(diǎn)比較奇怪,因?yàn)閘u指令16位無(wú)符號(hào)數(shù)會(huì)自動(dòng)擴(kuò)展為32位,這里不涉及和其他數(shù)值交互,沒太明白為什么還要左右移。 2. 用了lh的話指令數(shù)會(huì)更少,應(yīng)該更有利于性能。GCC在內(nèi)存操作為了性能不用LH是說(shuō)為了提高編譯速度還是?


沒錯(cuò),左右移的目的并不是什么源代碼級(jí)別的優(yōu)化(也就是volatile)與否,而是在將字節(jié)/半字?jǐn)U展成字。

因此,這里的問題不僅僅是有符號(hào)擴(kuò)展為什么不用現(xiàn)成指令,還包括無(wú)符號(hào)擴(kuò)展為什么還要 AND 0xFF(andi a3,a3,255)?


不但沁恒專用的GCC這樣,xPack的最新版(GCC: (xPack GNU RISC-V Embedded GCC x86_64) 13.2.0)也一樣。


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97417


應(yīng)該就是同一個(gè)道理吧?難道還沒解決嗎……


只有登錄才能回復(fù),可以選擇微信賬號(hào)登錄

国产91精品新入口,国产成人综合网在线播放,九热这里只有精品,本道在线观看,美女视频a美女视频,韩国美女激情视频,日本美女pvp视频