softfloatは、浮動小数点をソフトウェアで実現するためのライブラリだ。
今までは整数命令ばかり実装していたけど、MIPS64やRISC-Vも注目を浴びてきたということもあり、浮動小数点の命令も実装していこう。 そのためには、x86の命令を使って実装するのもいいけれど、より制御にしやすいsoftfloatを使っていこう。
softfloatはどのような仕組みになっているのか
浮動小数点の型定義
例えば、単精度浮動小数点の加算のための関数は以下のように実装されている。
- f32_add.c
float32_t f32_add( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; bool signA;
softfloatの浮動小数点の型定義
ここで、float32_tは以下のように定義されている。
typedef struct { uint32_t v; } float32_t; typedef struct { uint64_t v; } float64_t; typedef struct { uint64_t v[2]; } float128_t;
基本的に整数型の構造体になっており、これをf32_add内で分解して加算を実行するようになっている。
つまり、ISSでf32_addを呼び出す前に、型を変換する必要があるわけだ。
softfloatを用いた浮動小数点命令の実装
void InstEnv::MIPS64_INST_ADD_S (Word_t inst_hex)
{
...
Word_t rs1_val = m_env->ReadFReg<Word_t> (rs1_addr);
Word_t rs2_val = m_env->ReadFReg<Word_t> (rs2_addr);
Word_t res = InstOps::FloatAdd (rs1_val, rs2_val);
m_env->WriteFReg<Word_t> (rd_addr, res);
}
ReadFRegにより浮動小数点レジスタから値を読み出し、FloatAdd()関数を介して浮動小数点加算を実行する。その結果をWriteFRegに返す。 このために、FloatAdd()関数は以下のように実装されている。
Word_t InstOps::FloatAdd (Word_t op1, Word_t op2)
{
float32_t f_op1, f_op2;
f_op1.v = op1;
f_op2.v = op2;
float32_t f_res = f32_add(f_op1, f_op2);
Word_t res = f_res.v;
return res;
}
一旦f_op1, f_op2という型に載せ変え、f32_add()を呼び出した上で再度Word_t(=整数型)に変換して戻す。 これにより、浮動小数点の命令をsoftfloatで実現できるようになる訳だ。
softfloatライブラリの構築
softfloatの関数群をコンパイルし、ライブラリを作成しよう。
下記のようなCMakeLists.txtを作成して、ライブラリを生成した。
add_library (softfloat ../SoftFloat-3a/source/extF80_add.c ../SoftFloat-3a/source/extF80_div.c ../SoftFloat-3a/source/extF80_eq.c ... )
$ cmake . -- Configuring done -- Generating done -- Build files have been written to: /home/vagrant/swimmer_iss/vendor/softfloat/build $ make [ 0%] Building C object CMakeFiles/softfloat.dir/home/vagrant/swimmer_iss/vendor/softfloat/SoftFloat-3a/source/extF80_add.c.o [ 0%] Building C object CMakeFiles/softfloat.dir/home/vagrant/swimmer_iss/vendor/softfloat/SoftFloat-3a/source/extF80_div.c.o ... [ 99%] Building C object CMakeFiles/softfloat.dir/home/vagrant/swimmer_iss/vendor/softfloat/SoftFloat-3a/source/8086-SSE/s_propagateNaNF32UI.c.o [ 99%] Building C object CMakeFiles/softfloat.dir/home/vagrant/swimmer_iss/vendor/softfloat/SoftFloat-3a/source/8086-SSE/s_propagateNaNF64UI.c.o [100%] Linking C static library libsoftfloat.a [100%] Built target softfloat $ ls -1 CMakeCache.txt CMakeFiles cmake_install.cmake CMakeLists.txt cpp_source libsoftfloat.a Makefile platform.h
ISSへのsoftfloatへの埋め込み
libsoftfloat.aが作成された。これをISSのリンク時に接続すれば良い。
add_library (core_mips64 ../src/mips64_env.cpp ../src/env.cpp ../src/trace.cpp ../src/inst_print.cpp ../src/inst_mnemonic.cpp ... ) target_link_libraries (core_mips64 softfloat)