user_mode_riscv/cpu/
instruction.rs

1use crate::cpu::{Cpu, Trap};
2use std::fmt::{Debug, Formatter};
3use std::fmt;
4
5pub struct Instruction {
6    pub name: &'static str,
7    pub operation: fn(cpu: &mut Cpu, word: u32, address: *const u8) -> Result<(), Trap>
8}
9
10impl Debug for Instruction {
11    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
12        f.debug_struct("Instruction")
13            .field("name", &self.name)
14            .finish()
15    }
16}
17
18#[derive(Debug)]
19pub struct FormatR {
20    pub rd: usize,
21    pub rs1: usize,
22    pub rs2: usize
23}
24
25pub fn parse_format_r(word: u32) -> FormatR {
26    FormatR {
27        rd: ((word >> 7) & 0x1f) as usize, // [11:7]
28        rs1: ((word >> 15) & 0x1f) as usize, // [19:15]
29        rs2: ((word >> 20) & 0x1f) as usize // [24:20]
30    }
31}
32
33#[derive(Debug)]
34pub struct FormatU {
35    pub rd: usize,
36    pub imm: u64
37}
38
39pub fn parse_format_u(word: u32) -> FormatU {
40    FormatU {
41        rd: ((word >> 7) & 0x1f) as usize, // [11:7]
42        imm: (
43            match word & 0x80000000 {
44                0x80000000 => 0xffffffff00000000,
45                _ => 0
46            } | // imm[63:32] = [31]
47                ((word as u64) & 0xfffff000) // imm[31:12] = [31:12]
48        ) as u64
49    }
50}
51
52#[derive(Debug)]
53pub struct FormatI {
54    pub rd: usize,
55    pub rs1: usize,
56    pub imm: i64
57}
58
59pub fn parse_format_i(word: u32) -> FormatI {
60    FormatI {
61        rd: ((word >> 7) & 0x1f) as usize, // [11:7]
62        rs1: ((word >> 15) & 0x1f) as usize, // [19:15]
63        imm: (
64            match word & 0x80000000 { // imm[31:11] = [31]
65                0x80000000 => 0xfffff800,
66                _ => 0
67            } |
68                ((word >> 20) & 0x000007ff) // imm[10:0] = [30:20]
69        ) as i32 as i64
70    }
71}
72
73#[derive(Debug)]
74pub struct FormatJ {
75    pub rd: usize,
76    pub imm: u64
77}
78
79pub fn parse_format_j(word: u32) -> FormatJ {
80    FormatJ {
81        rd: ((word >> 7) & 0x1f) as usize, // [11:7]
82        imm: (
83            match word & 0x80000000 { // imm[31:20] = [31]
84                0x80000000 => 0xfff00000,
85                _ => 0
86            } |
87                (word & 0x000ff000) | // imm[19:12] = [19:12]
88                ((word & 0x00100000) >> 9) | // imm[11] = [20]
89                ((word & 0x7fe00000) >> 20) // imm[10:1] = [30:21]
90        ) as i32 as i64 as u64
91    }
92}
93
94#[derive(Debug)]
95pub struct FormatB {
96    pub rs1: usize,
97    pub rs2: usize,
98    pub imm: u64
99}
100
101pub fn parse_format_b(word: u32) -> FormatB {
102    FormatB {
103        rs1: ((word >> 15) & 0x1f) as usize, // [19:15]
104        rs2: ((word >> 20) & 0x1f) as usize, // [24:20]
105        imm: (
106            match word & 0x80000000 { // imm[31:12] = [31]
107                0x80000000 => 0xfffff000,
108                _ => 0
109            } |
110                ((word << 4) & 0x00000800) | // imm[11] = [7]
111                ((word >> 20) & 0x000007e0) | // imm[10:5] = [30:25]
112                ((word >> 7) & 0x0000001e) // imm[4:1] = [11:8]
113        ) as i32 as i64 as u64
114    }
115}
116
117#[derive(Debug)]
118pub struct FormatS {
119    pub rs1: usize,
120    pub rs2: usize,
121    pub imm: i64
122}
123
124pub fn parse_format_s(word: u32) -> FormatS {
125    FormatS {
126        rs1: ((word >> 15) & 0x1f) as usize, // [19:15]
127        rs2: ((word >> 20) & 0x1f) as usize, // [24:20]
128        imm: (
129            match word & 0x80000000 {
130                0x80000000 => 0xfffff000,
131                _ => 0
132            } | // imm[31:12] = [31]
133                ((word >> 20) & 0xfe0) | // imm[11:5] = [31:25]
134                ((word >> 7) & 0x1f) // imm[4:0] = [11:7]
135        ) as i32 as i64
136    }
137}
138
139#[derive(Debug)]
140pub struct FormatCSR {
141    pub csr: u16,
142    pub rs: usize,
143    pub rd: usize
144}
145
146pub fn parse_format_csr(word: u32) -> FormatCSR {
147    FormatCSR {
148        csr: ((word >> 20) & 0xfff) as u16, // [31:20]
149        rs: ((word >> 15) & 0x1f) as usize, // [19:15], also uimm
150        rd: ((word >> 7) & 0x1f) as usize // [11:7]
151    }
152}
153
154// has rs3
155#[derive(Debug)]
156pub struct FormatR2 {
157    pub rd: usize,
158    pub rs1: usize,
159    pub rs2: usize,
160    pub rs3: usize
161}
162
163pub fn parse_format_r2(word: u32) -> FormatR2 {
164    FormatR2 {
165        rd: ((word >> 7) & 0x1f) as usize, // [11:7]
166        rs1: ((word >> 15) & 0x1f) as usize, // [19:15]
167        rs2: ((word >> 20) & 0x1f) as usize, // [24:20]
168        rs3: ((word >> 27) & 0x1f) as usize // [31:27]
169    }
170}
171