ぐだぐだ低レベルプログラミング(45) RISC-V、浮動小数点の丸めと例外

Joseph Halfmoon

RISC-Vの浮動小数点演算命令セットを実際に動かして堪能しようと思いつつ、ついつい後回しにしてきました。何でかといって難物の「丸め」と「例外」などがチラチラしていたからでございます。浮動小数点素人の私としては触りたくない「奴ら」ですが、これに触れないことには先に進みませぬ。

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

さて今回参照させていただいております文献は、以下のRISC-V International様のページの

RISC-V Specifications

以下のタイトルのついたドキュメントでございます。約2年ほど前のもの。

The RISC-V Instruction Set Manual
Volume I: Unprivileged ISA
Document Version 20191213

それ読んでくだされ、でさっさと実習へ行ければ良いのですが、私自身も覚えていないので(覚えたくない?)今回は自分で自分に分かるように図や表にまとめながら学んでまいりたいと思います(直ぐに忘れるケド。)

浮動小数点命令用にはステータスレジスタがあるのだ

最初にRISC-Vの整数基本命令セットを見た時にちょっと驚いたのは、条件判断に使うフラグなどを納めた「ステータス・レジスタ」(例えばx86における、Flagsレジスタ)が存在しない、ということでありました。RISC-Vの基本命令セットを見ると、条件フラグなんて無くてもなんとかなる、ということが分かって目から鱗、と思っとりました。しかしです。浮動小数点を扱う命令セット拡張を見れば

fcsr : Floating-point Control and Status register

なるものがあーるじゃありませんか。 私の感動を返せ、と言う気はありませねぬ。それだけ浮動小数点の処理がメンドイということでしょう。以下にfcsrレジスタを描いてみました。

fcsr
32ビットのうち、上位の24ビットは現状予約ビットで使われておらず、使われているのは下の8ビットだけです。機能的には以下の2つに分かれます。

  • 図の緑の部分、frm、Rounding Mode
  • 図の水色の部分、fflags、Accrued Exceptions

「丸めの制御」と「例外のステータス」であります。

丸め(Rounding)

丸めというと、小学校で習った「四捨五入」に頼り切りの私ですが、IEEE浮動小数点規格をご存じの方ならば「四捨五入」などバッサリでしょう。しかし、RISC-Vの場合、「IEEE丸め」に進む前に以下の選択があるのです。

  • Dynamic rounding mode
  • Static rounding mode

冒頭のアイキャッチ画像に、この選択のフローを描いてしまいました。恐ろしいことに、RISC-Vの「丸め」が必要になる浮動小数点演算命令には、rmと略記される3ビットのフィールドがあるのです。そして演算対象のレジスタを指定するオペランドの末尾に、rne とか、なんだか分からぬニーモニックを追加することができるのです。つまり、

  • 命令オペランドとして丸めモードを記載すれば、その命令はStatic rounding mode として指定のモードで丸め処理をする(図のピンク)
  • 明示的にDynamic rounding modeを指定するか、省略すれば、Dynamic rounding modeとなり、fcsrレジスタのfrmフィールドで指定されるモードで丸められる(図の緑)

命令の丸めまで全て制御したい(そうすれば常に同じ結果が得られる筈)か、場合によってオブジェクトコードを再コンパイルしないでも切り替えられるかは、計算する人のお好み、ということですな。四捨五入で満足している私などは出る幕の無い世界の話であります。

さて、実際の丸めモードはというと以下の5つが用意されています。

frm/rm Mnemonic 意味
000 RNE 偶数への最近接丸め
001 RTZ 0方向への丸め
010 RDN 負の無限大方向への丸め
011 RUP 正の無限大方向への丸め
100 RMM Max Magnitudeへの最近接丸め

最初の「偶数への」というのは、2進数で計算しているので、仮数の最後の桁が0ということだと思います。「最近接」であるので、所定のフォーマット内で表現しきれない下のビットをみて、「近い」方の表現可能な数にする。ただし、ちょうど半分、真ん中、の場合は最下位ビットが0である表現の方を選択する、ということなのだと思います(ホントか?)

0方向丸め、正負の無限大方向丸めは、一定方向への丸め(というか切り捨て、切り上げ的な)なので、分かったような気になります。しかし、最後のRMMは何でしょうか。最近接で、真ん中のときは、大きい方にするってこと?Max Magnitudeというのは絶対値なの、符号ありなの?「浮動小数点業界の常識」がない私にはよく分かりません。これはまた調べないとダメだな。

本日は例外まで行き着けませんでした。トホホ。

ぐだぐだ低レベルプログラミング(44) 64bit RISC-V、サイクル数と命令数の計測 へ戻る

ぐだぐだ低レベルプログラミング(46) RISC-V、浮動小数点の丸めと例外、その2 へ進む