ぐだぐだ低レベルプログラミング(77)ARM64(AArch64)、EXTR、RORでもある

Joseph Halfmoon

前回までのビットフィールド転送命令群と比べて今回のレジスタ抽出命令EXTRの動作は分かり易いです。エイリアスもシンプル、たった1個。ROR(右ローテイト)命令だけです。ただ、左にシフトして取り出すような操作のEXTRに対して、詰まっているデータから見ると右ローテイトに見えると。左右が時々混乱するのは私だけ?

※「ぐだぐだ低レベルプログラミング」投稿順indexはこちら

※以下は下記にて動作確認しています。

    • Raspberry Pi 4 model B、Cortex-A72コア ARMv8-A
    • Raspberry Pi OS (64bit) bullseye
    • gcc (Debian 10.2.1-6) 10.2.1 20210110
EXTR命令

EXTR命令は2つのレジスタを接続して、そこから1レジスタ分のデータを抽出する命令です。何に使うのと思われる方もいらっしゃるかもしれませんが、結構重宝する命令です。個人的にこの手の命令、私は好んで使っております。

接続する2つのレジスタをソース1(n)とソース2(m)として、デスティネーション(d)に取り出します。取り出し位置は取り出すデータのlsb位置を即値で指定します。EXTR

上記では、ソースに異なる2つのレジスタを取っていますが、同一のレジスタをソース1とソース2に指定すると、EXTRのエイリアスである ROR (右ローテイト)命令となります。先ほども書きましたがデータからみると右です。左ローテイト命令が無いですが、シフト量を調整すれば右ローテイトは左ローテイトにもなります。右に行き過ぎれば左になると。

実験用アセンブリ言語ソース

例によって1命令=1被テスト関数のスタイルですが、エイリアスであるROR命令については、ROR命令と同一の機械語に落ちるEXTR命令を先に置いて比べられるようにしてあります。

.globl	extrW, extrX, rorW, rorX
.text
.balign	4

extrW:
    extr	w0, w1, w2, #4
    ret

extrX:
    extr	x0, x1, x2, #4
    ret

rorW:
    extr	w0, w1, w1, #4
    ror		w0, w1, #4
    ret

rorX:
    extr	x0, x1, x1, #4
    ror		x0, x1, #4
    ret

上記でEXTR命令とROR命令が、同じ機械語に落ちている様子をディスアセンブルリストで見たものが以下に。disasm

 

アセンブル関数を呼び出してテストするCのコード

「とりあえず各関数1例だけ」触ってみるコードが以下に。

#include <stdio.h>
#include <stdint.h>

extern uint32_t extrW(uint32_t, uint32_t, uint32_t);
extern uint64_t extrX(uint64_t, uint64_t, uint64_t);
extern uint32_t rorW(uint32_t, uint32_t);
extern uint64_t rorX(uint64_t, uint64_t);

int main(void)
{
    uint32_t result;
    uint64_t resultX;

    result = extrW(0, 0x12345678, 0x9ABCDEF0);
    printf ("extrW: %08x\n", result);
    resultX = extrX(0, 0xA5A5A5A5A5A5A5A5, 0x0123456789ABCDEF);
    printf ("extrX %lx\n", resultX);

    result = rorW(0, 0x87654321);
    printf ("rorW: %08x\n", result);
    resultX = rorX(0, 0x87654321A5A5A5A5);
    printf ("rorX: %lx\n", resultX);

    return 0;
}
ビルドして実行

ビルドは以下のコマンドラインで。

gcc -g -O0 -o extr extr.c extr.s

実行結果は以下のようです。

Result

意図通りに抽出、あるいは右ローテイトされとります。左右こんがらがらなくてよかった。

ぐだぐだ低レベルプログラミング(76)ARM64(AArch64)、UBFM命令、伸縮自在 へ戻る

ぐだぐだ低レベルプログラミング(78)ARM64(AArch64)、シフト、ローテイトの片割 へ進む