FPGA開発日記

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

Binary Translation型エミュレータを作る(Compressed命令の実装2)

前回Compressed命令のフレームワークは完成したので後はひたすら命令を追加していくだけとなる。算術演算命令の実装を行った。

Compressed命令はレジスタフィールドの取り扱いに一貫性が無いので、レジスタの読み取り方法が難しい。C.ADD命令は5ビットを用いた32本のレジスタを使用するエンコーディングだが、C.SUB命令などはレジスタは3ビットの圧縮形式のレジスタエンコーディングとなっている。

f:id:msyksphinz:20201126232159p:plain
f:id:msyksphinz:20201126232210p:plain
    pub fn translate_c_add (&mut self, inst: &InstrInfo) -> Vec<TCGOp> { 
        let rd_addr   = (inst.inst >> 7) & 0x1f;
        let rs2_addr  = (inst.inst >> 2) & 0x1f;

        let mut tcg_lists = vec![];

        let rd_tmp = self.tcg_temp_new();
        let rs2_tmp = self.tcg_temp_new();

        tcg_lists.push(TCGOp::tcg_get_gpr(rd_tmp, rd_addr));
        tcg_lists.push(TCGOp::tcg_get_gpr(rs2_tmp, rs2_addr));
        
        tcg_lists.push(TCGOp::new_3op(TCGOpcode::ADD_64BIT, rd_tmp, rd_tmp, rs2_tmp));
        tcg_lists.push(TCGOp::tcg_set_gpr(rd_addr, rd_tmp));

        self.tcg_temp_free(rd_tmp);
        self.tcg_temp_free(rs2_tmp);

        tcg_lists
    }
    pub fn translate_c_sub   (&mut self, inst: &InstrInfo) -> Vec<TCGOp> { 
        let rd_addr   = get_c_reg_addr!((inst.inst >> 7) & 0x7);
        let rs2_addr  = get_c_reg_addr!((inst.inst >> 2) & 0x7);

        let mut tcg_lists = vec![];

        let rd_tmp = self.tcg_temp_new();
        let rs2_tmp = self.tcg_temp_new();

        tcg_lists.push(TCGOp::tcg_get_gpr(rd_tmp, rd_addr));
        tcg_lists.push(TCGOp::tcg_get_gpr(rs2_tmp, rs2_addr));
        
        tcg_lists.push(TCGOp::new_3op(TCGOpcode::SUB_64BIT, rd_tmp, rd_tmp, rs2_tmp));
        tcg_lists.push(TCGOp::tcg_set_gpr(rd_addr, rd_tmp));

        self.tcg_temp_free(rd_tmp);
        self.tcg_temp_free(rs2_tmp);

        tcg_lists
    }

レジスタエンコーディングの部分だけ注意すれば、それ以外の実装部分は通常の命令の実装から借りてくることができる。

C.ADD命令 / C.SUB命令のx86に変換した結果は以下のコードになった。

  • C.ADD命令の変換結果
 00000000800022ba:00000000800022ba Hostcode 039392aa : c.add   t0, a0
00007FA618080000 488B9530000000       mov       0x30(%rbp),%rdx
00007FA618080007 488B9D58000000       mov       0x58(%rbp),%rbx
00007FA61808000E 4803D3               add       %rbx,%rdx
00007FA618080011 48899530000000       mov       %rdx,0x30(%rbp)
00007FA618080018 E9F2FFF700           jmp       0x0000_7FA6_1900_000F
  • C.SUB命令の変換結果
 0000000080002118:0000000080002118 Hostcode 00018c89 : c.sub   s1, a0
00007FA618860000 488B9550000000       mov       0x50(%rbp),%rdx
00007FA618860007 488B9D58000000       mov       0x58(%rbp),%rbx
00007FA61886000E 482BD3               sub       %rbx,%rdx
00007FA618860011 48899550000000       mov       %rdx,0x50(%rbp)
00007FA618860018 E9F2FF7900           jmp       0x0000_7FA6_1900_000F

ここまではテストパタンの正常動作を確認できた。