Repository: nexus-xyz/nexus-zkvm
File: vm/src/rv32/parse.rs (Rust)

Code before:

// parsing of arithmetic operations pg. 18-20

fn aop(word: u32) -> Option<AOP> {
    assert_eq!(opcode(word), OPC_ALU);
    let res = match (funct3(word), funct7(word)) {
        (0b000, 0b0100000) => SUB,
        (0b000, 0b0000000) => ADD,
        (0b001, 0b0000000) => SLL,
        (0b010, 0b0000000) => SLT,
        (0b011, 0b0000000) => SLTU,
        (0b100, 0b0000000) => XOR,
        (0b101, 0b0000000) => SRL,
        (0b101, 0b0100000) => SRA,
        (0b110, 0b0000000) => OR,
        (0b111, 0b0000000) => AND,
        _ => return None,
    };
    Some(res)
}

fn aopi(word: u32) -> Option<AOP> {
    assert_eq!(opcode(word), OPC_ALUI);
    let res = match (funct3(word), funct7(word)) {
        (0b000, _) => ADD,
        (0b001, 0b0000000) => SLL,
        (0b010, _) => SLT,
        (0b011, _) => SLTU,
        (0b100, _) => XOR,
        (0b101, 0b0000000) => SRL,
        (0b101, 0b0100000) => SRA,
        (0b110, _) => OR,
        (0b111, _) => AND,
        _ => return None,
    };
    Some(res)
}

/// extract immediate from ALU instruction
pub fn immA(word: u32) -> u32 {
    match funct3(word) {
        0b001 | 0b101 => shamt(word),
        _ => immI(word),
    }
}

// instruction parsing by opcode

#[allow(clippy::unusual_byte_groupings)]
#[rustfmt::skip]
mod opcodes {

Review comment (bug):
We should document here with a comment that `funct7` happens to capture the same set of bits as the `imm[11:6]` chunk that distinguishes the type of intermediate-based shift (`slli` vs. `srli` vs. `srai`).

Otherwise at first glance it looks like we're parsing them wrong since they don't include a `funct7` chunk.

Code after:

// parsing of arithmetic operations pg. 18-20

fn aop(word: u32) -> Option<AOP> {
    assert_eq!(opcode(word), OPC_ALU);
    let res = match (funct3(word), funct7(word)) {
        (0b000, 0b0100000) => SUB,
        (0b000, 0b0000000) => ADD,
        (0b001, 0b0000000) => SLL,
        (0b010, 0b0000000) => SLT,
        (0b011, 0b0000000) => SLTU,
        (0b100, 0b0000000) => XOR,
        (0b101, 0b0000000) => SRL,
        (0b101, 0b0100000) => SRA,
        (0b110, 0b0000000) => OR,
        (0b111, 0b0000000) => AND,
        _ => return None,
    };
    Some(res)
}

fn aopi(word: u32) -> Option<AOP> {
    assert_eq!(opcode(word), OPC_ALUI);
    let res = match (funct3(word), funct7(word) /* imm[11:5] */) {
        (0b000, _ /* imm[11:5] can be any */) => ADD,
        (0b001, 0b0000000 /* SLLI requires special value in imm[11:5] */) => SLL,
        (0b010, _ /* imm[11:5] can be any */) => SLT,
        (0b011, _ /* imm[11:5] can be any */) => SLTU,
        (0b100, _ /* imm[11:5] can be any */) => XOR,
        (0b101, 0b0000000 /* SRLI requires special value in imm[11:5] */) => SRL,
        (0b101, 0b0100000 /* SRAI requires special value in imm[11:5] */) => SRA,
        (0b110, _ /* imm[11:5] can be any */) => OR,
        (0b111, _ /* imm[11:5] can be any */) => AND,
        _ => return None,
    };
    Some(res)
}

/// extract immediate from ALU instruction
pub fn immA(word: u32) -> u32 {
    match funct3(word) {
        0b001 | 0b101 => shamt(word),
        _ => immI(word),
    }
}

// instruction parsing by opcode

#[allow(clippy::unusual_byte_groupings)]
#[rustfmt::skip]
mod opcodes {