以下の内容はhttps://msyksphinz.hatenablog.com/entry/2025/10/18/040000より取得しました。


Snipersim 8.1をRISC-V対応でビルドさせる方法試行 (3. riscv-opcodesを使った自動化)

github.com

msyksphinz.hatenablog.com

SniperのRISC-V向けデコーダは結構古いものが使われているので、 riscv-opcodes (https://github.com/riscv/riscv-opcodes) を使ってデコーダを最新版に更新することを考える。

まず、riscv-opcodes をダウンロードする。

    if [ ! -d "$NEW_OPCODES_DIR" ]; then
        echo "Error: Latest riscv-opcodes not found"
        echo "Please fetch it with:"
        echo "  cd $RISCV_DIR && git clone https://github.com/riscv/riscv-opcodes.git riscv-opcodes-latest"
        exit 1
    fi

ターゲットとなる命令拡張をもとに、Sniper用のopcodesを作っていく。最初はrv8のフォーマットに準じながらデコーダを作ろうかと考えたが、それは無駄な気がしてきたので、riscv-opcodeから直接デコーダを作る方法を探ることにした。

  1. riscv-opcodes (公式定義)
  2. generate_decoder.py (変換スクリプト)
  3. riscv_decoder_generated.h (生成ヘッダ)
  4. riscv_decoder_simple.{h,cc} (デコーダ実装)

1. 生成スクリプト

生成スクリプトによって、riscv-opcodeから必要な情報を抽出していく。

#!/usr/bin/env python3
"""
RISC-V Decoder Header Generator
riscv-opcodesからRISC-Vデコーダヘッダーを直接生成
"""

def classify_instruction(name):
    """命令を分類"""
    if name.startswith(('beq', 'bne', 'blt', 'bge')):
        return 'branch'
    elif name.startswith(('jal', 'jalr')):
        return 'jump'
    elif name.startswith(('lb', 'lh', 'lw', 'ld')):
        return 'load'
    # ... その他の分類

2. 生成されるデータ構造

抽出した情報をもとに、 riscv_decoder_generated.h を吐き出す。

decode構造体

namespace riscv {

struct decode {
    int32_t  imm;        // 即値
    uint8_t  rd;         // デスティネーションレジスタ
    uint8_t  rs1;        // ソースレジスタ1
    uint8_t  rs2;        // ソースレジスタ2
    uint8_t  rs3;        // ソースレジスタ3
    uint16_t op    : 10; // オペレーション
    uint16_t codec : 6;  // コーデック
    uint8_t  rm    : 3;  // 丸めモード
    uint8_t  aq    : 1;  // acquire
    uint8_t  rl    : 1;  // release
    uint8_t  pred  : 4;  // fence predecessor
    uint8_t  succ  : 4;  // fence successor
};

}

命令enum

enum rv_op {
    rv_op_illegal = 0,
    rv_op_beq = 1,      // branch
    rv_op_bne = 2,      // branch
    rv_op_add = 20,     // alu
    rv_op_c_addi = 204, // compressed
    // ...
};

3. デコーダ実装

riscv_decoder_generated.h をもとに、Sniper向けのRISC-Vデコーダのクラスを作成する。

class RISCVDecoderSimple : public Decoder
{
public:
    void decode(DecodedInst * inst) override {
        riscv::decode dec;
        riscv::inst_t r_inst;
        memcpy(&r_inst, inst->get_code(), 8);

        // 命令長判定
        uint32_t inst_bits = r_inst & 0xFFFFFFFF;
        inst->get_size() = ((inst_bits & 0x3) != 0x3) ? 2 : 4;

        // デコード
        riscv::decode_inst_rv64(dec, r_inst);
        ((RISCVDecodedInstSimple *)inst)->set_decode(dec);
    }

    // その他の仮想関数実装...
};

以下のようなコマンドで、riscv_decoder_generated.hを生成する。

# riscv-opcodesから直接生成
cat riscv/riscv-tools/riscv-opcodes/opcodes \\
    riscv/riscv-tools/riscv-opcodes/opcodes-rvc | \\
python3 riscv/scripts/generate_decoder.py /dev/stdin \\
    > decoder_lib/riscv_decoder_generated.h

RISC-Vの拡張を増やしたい場合、以下のようにしてターゲットとなるファイルの指定を増やす。

cat riscv/riscv-tools/riscv-opcodes/opcodes \\
    riscv/riscv-tools/riscv-opcodes/opcodes-rvc \\
    riscv/riscv-tools/riscv-opcodes/rv_zba \\
    riscv/riscv-tools/riscv-opcodes/rv_zbb | \\
python3 riscv/scripts/generate_decoder.py /dev/stdin \\
    > decoder_lib/riscv_decoder_generated.h

分類の関数は、さすがに自分で組まないといけないが…

def classify_instruction(name):
    # ...既存の分類...
    elif name.startswith(('andn', 'orn', 'clz', 'ctz')):
        return 'bitmanip'
    # ...



以上の内容はhttps://msyksphinz.hatenablog.com/entry/2025/10/18/040000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14