ぐだぐだ低レベルプログラミング(57) RISC-V、浮動小数点数のロード/ストア命令

Joseph Halfmoon

今回は珍しくメンドクない命令です。浮動小数のロード、ストアです。アドレスの指定は通常のロード、ストア同様に整数レジスタに12ビットのディスプレースメントを加える方式。これだけ。シンプル。RISCだもんね。

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

※以下は単精度浮動小数点命令について述べています。なお実機動作は、64bit RISC-V搭載、Kendryte K210上で行っています。

浮動小数のロードとストア命令

命令のエンコードとしてはどちらも3オペランドの命令です。

    • flw rd, offset(rs1)
    • fsw rs2, offset(rs1)

ロードもストアも12ビットのオフセットをとり、その値を符号拡張した上で、rs1で指定される整数レジスタ x[rs1] に格納されているメモリアドレスと加算してロード、ストアの対象となるメモリアドレスを得ます。

flwの場合は、そのアドレスから単精度浮動小数を読み出してrdで指定される浮動小数レジスタ f[rd] に格納します。

fswの場合は、rs2で指定される浮動小数レジスタ f[rs2] の内容を上記のアドレスに格納します。

被テスト関数のソース

ロードしただけでは結果が観察できないので、ロードしたらおとなりのメモリアドレスにストアすることにしました。被テスト関数も1個になってラクチン。いいのかそういうことで。

void tst_Flw_sw(uint32_t tnum, float arg1)
{
  TestFloat f0S;
  float work[8];
  float *adr;

  f0S.fDat = 0.0f;
  work[0] = 0.2345f;
  work[1] = arg1;
  work[2] = 2.4567f;
  work[3] = 3.4567f;
  adr = &work[1];
  asm volatile("fmv.w.x f0, %[Rd]\n\t"
               "flw f0, (%[Rs1])\n\t"
               "fsw f0, 4(%[Rs1])\n\t"
               "fmv.x.w %[Rd], f0\n\t"
              : [Rd] "=r" (f0S.u32Dat.LowW)
              : [Rs1] "r" (adr)
              : );
  Serial.printf("TEST-flw_fsw #%u\r\n", tnum);
  Serial.printf("%f <- flw 0(ADR)\r\n", f0S.fDat);
  Serial.printf("%f <- fsw 4(ADR)\r\n", work[2]);
  Serial.printf("  HEX: %08x\r\n", f0S.u32Dat.LowW);
  for(int i=0; i<4; i++) {
    Serial.printf("work[%d]: %f\r\n", i, work[i]);
  }
  Serial.printf("\r\n");
}
テストケース

テストケースもおざなり、わずか3ケースのみです。手抜き。

tst_Flw_sw(0, 1.3333f);
tst_Flw_sw(1, -1.3333f);
tst_Flw_sw(2, 2.5f);
実機動作結果

実機動作結果は、冒頭のアイキャッチ画像に貼り付けました。実機はRaspberry Pi 4機のUSBポートに刺してあるので、USBシリアルに垂れ流されてくる結果をminicomで見ているものです。

まあ予定通りに動いている感じ。いつもこんなに簡単だと良いけれど。実は知っています。浮動小数関係の命令の中でもメンドクセー奴らの一群がまだ隠れていることを。。。次回は気が重いな。

ぐだぐだ低レベルプログラミング(56) RISC-V、浮動小数点数のClassify命令 へ戻る

ぐだぐだ低レベルプログラミング(58) RISC-V、整数と浮動小数の変換命令 へ進む