FPGA開発日記

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

Binary Translation型エミュレータを作る(ストア命令をTCGで書き直す)

Binary Translation型のRISC-Vエミュレータを作っている。これまで、Binary Translationのための中間表現であるTCGは、かなりx86に近い構造になっていたが、より一般的な構造としてTCGをより細かな粒度に変換している。新しいTCGを使ってメモリアクセス命令を書き直していこうと思う。

ロード命令について実装が完了したので、次はストア命令だ。物理アドレスへの変換のためのTCGは完成しているので、最後のロード命令をストア命令に置き換えるだけだ。

f:id:msyksphinz:20201031110627p:plain
        // Extract lower 12bit address and add with TLB address
        tcg_lists.push(tcg_label_tlb_match);
        tcg_lists.push(TCGOp::new_1op(TCGOpcode::MOVE_STACK, stack_reg));
        tcg_lists.push(TCGOp::new_2op(TCGOpcode::ADD_TLBADDR_OFFSET, tlb_byte_addr, stack_reg));  // Relative Addr of TLB Paddr
        tcg_lists.push(TCGOp::new_3op(TCGOpcode::ADD_64BIT, tlb_byte_addr, tlb_byte_addr, vaddr_tlb_idx));
        tcg_lists.push(TCGOp::new_2op(TCGOpcode::MEM_LOAD, tlb_byte_addr, tlb_byte_addr));
        tcg_lists.push(TCGOp::new_3op(TCGOpcode::ADD_64BIT, tlb_byte_addr, tlb_byte_addr, vaddr_low12bit));
        tcg_lists.push(TCGOp::new_3op(TCGOpcode::ADD_64BIT, tlb_byte_addr, tlb_byte_addr, TCGv::new_imm(0x80000000)));
        tcg_lists.push(TCGOp::new_2op(TCGOpcode::ADD_MEM_OFFSET, tlb_byte_addr, tlb_byte_addr));
        tcg_lists.push(TCGOp::tcg_get_gpr(stack_reg, rs2_addr));
        tcg_lists.push(TCGOp::new_2op(TCGOpcode::MEM_STORE, stack_reg, tlb_byte_addr));
        tcg_lists.push(tcg_label_load_excp);

最後のTCGMEM_LOADからMEM_STOREへ書き換えた。これだけでストア命令の実装完了だ。テストパタンを実行してみる。

$ cargo run -- --step --mmu --dump-gpr --dump-guest --dump-host \
    --elf-file /home/msyksphinz/riscv64/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-sd | tee rv64ui-p-sd.step.dydra.log

ストア命令に対して以下のようなx86命令が生成された。

69: Guest PC Address = 8000016c
<Convert_Virtual_Address. virtual_addr=000000008000016c : vm_mode = 0, priv_mode = 3>
  converted physical address = 8000016c
 000000008000016c:000000008000016c Hostcode 0020b423 : sd      sp, 8(ra)
00007F8208B10000 488B9510000000       mov       0x10(%rbp),%rdx
00007F8208B10007 4881C208000000       add       $8,%rdx
00007F8208B1000E 488BDA               mov       %rdx,%rbx
00007F8208B10011 4881E3FF0F0000       and       $0xFFF,%rbx
00007F8208B10018 488BCA               mov       %rdx,%rcx
00007F8208B1001B 48C1E90C             shr       $0xC,%rcx
00007F8208B1001F 4881E1FF0F0000       and       $0xFFF,%rcx
00007F8208B10026 48C1E103             shl       $3,%rcx
00007F8208B1002A 488BF5               mov       %rbp,%rsi
00007F8208B1002D 488BFE               mov       %rsi,%rdi
00007F8208B10030 4881C7A0050000       add       $0x5A0,%rdi
00007F8208B10037 4803F9               add       %rcx,%rdi
00007F8208B1003A 48C1EA18             shr       $0x18,%rdx
00007F8208B1003E 488B3F               mov       (%rdi),%rdi
00007F8208B10041 483BFA               cmp       %rdx,%rdi
00007F8208B10044 0F844A000000         je        0x0000_7F82_08B1_0094
00007F8208B1004A 48BF40DF45C8FF7F0000 movabs    $0x7FFF_C845_DF40,%rdi
00007F8208B10054 48BE0200000000000000 movabs    $2,%rsi
00007F8208B1005E 48BA0100000000000000 movabs    $1,%rdx
00007F8208B10068 48B90800000000000000 movabs    $8,%rcx
00007F8208B10072 49B86C01008000000000 movabs    $0x8000_016C,%r8
00007F8208B1007C FF9598040000         callq     *0x498(%rbp)
00007F8208B10082 483B8508000000       cmp       8(%rbp),%rax
00007F8208B10089 0F840A000000         je        0x0000_7F82_08B1_0099
00007F8208B1008F E97BFF3E00           jmp       0x0000_7F82_08F0_000F
00007F8208B10094 488BF5               mov       %rbp,%rsi
00007F8208B10097 488BFE               mov       %rsi,%rdi
00007F8208B1009A 4881C7A0850000       add       $0x85A0,%rdi
00007F8208B100A1 4803F9               add       %rcx,%rdi
00007F8208B100A4 488B3F               mov       (%rdi),%rdi
00007F8208B100A7 4803FB               add       %rbx,%rdi
00007F8208B100AA 4881C700000080       add       $0xFFFF_FFFF_8000_0000,%rdi
00007F8208B100B1 48B80000F108827F0000 movabs    $0x7F82_08F1_0000,%rax
00007F8208B100BB 4803F8               add       %rax,%rdi
00007F8208B100BE 488BB518000000       mov       0x18(%rbp),%rsi
00007F8208B100C5 488937               mov       %rsi,(%rdi)
00007F8208B100C8 E942FF3E00           jmp       0x0000_7F82_08F0_000F

最後の以下の命令がポイントで、最後のmov命令でメモリストアを行っている。

00007F8208B100AA 4881C700000080       add       $0xFFFF_FFFF_8000_0000,%rdi
00007F8208B100B1 48B80000F108827F0000 movabs    $0x7F82_08F1_0000,%rax
00007F8208B100BB 4803F8               add       %rax,%rdi
00007F8208B100BE 488BB518000000       mov       0x18(%rbp),%rsi
00007F8208B100C5 488937               mov       %rsi,(%rdi)