前回のブログでは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ビットデータストア |
これらのすべての命令について新しい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