FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

Binary Translation型エミュレータを作る(riscv-testsのパタンを通していく)

Binary Translation型のエミュレータをRustで自作する話、徐々にテストパタンが安定して動作するようになっている。64ビット整数命令のパタンはすべてPassできるようになりたい。

これに伴っていくつかの実装変更を行った。これまではCSRRW命令などは専用のTCGを持っていたがこれを汎用的なCALL_HELPERに置き換えた。これにより独自のTCGを持つ必要性が減ってより汎用的な実装となっている。

    pub fn translate_csrrw(inst: &InstrInfo) -> Vec<TCGOp> {
        let rs1_addr: usize = get_rs1_addr!(inst.inst) as usize;
        let rd_addr: usize = get_rd_addr!(inst.inst) as usize;
        let csr_const: u64 = get_imm12!(inst.inst);

        let rs1 = Box::new(TCGv::new_reg(rs1_addr as u64));
        let rd = Box::new(TCGv::new_reg(rd_addr as u64));
        let csr = Box::new(TCGv::new_imm(csr_const));

        let csr_op = TCGOp::new_helper_call_arg3(CALL_HELPER_IDX::CALL_CSRRW_IDX as usize, *rd, *rs1, *csr);
        vec![csr_op]
    }

そのほか、TCGを簡単に記述できるようにいくつかWrapperの実装も行った。例えばRAXにGPRの値をロードするための専用関数tcg_gen_load_gpr_64bit()や、RAXの値をGPRにストアするための専用関数tcg_gen_store_gpr_64bitなど。

    fn tcg_gen_load_gpr_64bit(
        emu: &EmuEnv,
        dest: X86TargetRM,
        source: u64,
        mc: &mut Vec<u8>,
    ) -> usize {
        let mut gen_size = 0;
        gen_size +=
            Self::tcg_modrm_64bit_out(X86Opcode::MOV_GV_EV, X86ModRM::MOD_10_DISP_RBP, dest, mc);
        gen_size += Self::tcg_out(emu.calc_gpr_relat_address(source) as u64, 4, mc);
        return gen_size;
    }
    fn tcg_gen_store_gpr_64bit(
        emu: &EmuEnv,
        source: X86TargetRM,
        dest: u64,
        mc: &mut Vec<u8>,
    ) -> usize {
        let mut gen_size = 0;
        gen_size +=
            Self::tcg_modrm_64bit_out(X86Opcode::MOV_EV_GV, X86ModRM::MOD_10_DISP_RBP, source, mc);
        gen_size += Self::tcg_out(emu.calc_gpr_relat_address(dest) as u64, 4, mc);
        return gen_size;
    }

バグをいくつか潰していって現在は殆どすべてのパタンをPassさせることができるようになった。

test rv64ui_p_andi ... ok
test rv64ui_p_add ... ok
test rv64ui_p_addi ... ok
test rv64ui_p_addiw ... ok
test rv64ui_p_auipc ... ok
test rv64ui_p_beq ... ok
test rv64ui_p_addw ... ok
test rv64ui_p_and ... ok
...
test rv64ui_p_sraiw ... ok
test rv64ui_p_sraw ... ok
test rv64ui_p_srl ... ok
test rv64ui_p_srli ... ok
test rv64ui_p_srliw ... ok
test rv64ui_p_srlw ... ok
test rv64ui_p_sub ... ok
test rv64ui_p_subw ... ok
test rv64ui_p_sw ... ok
test rv64ui_p_xor ... ok
test rv64ui_p_xori ... ok

次はどっちの方向に進もうか。。。乗除算命令系を実装しなければならないとして、その後は浮動小数点の方向へ行くか、仮想アドレスのサポートへ進むか。。。