Binary Translation型のRISC-Vエミュレータを作っている。これまで、Binary Translationのための中間表現であるTCGは、かなりx86に近い構造になっていたが、より一般的な構造としてTCGをより細かな粒度に変換している。新しいTCGを使ってメモリアクセス命令を書き直していこうと思う。
ロード命令について実装が完了したので、次はストア命令だ。物理アドレスへの変換のためのTCGは完成しているので、最後のロード命令をストア命令に置き換えるだけだ。
// 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);
最後のTCGをMEM_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)