ぐだぐだ低レベルプログラミング(120)ARM64(AArach64)Floatのストア#1

Joseph Halfmoon

ロードあればストアあり。前回前々回と浮動小数とSIMD(スカラー)のロード命令(LDR)を練習してみました。今回は対になるストア命令(STR)の練習です。ほぼ同様なアドレシングモードが使用できますが、唯一PC相対だけはありません。PC相対で指定できるのは”.TEXT”セグメントと解釈されるのでストアは対象外っと。

※「ぐだぐだ低レベルプログラミング」投稿順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

ARMv8もいろいろレベルがあり、Arm Cortex-A72はARMv8の中でもベーシックな(命令数の少ない)ARMv8p0です。

※A64の最新のマニュアルは以下でダウンロード可能です。

Arm Architecture Reference Manual for A-profile architecture

STR命令

前回、前々回と練習したLDR命令と対になるストア命令はSTRというニーモニックです。整数型のロード、ストアとニーモニック共通なので、ロード、ストアの対象になるレジスタ指定で整数なのか浮動小数(SIMDスカラ)か判定することになります。

LDRとSTRは「代表的な」ロード/ストア命令ですが、他にもいろいろあるのは以前にやったとおりです。RISCといいつつ命令多すぎA64です。今回は、前回、前々回と練習したLDRのほぼほぼ同じアドレシングのSTRを見ていきたいと思います。SIMDスカラまでいれるとストアできるビット幅はいろいろなのですが、例によってFloat(単精度浮動小数)だけにしてます。手抜き。

今回実験のアセンブリ言語関数

「いつものように手抜きな」関数プロローグもエピローグもない被テスト関数ですが、いつもと違って実質2命令です。ストアするからにはストアするデータがレジスタに載っていないとならないのですが、今回は引数でデータを与えるのでなく、唯一STRでおよびがかからないPC相対アドレシングで .TEXT セグメント中の定数をロードしたものをストアするようにしてます。

.globl	fstrSImmPost, fstrSImmPre, fstrSImmU, fstrSRegLSL0, fstrSRegLSL2, fstrSRegUXTW0, fstrSRegUXTW2 
.text
.balign	4

fstrSImmPost:
    ldr s0, dlabel1
    str s0, [x0], #4
    ret

fstrSImmPre:
    ldr s0, dlabel2
    str s0, [x0, #4]!
    ret

fstrSImmU:
    ldr s0, dlabel3
    str s0, [x0, #8]
    ret

fstrSRegLSL0:
    ldr s0, dlabel4
    str s0, [x0, x1]
    ret

fstrSRegLSL2:
    ldr s0, dlabel5
    str s0, [x0, x1, LSL #2]
    ret

fstrSRegUXTW0:
    ldr s0, dlabel6
    str s0, [x0, w1, UXTW]
    ret

fstrSRegUXTW2:
    ldr s0, dlabel7
    str s0, [x0, w1, UXTW #2]
    ret

.balign 4
dlabel1:
    .single 1.2345e3
dlabel2:
    .single 2.2345e3
dlabel3:
    .single 3.2345e3
dlabel4:
    .single 4.2345e3
dlabel5:
    .single 5.2345e3
dlabel6:
    .single 6.2345e3
dlabel7:
    .single 7.2345e3
C言語記述のmain関数

「通り一遍さわるだけの手抜きな」C言語記述のテスト駆動部です。被テスト関数は格納先のアドレスへのポインタ、およびインデックスを受け入れ、Float型の定数を所定メモリにストアします。ストア先としては配列を用意しておきます。Pre、Postインデックスアドレシングをテストする場合には、更新後のポインタを戻り値として受け取ります。他のケースでは処理結果は配列に入っているハズなので戻り値はvoidです。

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

extern uint64_t    fstrSImmPost(float *);
extern uint64_t    fstrSImmPre(float *);
extern void        fstrSImmU(float *);
extern void        fstrSRegLSL0(float *, uint64_t);
extern void        fstrSRegLSL2(float *, uint64_t);
extern void        fstrSRegUXTW0(float *, uint32_t);
extern void        fstrSRegUXTW2(float *, uint32_t);

#define MAXMEM	(10)
float TargetMEM[MAXMEM];

void initTGT() {
    for (int i=0; i < MAXMEM; i++) {
        TargetMEM[i] = 0.0f;
    }
}

int main(void) {
    uint64_t resultA;
    initTGT();

    printf ("TargetMEM-A   : 0x%lx\n", TargetMEM);

    resultA =fstrSImmPost(TargetMEM);
    printf ("fstrSImmPost-A: 0x%lx\n", resultA);
    resultA =fstrSImmPre(TargetMEM);
    printf ("fstrSImmPre-A : 0x%lx\n", resultA);
    fstrSImmU(TargetMEM);
    fstrSRegLSL0(TargetMEM, 12);
    fstrSRegLSL2(TargetMEM, 4);
    fstrSRegUXTW0(TargetMEM, 20);
    fstrSRegUXTW2(TargetMEM, 6);

    for (int i=0; i < MAXMEM; i++) {
        printf("%d : %e \n", i, TargetMEM[i]);
    }

    return 0;
}
ビルドして実行

ビルドして実行した結果が以下に。fstrResults

ちゃんと期待通りの結果がメモリに格納されたようです。目出度し目出度し。といってまだロード、ストア続くんじゃが。ほんと命令多いなA64。

ぐだぐだ低レベルプログラミング(120)ARM64(AArach64)Floatのロード#2 へ戻る

ぐだぐだ低レベルプログラミング(121)ARM64(AArach64)LDUR/STUR へ進む