1mod amo_function;
2mod amo_ordering;
3mod amo_width;
4mod branch_operation;
5mod load_width;
6mod misc_mem;
7mod op_32_function;
8mod op_function;
9mod op_imm_32_function;
10mod op_imm_function;
11mod store_width;
12mod system_function;
13
14pub use self::{
15 amo_function::AmoFunction,
16 amo_ordering::AmoOrdering,
17 amo_width::AmoWidth,
18 branch_operation::BranchOperation,
19 load_width::LoadWidth,
20 misc_mem::MiscMemFunction,
21 op_32_function::Op32Function,
22 op_function::OpFunction,
23 op_imm_32_function::OpImm32Function,
24 op_imm_function::OpImmFunction,
25 store_width::StoreWidth,
26 system_function::{CSRFunction, EnvironmentFunction, SystemFunction},
27};
28
29#[derive(Copy, Clone, Debug, PartialEq)]
30#[repr(u8)]
31pub enum Opcode {
32 Load(LoadWidth),
33 LoadFp,
34 Custom0,
35 MiscMem(MiscMemFunction),
36 OpImm(OpImmFunction),
37 AuiPc,
38 OpImm32(OpImm32Function),
39
40 Store(StoreWidth),
41 StoreFp,
42 Custom1,
43 Amo(AmoFunction, AmoWidth),
44 Op(OpFunction),
45 Lui,
46 Op32(Op32Function),
47
48 MAdd,
49 MSub,
50 NMSub,
51 NMAdd,
52 OpFp,
53 Reserved0,
54 Custom2,
55
56 Branch(BranchOperation),
57 JAlr,
58 Reserved1,
59 JAl,
60 System(SystemFunction),
61 Reserved2,
62 Custom3,
63
64 CADDI4SPN,
66 CADDI,
67 CNOP,
68 CFLD,
69 CLW,
70 CLD,
71 CSW,
72 CSD,
73 CADDIW,
74 CLI,
75 CADDI16SP,
76 CLUI,
77 CSRLI,
78 CSRAI,
79 CANDI,
80 CSUB,
81 CXOR,
82 COR,
83 CAND,
84 CSUBW,
85 CADDW,
86 CJ,
87 CBEQZ,
88 CBNEZ,
89 CSLLI,
90 CLWSP,
91 CLDSP,
92 CJR,
93 CMV,
94 CBREAK,
95 CJALR,
96 CADD,
97 CSWSP,
98 CSDSP,
99}
100
101impl Opcode {
102 pub fn new_compressed(base: u16) -> Opcode {
103 let op_low = base & 0b11;
104 let op_high = (base >> 13) & 0b111;
105
106 match (op_high, op_low) {
107 (0b000, 0b00) => Opcode::CADDI4SPN,
108 (0b000, 0b01) => {
109 if (base >> 7) & 0b11111 == 0 {
110 Opcode::CNOP
111 } else {
112 Opcode::CADDI
113 }
114 }
115 (0b001, 0b00) => Opcode::CFLD, (0b010, 0b00) => Opcode::CLW,
117 (0b011, 0b00) => Opcode::CLD,
118 (0b110, 0b00) => Opcode::CSW,
119 (0b111, 0b00) => Opcode::CSD,
120 (0b001, 0b01) => Opcode::CADDIW,
121 (0b010, 0b01) => Opcode::CLI,
122 (0b011, 0b01) => {
123 if (base >> 7) & 0b11111 == 2 {
124 Opcode::CADDI16SP
125 } else {
126 Opcode::CLUI
127 }
128 }
129 (0b100, 0b01) => {
130 let func3 = (base >> 10) & 0b111;
131 let func2 = (base >> 5) & 0b11;
132 match (func3, func2) {
133 (0b000, _) | (0b100, _) => Opcode::CSRLI,
134 (0b001, _) | (0b101, _) => Opcode::CSRAI,
135 (0b010, _) | (0b110, _) => Opcode::CANDI,
136 (0b011, 0b00) => Opcode::CSUB,
137 (0b011, 0b01) => Opcode::CXOR,
138 (0b011, 0b10) => Opcode::COR,
139 (0b011, 0b11) => Opcode::CAND,
140 (0b111, 0b00) => Opcode::CSUBW,
141 (0b111, 0b01) => Opcode::CADDW,
142 _ => todo!(
143 "compressed arithmetic function with func=({:#03b}, {:#02b})",
144 func3,
145 func2
146 ),
147 }
148 }
149 (0b101, 0b01) => Opcode::CJ,
150 (0b110, 0b01) => Opcode::CBEQZ,
151 (0b111, 0b01) => Opcode::CBNEZ,
152 (0b000, 0b10) => Opcode::CSLLI,
153 (0b010, 0b10) => Opcode::CLWSP,
154 (0b011, 0b10) => Opcode::CLDSP,
155 (0b100, 0b10) => {
156 let func12 = (base >> 12) & 0b1;
157 let func11_7 = (base >> 7) & 0b11111;
158 let func6_2 = (base >> 2) & 0b11111;
159
160 match (func12, func11_7, func6_2) {
161 (0b0, _, 0b00000) => Opcode::CJR,
162 (0b0, _, _) => Opcode::CMV,
163 (0b1, 0b0, 0b00000) => unimplemented!("C.EBREAK"),
164 (0b1, _, 0b00000) => Opcode::CJALR,
165 (0b1, _, _) => Opcode::CADD,
166 spec => unimplemented!("compressed opcode 100...10 with func ({:?})", spec),
167 }
168 }
169 (0b110, 0b10) => Opcode::CSWSP,
170 (0b111, 0b10) => Opcode::CSDSP,
171
172 _ => todo!(
173 "compressed instruction with op={:03b}...{:02b} from base={:016b} ({:#04x})",
174 op_high,
175 op_low,
176 base,
177 base
178 ),
179 }
180 }
181
182 pub fn new(base: u16, func3: u8, imm11_0: u16, func5: u8, func7: u8) -> Opcode {
183 let opcode = base & 0b1111111;
184 match opcode {
185 0b0000011 => Opcode::Load(LoadWidth::from_func3(func3)),
186 0b0000111 => Opcode::LoadFp,
187 0b0001011 => unimplemented!("Custom 0"),
188 0b0001111 => Opcode::MiscMem(MiscMemFunction::from_func3(func3)),
189 0b0010011 => Opcode::OpImm(OpImmFunction::from_imm11_0_func3(imm11_0, func3)),
190 0b0010111 => Opcode::AuiPc,
191 0b0011011 => Opcode::OpImm32(OpImm32Function::from_func3_imm(func3, imm11_0)),
192
193 0b0100011 => Opcode::Store(StoreWidth::from_func3(func3)),
194 0b0100111 => Opcode::StoreFp,
195 0b0101011 => unimplemented!("Custom 1"),
196 0b0101111 => Opcode::Amo(AmoFunction::from_func5(func5), AmoWidth::from_func3(func3)),
197 0b0110011 => Opcode::Op(OpFunction::from_func3_func7(func3, func7)),
198 0b0110111 => Opcode::Lui,
199 0b0111011 => Opcode::Op32(Op32Function::from_func3_func7(func3, func7)),
200
201 0b1000011 => Opcode::MAdd,
202 0b1000111 => Opcode::MSub,
203 0b1001011 => Opcode::NMSub,
204 0b1001111 => Opcode::NMAdd,
205 0b1010011 => Opcode::OpFp,
206 0b1010111 => unimplemented!("Reserved 0"),
207 0b1011011 => unimplemented!("Custom 2"),
208
209 0b1100011 => Opcode::Branch(BranchOperation::from_func3(func3)),
210 0b1100111 => Opcode::JAlr,
211 0b1101011 => unimplemented!("Reserved 1"),
212 0b1101111 => Opcode::JAl,
213 0b1110011 => Opcode::System(SystemFunction::from_func3_imm11_0(func3, imm11_0)),
214 0b1110111 => unimplemented!("Reserved 2"),
215 0b1111011 => unimplemented!("Custom 3"),
216
217 _ => panic!("Unknown opcode"),
218 }
219 }
220
221 pub fn opcode_field(&self) -> i32 {
222 match self {
223 Opcode::Load(_) => 0b0000011,
224 Opcode::LoadFp => 0b0000111,
225 Opcode::Custom0 => 0b0001011,
226 Opcode::MiscMem(_) => 0b0001111,
227 Opcode::OpImm(_) => 0b0010011,
228 Opcode::AuiPc => 0b0010111,
229 Opcode::OpImm32(_) => 0b0011011,
230
231 Opcode::Store(_) => 0b0100011,
232 Opcode::StoreFp => 0b0100111,
233 Opcode::Custom1 => 0b0101011,
234 Opcode::Amo(_, _) => 0b0101111,
235 Opcode::Op(_) => 0b0110011,
236 Opcode::Lui => 0b0110111,
237 Opcode::Op32(_) => 0b0111011,
238
239 Opcode::MAdd => 0b1000011,
240 Opcode::MSub => 0b1000111,
241 Opcode::NMSub => 0b1001011,
242 Opcode::NMAdd => 0b1001111,
243 Opcode::OpFp => 0b1010011,
244 Opcode::Reserved0 => 0b1010111,
245 Opcode::Custom2 => 0b1011011,
246
247 Opcode::Branch(_) => 0b1100011,
248 Opcode::JAlr => 0b1100111,
249 Opcode::Reserved1 => 0b1101011,
250 Opcode::JAl => 0b1101111,
251 Opcode::System(_) => 0b1110011,
252 Opcode::Reserved2 => 0b1110111,
253 Opcode::Custom3 => 0b1111011,
254
255 Opcode::CADDI4SPN => 0b00,
256 Opcode::CADDI => 0b01,
257 Opcode::CNOP => 0b01,
258 Opcode::CFLD => 0b00,
259 Opcode::CLW => 0b00,
260 Opcode::CLD => 0b00,
261 Opcode::CSW => 0b00,
262 Opcode::CSD => 0b00,
263 Opcode::CADDIW => 0b01,
264 Opcode::CLI => 0b01,
265 Opcode::CADDI16SP => 0b01,
266 Opcode::CLUI => 0b01,
267 Opcode::CSRLI => 0b01,
268 Opcode::CSRAI => 0b01,
269 Opcode::CANDI => 0b01,
270 Opcode::CSUB => 0b01,
271 Opcode::CXOR => 0b01,
272 Opcode::COR => 0b01,
273 Opcode::CAND => 0b01,
274 Opcode::CSUBW => 0b01,
275 Opcode::CADDW => 0b01,
276 Opcode::CJ => 0b01,
277 Opcode::CBEQZ => 0b01,
278 Opcode::CBNEZ => 0b01,
279 Opcode::CSLLI => 0b10,
280 Opcode::CLWSP => 0b10,
281 Opcode::CLDSP => 0b10,
282 Opcode::CJR => 0b10,
283 Opcode::CMV => 0b10,
284 Opcode::CBREAK => 0b10,
285 Opcode::CJALR => 0b10,
286 Opcode::CADD => 0b10,
287 Opcode::CSWSP => 0b10,
288 Opcode::CSDSP => 0b10,
289 }
290 }
291
292 pub fn funct3_field(&self) -> i32 {
293 match self {
294 Opcode::Load(function) => function.to_func3(),
295 Opcode::OpImm(function) => function.to_func3(),
296 Opcode::Store(function) => function.to_func3(),
297 Opcode::Op(function) => function.to_func3(),
298 Opcode::Branch(function) => function.to_func3(),
299 Opcode::System(_) => 0,
300
301 _ => unimplemented!("opcode {:?} does not have funct3 field", self),
302 }
303 }
304
305 pub fn funct7_field(&self) -> i32 {
306 match self {
307 Opcode::Op(function) => function.to_func7(),
308
309 _ => unimplemented!("opcode {:?} does not have funct7 field", self),
310 }
311 }
312}