summaryrefslogtreecommitdiff
path: root/src/instructions.rs
blob: e4d5b0364c791c02eca1bbaf67098c4fa3f1121c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// Copyright (c) 2025 taitep
// SPDX-License-Identifier: MIT
//
// This file is part of TRVE (https://gitea.taitep.se/taitep/trve)
// See LICENSE file in the project root for full license text.

mod rvi;

use crate::{
    core::{Core, InstructionResult},
    decode::Instruction,
};

pub(crate) fn find_and_exec(instr: Instruction, core: &mut Core) -> Option<InstructionResult> {
    match instr.opcode_noncompressed() {
        0b01100 => match (instr.funct7(), instr.funct3()) {
            // OP
            (0b0000000, 0b000) => Some(rvi::add(core, instr)),
            (0b0100000, 0b000) => Some(rvi::sub(core, instr)),
            (0b0000000, 0b111) => Some(rvi::and(core, instr)),
            (0b0000000, 0b110) => Some(rvi::or(core, instr)),
            _ => None,
        },
        0b00100 => match instr.funct3() {
            // OP_IMM
            0b000 => Some(rvi::addi(core, instr)),
            0b001 => (instr.funct6() == 0).then(|| rvi::slli(core, instr)),
            0b101 => match instr.funct6() {
                // immediate right-shift
                0b000000 => Some(rvi::srli(core, instr)),
                _ => None,
            },
            0b111 => Some(rvi::andi(core, instr)),
            _ => None,
        },
        0b00110 => match instr.funct3() {
            // OP_IMM_32
            0b000 => Some(rvi::addiw(core, instr)),
            _ => None,
        },
        0b01000 => match instr.funct3() {
            // STORE
            0b000 => Some(rvi::sb(core, instr)),
            0b001 => Some(rvi::sh(core, instr)),
            0b010 => Some(rvi::sw(core, instr)),
            0b011 => Some(rvi::sd(core, instr)),
            _ => None,
        },
        0b00000 => match instr.funct3() {
            // LOAD
            0b000 => Some(rvi::lb(core, instr)),
            0b100 => Some(rvi::lbu(core, instr)),
            0b001 => Some(rvi::lh(core, instr)),
            0b010 => Some(rvi::lw(core, instr)),
            0b011 => Some(rvi::ld(core, instr)),
            _ => None,
        },
        0b11000 => match instr.funct3() {
            // BRANCH
            0b000 => Some(rvi::beq(core, instr)),
            0b001 => Some(rvi::bne(core, instr)),
            0b100 => Some(rvi::blt(core, instr)),
            0b110 => Some(rvi::bltu(core, instr)),
            0b111 => Some(rvi::bgeu(core, instr)),
            _ => None,
        },
        0b01101 => Some(rvi::lui(core, instr)),
        0b00101 => Some(rvi::auipc(core, instr)),
        0b11011 => Some(rvi::jal(core, instr)),
        0b11001 => (instr.funct3() == 0).then(|| rvi::jalr(core, instr)),
        _ => None,
    }
}