ぐだぐだ低レベルプログラミング(114)ARM64(AArach64)FABS他

Joseph Halfmoon

今回はFABS「他」などと省略してしまいましたが、残りはFNEGとFSQRTです。絶対値(FABS)に符号反転(FNEG)そして平方根(FSQRT)です。いずれもソース一つをとって結果ひとつをデスティネーションに返すもの。例によってARMv8.0に半精度はないので、単精度と倍精度のみ。お楽?

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

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

くどくどと説明も不要な命令3種であるので、「いつものように手抜きな」関数プロローグもエピローグもない1命令1関数スタイルの被テスト関数を掲げておきます。前回などメンドイので単精度のみにしてましたが、今回は単精度のみだとあまりに手抜きが目立つので倍精度も入れてみました。ご都合主義ね。

.globl    fabsS, fnegS, fsqrtS, fabsD, fnegD, fsqrtD
.text
.balign    4

fabsS:
    fabs s0, s1
    ret

fnegS:
    fneg s0, s1
    ret

fsqrtS:
    fsqrt s0, s1
    ret

fabsD:
    fabs d0, d1
    ret

fnegD:
    fneg d0, d1
    ret

fsqrtD:
    fsqrt d0, d1
    ret
C言語記述のmain関数

いつもの通り「これまた手抜きな」C言語記述のテスト駆動部が以下に。平方根が取れないような値を渡したらどうなるのよ(当然例外発生)とかコマケー話をやり始めるとメンドイので今回は(今回も)見て見ぬふりっす。各命令1回だけさわってみるだけ。

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

extern float fabsS(float, float);
extern float fnegS(float, float);
extern float fsqrtS(float, float);
extern double fabsD(double, double);
extern double fnegD(double, double);
extern double fsqrtD(double, double);

int main(void)
{
    union {
        float s;
        uint32_t u;
    } f32;

    union {
        double d;
        uint64_t u;
    } f64;

    f32.s = fabsS(0.0f, -1.234567f);
    f64.d = fabsD(0.0,  -1.234567890123);
    printf ("fabsS =%2.12f(0x%08x)\n", f32.s, f32.u);
    printf ("fabsD =%2.12f(0x%016lx)\n", f64.d, f64.u);

    f32.s = fnegS(0.0f, 1.234567f);
    f64.d = fnegD(0.0,  1.234567890123);
    printf ("fnegS =%2.12f(0x%08x)\n", f32.s, f32.u);
    printf ("fnegD =%2.12f(0x%016lx)\n", f64.d, f64.u);

    f32.s = fsqrtS(0.0f, 2.0f);
    f64.d = fsqrtD(0.0,  2.0);
    printf ("fabsS =%2.12f(0x%08x)\n", f32.s, f32.u);
    printf ("fabsD =%2.12f(0x%016lx)\n", f64.d, f64.u);

    return 0;
}

小数点以下12桁と無駄に長い表示をしているのは、単精度浮動小数の「馬脚」を現すための意地悪です。倍精度なら予定どおり表示ができるのに、との差別化を予定。16進数表記も併記しているので詳しい内部表現を追求することも可(やらんけど。。。)

実行結果

ビルドして実行したものが以下に。FABSresults

予定どおりですな。ルート2は「ひとよひとよにひとみごろ~」と。単精度だと最後の「ろ~」のところまで行きつかないじゃん!

ちなみにということでいうと、以下の別シリーズ記事で2の平方根を「とりあえず」1000桁もとめてみてます。MPFRライブラリ使えば何桁でも思うがままだと。

ソフトな忘却力(27) MPFR、the Multiple Precision Floating-Point Reliable Library

1000桁みると目がちかちかしてきたですが。白内障?医者へ行けよ。

ぐだぐだ低レベルプログラミング(113)ARM64(AArach64)積和演算4種の違い へ戻る

ぐだぐだ低レベルプログラミング(115)ARM64(AArach64)FMAX, FMIN へ進む