前回までで「特権なし」で楽しく使える分岐命令はだいたい網羅したので、今回から「懸案」のSIMD命令、FP命令に入っていきたいと思います。新たなレジスタファイルが登場します。Vレジスタとな。まあ、X86_64ほど複雑怪奇ではないものの、それなりに込み入ってます。今回は冒頭の画像1枚描いて力尽きました。
※「ぐだぐだ低レベルプログラミング」投稿順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
SIMD & FP registers
前回まで長いこと整数型のレジスタファイルを扱う命令をエクササイズしてきました。Xnみたいなお名前の64ビットレジスタ(nは0から30)、Wnみたいなお名前の32ビットレジスタ(nは0から30)が31本(32本目は常にゼロのレジスタなので別勘定)を使うことができました。
アセンブラではもっぱら Xnとか、Wnとか記述してましたが、WnはXnの下半分で実体は同じレジスタです。そして物理的な実体レジスタ自体は、Rnみたいな呼び方されているのです(マニュアル上は。)
今回新たに登場するレジスタファイルのレジスタはVn(nは0から31、ゼロレジスタは無いのでフルに32本使えます)と呼ばれるようです。しかしこれは整数レジスタファイルがRnと呼ばれる類の「実体名称」であって、具体的なアセンブリ言語命令を記述する際には「データのビット幅」を反映した別なお名前が使用されます。今回はこれを頭に叩き込んでおこうと。よって実習はナシであります。
レジスタファイルの実体は128ビット幅でV0からV31までの32本存在します。このレジスタファイルを2系統の命令群が共用する、というところがまずはポイントです。
-
- FP(Floating Point) 命令
- SIMD(Single Instruction/Multiple Data)命令
FP命令
一度に一つのデータについて処理を行う浮動小数点命令群です。データのビット幅にかかわらず128ビット幅のVレジスタ1本を一つのデータについて割り当て、LSB側からデータを詰めこみます。データのビット幅により以下の5通りの呼ばれ方をすることになります。
-
- Bn、バイト(8ビット)
- Hn、半精度浮動小数(16ビット)
- Sn、単精度浮動小数(32ビット)
- Dn、倍精度浮動小数(64ビット)
- Qn、クワッドワード(128ビット)
しかし、実際の浮動小数点処理としては半精度、単精度、倍精度の3つが中心であるので、1と5は後のSIMD命令との関係で一応お名前を確保してある、といった程度なのかもしれませぬ(命令舐めていけばその真意が分かるかも知れませんが。)最初から半精度が確保されているところなどは、AIの流行にのったコンテンポラリな感じがします。
SIMD命令
1命令で複数個のデータについて処理を行うSIMD命令ですが、ここは後方互換性など考えたのかチョッチ複雑です。合計で128ビット幅でのSIMD処理と、合計で64ビット幅でのSIMD処理の2系統の処理命令が可能なためです。64ビット処理時には128ビット幅の下64ビット部分のみを使います。
たとえば単精度の浮動小数点数(32ビット幅)であると、128ビット幅処理では4個、64ビット幅処理では2個が同時に処理可能です。このため、アセンブラ書く時も、今は128ビット処理なのか、64ビット処理なのかを意識して指定しなければならず、同じV0レジスタに対する処理でも以下のようにかき分ける必要があるようです。
-
- V0.4S 128ビット幅での単精度データ4個の並列処理
- V0.2S 64ビット幅での単精度データ2個の並列処理
ベクトル命令については実装と命令を分離したRISC-Vスタイルの方がカッコええなあと思うのですが(個人の感想です。)まあ、ぶちぶちと物理レジスタ幅を意識せざるを得ない伝統的なSIMD命令の方が、アセンブラ書きするときには面白いというかテクを使う余地があるのかもです。知らんけど。
ま、次回からそろそろとエクササイズしていきますべい。