FPGA開発日記

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

Binary Translation型エミュレータを作る(ロードストア命令全修正)

前回のブログではBinary Translation型のエミュレータの実装において、いくつかの命令を新しいTCG形式に書き直した。これをすべてのメモリアクセス命令について修正していこうと思う。RISC-Vには以下のロードストア命令が定義されている。

命令 アセンブリ言語 説明
LD ld rd, imm(rs1) 64ビットデータロード
LW lw rd, imm(rs1) 32ビット符号拡張付きデータロード
LWU lwu rd, imm(rs1) 32ビット符号拡張無しデータロード
LH lh rd, imm(rs1) 16ビット符号拡張付きデータロード
LHU lhu rd, imm(rs1) 16ビット符号拡張無しデータロード
LB lb rd, imm(rs1) 8ビット符号拡張付きデータロード
LBU lbu rd, imm(rs1) 8ビット符号拡張無しデータロード
SD sd rs2, imm(rs1) 64ビットデータストア
SW sw rs2, imm(rs1) 32ビットデータストア
SH sh rs2, imm(rs1) 16ビットデータストア
SB sb rs2, imm(rs1) 8ビットデータストア
f:id:msyksphinz:20201101114252p:plain

これらのすべての命令について新しいTCGを適用した。

impl TranslateRiscv {
...
    pub fn translate_ld(&mut self, inst: &InstrInfo) -> Vec<TCGOp> {
        self.translate_load(inst, TCGOpcode::LOAD_64BIT, CALL_HELPER_IDX::CALL_LOAD64_IDX)
    }
    pub fn translate_lw(&mut self, inst: &InstrInfo) -> Vec<TCGOp> {
        self.translate_load(inst, TCGOpcode::LOAD_32BIT, CALL_HELPER_IDX::CALL_LOAD32_IDX)
    }
    pub fn translate_lh(&mut self, inst: &InstrInfo) -> Vec<TCGOp> {
        self.translate_load(inst, TCGOpcode::LOAD_16BIT, CALL_HELPER_IDX::CALL_LOAD16_IDX)
    }
    pub fn translate_lb(&mut self, inst: &InstrInfo) -> Vec<TCGOp> {
        self.translate_load(inst, TCGOpcode::LOAD_8BIT, CALL_HELPER_IDX::CALL_LOAD8_IDX)
    }
    pub fn translate_lwu(&mut self, inst: &InstrInfo) -> Vec<TCGOp> {
        self.translate_load(inst, TCGOpcode::LOADU_32BIT, CALL_HELPER_IDX::CALL_LOADU32_IDX)
    }
    pub fn translate_lhu(&mut self, inst: &InstrInfo) -> Vec<TCGOp> {
        self.translate_load(inst, TCGOpcode::LOADU_16BIT, CALL_HELPER_IDX::CALL_LOADU16_IDX)
    }
    pub fn translate_lbu(&mut self, inst: &InstrInfo) -> Vec<TCGOp> {
        self.translate_load(inst, TCGOpcode::LOADU_8BIT, CALL_HELPER_IDX::CALL_LOADU8_IDX)
    }
    ...
    pub fn translate_sd(&mut self, inst: &InstrInfo) -> Vec<TCGOp> {
        self.translate_store(inst, TCGOpcode::STORE_64BIT, CALL_HELPER_IDX::CALL_STORE64_IDX)
    }
    pub fn translate_sw(&mut self, inst: &InstrInfo) -> Vec<TCGOp> {
        self.translate_store(inst, TCGOpcode::STORE_32BIT, CALL_HELPER_IDX::CALL_STORE32_IDX)
    }
    pub fn translate_sh(&mut self, inst: &InstrInfo) -> Vec<TCGOp> {
        self.translate_store(inst, TCGOpcode::STORE_16BIT, CALL_HELPER_IDX::CALL_STORE16_IDX)
    }
    pub fn translate_sb(&mut self, inst: &InstrInfo) -> Vec<TCGOp> {
        self.translate_store(inst, TCGOpcode::STORE_8BIT, CALL_HELPER_IDX::CALL_STORE8_IDX)
    }

それぞれの実装については前回のブログに実装を掲載したので参照してほしい。

これによりロードストア命令のパタンがPassできるようになった。良かった良かった。

$ cargo run -- --elf-file /home/msyksphinz/riscv64/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-ld

sh_flags = 0
sh_flags = 0
tvec = 0000000080000004
7.8193 ns finished
Result: MEM[0x1000] = 00000001
$ cargo run -- --elf-file /home/msyksphinz/riscv64/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-v-ld

85.2794 ns finished
Result: MEM[0x1000] = 00000001