前回Compressed命令のフレームワークは完成したので後はひたすら命令を追加していくだけとなる。算術演算命令の実装を行った。
Compressed命令はレジスタフィールドの取り扱いに一貫性が無いので、レジスタの読み取り方法が難しい。C.ADD命令は5ビットを用いた32本のレジスタを使用するエンコーディングだが、C.SUB命令などはレジスタは3ビットの圧縮形式のレジスタエンコーディングとなっている。
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
ここまではテストパタンの正常動作を確認できた。