inline uint32_t REV(uint32_t din) {
uint32_t dout;
__asm__("REV
%[Rd], %[Rs1]" : [Rd] "=r"
(dout) : [Rs1] "r" (din));
return(dout);
}
inline uint32_t RBIT(uint32_t din) {
uint32_t dout;
__asm__("RBIT
%[Rd], %[Rs1]" : [Rd] "=r"
(dout) : [Rs1] "r" (din));
return(dout);
}
RBITがビットリバーサルです
RBIT命令は32bitのI/Oなので、8bitの入れ替えをしようと思うと予期しない結果になります
解決手段としては
1) ビットシフトで移動する
2) エンディアン変換で移動する
3) ポインタで正常な位置から読み出す
(もしくは最初にポインタでオフセットした位置に書き込む)
という方法があります
1と3については説明は不要だと思います
2のエンディアン変換はREV関数で行います
これも32bitI/Oです
動作確認については
uint32_t data = 0x12345678;
uint8_t *p = (uint8_t*)&data;
xprintf("%02X
%02X %02X %02X\n", p[0], p[1], p[2], p[3]);
data = REV(data);
xprintf("%02X
%02X %02X %02X\n", p[0], p[1], p[2], p[3]);
data = RBIT(data);
xprintf("%02X
%02X %02X %02X\n", p[0], p[1], p[2], p[3]);
という感じ1回目のprintfでは78 56 34 12が出てきます
2回目はエンディアンを入れ替えた12 34 56 78が出てきます
3回目はビットリバーサルした結果の1E 6A 2C 48が出てきます
8bit変数のビットリバーサルを行いたい場合は
REV(RBIT(
(uint8_t)hoge ))
という感じになりますREVとRBITはどちらが先でもいいはずです
でもビットリバーサルをやりたいだけならビットシフトのほうがらくだと思います
追記:2014-07-04
core_cm3.hに__RBIT及び__REV関数がありました
どちらも引数は32bitが1個 戻り値が32bit それぞれ符号無しです
やっていることはほぼ同じです
0 件のコメント:
コメントを投稿