MIPSの浮動小数点命令についても、大分実装が進んできたので、RISC-Vの実装を進めていこう。
RISC-Vにも単精度、倍精度の浮動小数点演算命令が定義されている。
RISC-Vの浮動小数点命令をISSに実装する
例えば32ビット単精度浮動小数点の加算命令は以下のように定義する。
void InstEnv::RISCV_INST_FADD_S (Word_t inst_hex)
{
RegAddr_t rs1_addr = ExtractR1Field (inst_hex);
RegAddr_t rs2_addr = ExtractR2Field (inst_hex);
RegAddr_t rd_addr = ExtractRDField (inst_hex);
Word_t rs1_val = m_env->ReadFReg<Word_t> (rs1_addr);
Word_t rs2_val = m_env->ReadFReg<Word_t> (rs2_addr);
UWord_t fflags;
Word_t res = InstOps::FloatAdd (rs1_val, rs2_val, &fflags);
m_env->WriteFReg<Word_t> (rd_addr, res);
m_env->CSRWrite (SYSREG_ADDR_FFLAGS, fflags);
}
CSRWrite()を使って、Softfloatの例外判定結果を書き込んでいる。このFloatAdd()関数は、softfloatを呼び出して浮動小数点演算を行い、例外結果をsoftfloat_exceptionFlagsという定数に返している。
Word_t InstOps::FloatAdd (Word_t op1, Word_t op2, uint32_t *fflags) { 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; *fflags = softfloat_exceptionFlags; return res; }
これをRISC-Vの定義する命令だけ記述した。まだ32ビットモードしか実装していなかったので、倍精度の命令は実装できていないが、まずはこんなところだろう。
浮動小数点命令をテストする
RISC-Vの実装をテストしてみよう。RISC-Vにはテストパタンであるricv_testsリポジトリが提供されている。
コンパイルしたfaddのテストパタンを実行してみよう。
./swimmer_riscv --binfile ~/riscv-tools/riscv-tests/isa/rv64uf-p-fadd --debug
まずはmcpuidを適切に指定する必要があった。mcpuidのBaseフィールドに適切な値を設定していないと、パタンの先頭でコけて停止してしまう。
このレジスタを適切に設定してパタンを実行してみると、お、流れた!
... 49 : [000002d4] 00052007 : flw r00,r10,0x000 r10=>00001020 (00001020)=>40490fdb f00<=40490fdb 50 : [000002d8] 00452087 : flw r01,r10,0x004 r10=>00001020 (00001024)=>322bcc77 f01<=322bcc77 51 : [000002dc] 00852107 : flw r02,r10,0x008 r10=>00001020 (00001028)=>00000000 f02<=00000000 52 : [000002e0] 00c52683 : lw r13,r10,0x00c r10=>00001020 (0000102c)=>40490fdb r13<=40490fdb 53 : [000002e4] 001071d3 : fadd.s r03,r00,r01 f00=>40490fdb f01=>322bcc77 f03<=40490fdb fflags<=00000001 54 : [000002e8] e0018553 : fmv.x.s r10,r03 f03=>40490fdb r10<=40490fdb 55 : [000002ec] 001015f3 : csrrw r11,0x001,r00 fflags=>00000001 r00=>00000000 fflags<=00000000 r11<=00000001 56 : [000002f0] 00100613 : addi r12,r00,0x001 r00=>00000000 r12<=00000001 57 : [000002f4] 34d51c63 : bne r10,r13,0x1a r10=>40490fdb r13=>40490fdb 58 : [000002f8] 34c59a63 : bne r11,r12,0x1a r11=>00000001 r12=>00000001 59 : [000002fc] 0040006f : jal r00,0x00400 pc<=00000300 60 : [00000300] 00500e13 : addi r28,r00,0x005 r00=>00000000 r28<=00000005 61 : [00000304] 00001517 : auipc r10,0x00001 r10<=00001304 62 : [00000308] d2c50513 : addi r10,r10,0xd2c r10=>00001304 r10<=00001030 63 : [0000030c] 00053007 : fld r00,r10,0x000 r10=>00001030 (00001030)=>00000000 (00001034)=>40040000 f00<=00000000 64 : [00000310] 00853087 : fld r01,r10,0x008 r10=>00001030 (00001038)=>00000000 (0000103c)=>3ff00000 f01<=00000000 65 : [00000314] 01053107 : fld r02,r10,0x010 r10=>00001030 (00001040)=>00000000 (00001044)=>00000000 f02<=00000000 <Error: instruction is not decoded. [00000318]=01853683 ChangeMode from Supervisor to Machine 67 : [00000140] 34202f73 : csrrs r30,0x342,r00 r00=>00000000 mcause=>00000002 r30<=00000002 68 : [00000144] fa0f5ee3 : bge r30,r00,0x7d r30=>00000002 r00=>00000000 pc<=00000100 ...
演算命令を実行した後、整数レジスタに移動して、演算結果と例外結果(fflags)の結果を比較している。
しかし、どうやらこのパタンは単精度命令と倍精度命令が混在して含まれているらしく、倍精度のfadd.d命令の所でエラーを吐いてしまった。 これは、最終的に64ビットモードをサポートしてパタンを通す必要があるなあ。