rrs_lib/
process_instruction.rs

1// Copyright 2021 Gregory Chadwick <mail@gregchadwick.co.uk>
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5use super::instruction_formats;
6use super::InstructionProcessor;
7
8fn process_opcode_op<T: InstructionProcessor>(
9    processor: &mut T,
10    insn_bits: u32,
11) -> Option<T::InstructionResult> {
12    let dec_insn = instruction_formats::RType::new(insn_bits);
13
14    match dec_insn.funct3 {
15        0b000 => match dec_insn.funct7 {
16            0b000_0000 => Some(processor.process_add(dec_insn)),
17            0b000_0001 => Some(processor.process_mul(dec_insn)),
18            0b010_0000 => Some(processor.process_sub(dec_insn)),
19            _ => None,
20        },
21        0b001 => match dec_insn.funct7 {
22            0b000_0000 => Some(processor.process_sll(dec_insn)),
23            0b000_0001 => Some(processor.process_mulh(dec_insn)),
24            _ => None,
25        },
26        0b010 => match dec_insn.funct7 {
27            0b000_0000 => Some(processor.process_slt(dec_insn)),
28            0b000_0001 => Some(processor.process_mulhsu(dec_insn)),
29            _ => None,
30        },
31        0b011 => match dec_insn.funct7 {
32            0b000_0000 => Some(processor.process_sltu(dec_insn)),
33            0b000_0001 => Some(processor.process_mulhu(dec_insn)),
34            _ => None,
35        },
36        0b100 => match dec_insn.funct7 {
37            0b000_0000 => Some(processor.process_xor(dec_insn)),
38            0b000_0001 => Some(processor.process_div(dec_insn)),
39            _ => None,
40        },
41        0b101 => match dec_insn.funct7 {
42            0b000_0000 => Some(processor.process_srl(dec_insn)),
43            0b000_0001 => Some(processor.process_divu(dec_insn)),
44            0b010_0000 => Some(processor.process_sra(dec_insn)),
45            _ => None,
46        },
47        0b110 => match dec_insn.funct7 {
48            0b000_0000 => Some(processor.process_or(dec_insn)),
49            0b000_0001 => Some(processor.process_rem(dec_insn)),
50            _ => None,
51        },
52        0b111 => match dec_insn.funct7 {
53            0b000_0000 => Some(processor.process_and(dec_insn)),
54            0b000_0001 => Some(processor.process_remu(dec_insn)),
55            _ => None,
56        },
57        _ => None,
58    }
59}
60
61fn process_opcode_op_imm<T: InstructionProcessor>(
62    processor: &mut T,
63    insn_bits: u32,
64) -> Option<T::InstructionResult> {
65    let dec_insn = instruction_formats::IType::new(insn_bits);
66
67    match dec_insn.funct3 {
68        0b000 => Some(processor.process_addi(dec_insn)),
69        0b001 => Some(processor.process_slli(instruction_formats::ITypeShamt::new(insn_bits))),
70        0b010 => Some(processor.process_slti(dec_insn)),
71        0b011 => Some(processor.process_sltui(dec_insn)),
72        0b100 => Some(processor.process_xori(dec_insn)),
73        0b101 => {
74            let dec_insn_shamt = instruction_formats::ITypeShamt::new(insn_bits);
75            match dec_insn_shamt.funct7 {
76                0b000_0000 => Some(processor.process_srli(dec_insn_shamt)),
77                0b010_0000 => Some(processor.process_srai(dec_insn_shamt)),
78                _ => None,
79            }
80        }
81        0b110 => Some(processor.process_ori(dec_insn)),
82        0b111 => Some(processor.process_andi(dec_insn)),
83        _ => None,
84    }
85}
86
87fn process_opcode_branch<T: InstructionProcessor>(
88    processor: &mut T,
89    insn_bits: u32,
90) -> Option<T::InstructionResult> {
91    let dec_insn = instruction_formats::BType::new(insn_bits);
92
93    match dec_insn.funct3 {
94        0b000 => Some(processor.process_beq(dec_insn)),
95        0b001 => Some(processor.process_bne(dec_insn)),
96        0b100 => Some(processor.process_blt(dec_insn)),
97        0b101 => Some(processor.process_bge(dec_insn)),
98        0b110 => Some(processor.process_bltu(dec_insn)),
99        0b111 => Some(processor.process_bgeu(dec_insn)),
100        _ => None,
101    }
102}
103
104fn process_opcode_load<T: InstructionProcessor>(
105    processor: &mut T,
106    insn_bits: u32,
107) -> Option<T::InstructionResult> {
108    let dec_insn = instruction_formats::IType::new(insn_bits);
109
110    match dec_insn.funct3 {
111        0b000 => Some(processor.process_lb(dec_insn)),
112        0b001 => Some(processor.process_lh(dec_insn)),
113        0b010 => Some(processor.process_lw(dec_insn)),
114        0b100 => Some(processor.process_lbu(dec_insn)),
115        0b101 => Some(processor.process_lhu(dec_insn)),
116        _ => None,
117    }
118}
119
120fn process_opcode_store<T: InstructionProcessor>(
121    processor: &mut T,
122    insn_bits: u32,
123) -> Option<T::InstructionResult> {
124    let dec_insn = instruction_formats::SType::new(insn_bits);
125
126    match dec_insn.funct3 {
127        0b000 => Some(processor.process_sb(dec_insn)),
128        0b001 => Some(processor.process_sh(dec_insn)),
129        0b010 => Some(processor.process_sw(dec_insn)),
130        _ => None,
131    }
132}
133
134/// Decodes instruction in `insn_bits` calling the appropriate function in `processor` returning
135/// the result it produces.
136///
137/// Returns `None` if instruction doesn't decode into a valid instruction.
138pub fn process_instruction<T: InstructionProcessor>(
139    processor: &mut T,
140    insn_bits: u32,
141) -> Option<T::InstructionResult> {
142    let opcode: u32 = insn_bits & 0x7f;
143
144    match opcode {
145        instruction_formats::OPCODE_OP => process_opcode_op(processor, insn_bits),
146        instruction_formats::OPCODE_OP_IMM => process_opcode_op_imm(processor, insn_bits),
147        instruction_formats::OPCODE_LUI => {
148            Some(processor.process_lui(instruction_formats::UType::new(insn_bits)))
149        }
150        instruction_formats::OPCODE_AUIPC => {
151            Some(processor.process_auipc(instruction_formats::UType::new(insn_bits)))
152        }
153        instruction_formats::OPCODE_BRANCH => process_opcode_branch(processor, insn_bits),
154        instruction_formats::OPCODE_LOAD => process_opcode_load(processor, insn_bits),
155        instruction_formats::OPCODE_STORE => process_opcode_store(processor, insn_bits),
156        instruction_formats::OPCODE_JAL => {
157            Some(processor.process_jal(instruction_formats::JType::new(insn_bits)))
158        }
159        instruction_formats::OPCODE_JALR => {
160            Some(processor.process_jalr(instruction_formats::IType::new(insn_bits)))
161        }
162        instruction_formats::OPCODE_MISC_MEM => {
163            let dec_insn = instruction_formats::IType::new(insn_bits);
164            match dec_insn.funct3 {
165                0b000 => Some(processor.process_fence(dec_insn)),
166                _ => None,
167            }
168        }
169        _ => None,
170    }
171}