1use crate::register::{Register,Register32,Register64,RegisterWidth};
2use crate::variant::{self,Variant};
3use crate::version;
4#[cfg(feature = "ext-csr")]
5use crate::csr::Csr;
6
7pub struct Core<R: Register> {
11 registers: [R; 32],
15
16 pub pc: R,
18
19 #[cfg(feature = "ext-csr")]
21 csr: Csr<R>
22}
23impl<R: Register + Default + Copy + Clone> Core<R> {
24 #[cfg(not(feature = "ext-csr"))]
27 pub fn new(address: R::Unsigned) -> Self {
28 Self {
29 registers: [Default::default(); 32],
30 pc: R::from_unsigned(address)
31 }
32 }
33
34 #[cfg(feature = "ext-csr")]
38 pub fn new(address: R::Unsigned, hart: R::Unsigned) -> Self {
39 Self {
40 registers: [Default::default(); 32],
41 pc: R::from_unsigned(address),
42 csr: Csr::new(hart, address)
43 }
44 }
45
46 pub fn step(&mut self) {
48 self.pc = self.pc.add_unsigned(R::zero_extended_byte(4))
49 }
50
51 #[inline(always)]
55 pub fn get(&self, index: usize) -> R {
56 self.registers[index]
57 }
58
59 #[inline(always)]
63 pub fn set(&mut self, index: usize, register: R) {
64 if index > 0 {
65 self.registers[index] = register
66 }
67 }
68
69 #[cfg(feature = "ext-csr")]
71 pub fn get_csr(&self, index: usize) -> Result<R, Exception> {
72 match index {
73 0x300 => unimplemented!(),
75 0x301 => {
77 const I: u8 = 1 << 7;
78
79 let isa0 = I;
80 let isa1 = 0;
81 let isa2 = 0;
82 let isa3 = 0;
83
84 const MXLEN32: u8 = 1;
85 const MXLEN64: u8 = 2;
86 const _MXLEN128: u8 = 3;
87 Ok(
88 match R::WIDTH {
89 RegisterWidth::Bits32 => R::zero_extended_word([isa0, isa1, isa2, isa3 | MXLEN32 << 6]),
90 RegisterWidth::Bits64 => R::zero_extended_double([isa0, isa1, isa2, isa3, 0, 0, 0, MXLEN64 << 6]),
91 }
92 )
93 },
94 0x302 => Ok(self.csr.medeleg),
96 0x303 => Ok(self.csr.mideleg),
98 0x304 => Ok(self.csr.mie),
100 0x305 => Ok(self.csr.mtvec),
102 0x306 => Ok(R::zero_extended_word(self.csr.mcounteren.word())),
104
105 0x340 => Ok(self.csr.mscratch),
107 0x341 => Ok(self.csr.mepc),
109 0x342 => Ok(self.csr.mcause),
111 0x343 => Ok(self.csr.mtval),
113 0x344 => Ok(self.csr.mip),
115
116 0xB00 if R::WIDTH != RegisterWidth::Bits32 => Ok(R::zero_extended_double(self.csr.mcycle.double())),
118 0xB00 if R::WIDTH == RegisterWidth::Bits32 => Ok(R::zero_extended_word((self.csr.mcycle.split().0).0)),
119 0xB80 if R::WIDTH == RegisterWidth::Bits32 => Ok(R::zero_extended_word((self.csr.mcycle.split().1).0)),
120 0xB02 if R::WIDTH != RegisterWidth::Bits32 => Ok(R::zero_extended_double(self.csr.mcycle.double())),
122 0xB02 if R::WIDTH == RegisterWidth::Bits32 => Ok(R::zero_extended_word((self.csr.mcycle.split().0).0)),
123 0xB82 if R::WIDTH == RegisterWidth::Bits32 => Ok(R::zero_extended_word((self.csr.mcycle.split().1).0)),
124 0xB03..=0xB1F => Ok(R::default()),
126 0xB83..=0xB9F if R::WIDTH == RegisterWidth::Bits32 => Ok(R::default()),
127 0xB23..=0xB3F => Ok(R::default()),
129
130 0xF11 => Ok(R::default()),
133 0xF12 => Ok(R::default()),
136 0xF13 => Ok(R::zero_extended_word([version::PATCH, version::MINOR, version::MAJOR, 0])),
139 0xF14 => Ok(self.csr.mhartid),
141 _ => Err(Exception::IllegalInstruction)
142 }
143 }
144
145 #[cfg(feature = "ext-csr")]
147 pub fn set_csr(&mut self, index: usize, value: R) {
148 match index {
149 0x304 => {
151 self.csr.mie = value.and(R::zero_extended_half([!0x44, !0xF4]))
153 },
154 0x344 => {
156 self.csr.mip = value.and(R::zero_extended_half([!0x44, !0xF4]))
158 },
159 _ => ()
160 }
161 }
162
163 #[allow(clippy::cognitive_complexity)]
165 pub fn execute(&mut self, mmu: &mut dyn Mmu<R>) -> Result<(), Exception> {
166 let instruction = mmu.fetch(self.pc);
167 let opcode = instruction[0] & 0x7F;
168 let funct3 = (instruction[1] & 0x70) >> 4;
169 let funct7 = (instruction[3] & 0xFE) >> 1;
170
171 #[cfg(feature = "ext-csr")]
173 {self.csr.mcycle = self.csr.mcycle.add_unsigned(Register64::zero_extended_byte(1))}
174
175 #[allow(clippy::unreadable_literal)]
176 match (opcode, funct3, funct7) {
177 (0b0110011, 0b000, 0b0000000) => {
179 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
180 self.set(destination, self.get(source1).add_unsigned(self.get(source2)));
181 Ok(self.step())
182 },
183 (0b0111011, 0b000, 0b0000000) => {
185 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
186 self.set(destination, R::sign_extended_word(Register32(self.get(source1).word()).add_unsigned(Register32(self.get(source2).word())).word()));
187 Ok(self.step())
188 },
189 (0b0110011, 0b000, 0b0100000) => {
191 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
192 self.set(destination, self.get(source1).sub_unsigned(self.get(source2)));
193 Ok(self.step())
194 },
195 (0b0111011, 0b000, 0b0100000) => {
197 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
198 self.set(destination, R::sign_extended_word(Register32(self.get(source1).word()).sub_unsigned(Register32(self.get(source2).word())).word()));
199 Ok(self.step())
200 },
201 (0b0110011, 0b010, 0b0000000) => {
203 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
204 self.set(destination, if self.get(source1).lt_signed(self.get(source2)) { R::zero_extended_byte(1) } else { R::zero_extended_byte(0) });
205 Ok(self.step())
206 },
207 (0b0110011, 0b011, 0b0000000) => {
209 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
210 self.set(destination, if self.get(source1).lt_unsigned(self.get(source2)) { R::zero_extended_byte(1) } else { R::zero_extended_byte(0) });
211 Ok(self.step())
212 },
213 (0b0010011, 0b000, _) => {
215 let variant::I { destination, source, immediate } = Variant::decode(instruction);
216 self.set(destination, self.get(source).add_signed(immediate));
217 Ok(self.step())
218 },
219 (0b0011011, 0b000, _) => {
221 let variant::I { destination, source, immediate } = Variant::decode(instruction);
222 self.set(destination, R::sign_extended_word(Register32(self.get(source).word()).add_signed(immediate).word()));
223 Ok(self.step())
224 },
225 (0b0010011, 0b010, _) => {
227 let variant::I { destination, source, immediate } = Variant::decode(instruction);
228 self.set(destination, if self.get(source).lt_signed(immediate) { R::zero_extended_byte(1) } else { R::zero_extended_byte(0) });
229 Ok(self.step())
230 },
231 (0b0010011, 0b011, _) => {
233 let variant::I { destination, source, immediate } = Variant::decode(instruction);
234 self.set(destination, if self.get(source).lt_unsigned(immediate) { R::zero_extended_byte(1) } else { R::zero_extended_byte(0) });
235 Ok(self.step())
236 },
237
238 (0b0110011, 0b100, 0b0000000) => {
240 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
241 self.set(destination, self.get(source1).xor(self.get(source2)));
242 Ok(self.step())
243 },
244 (0b0110011, 0b110, 0b0000000) => {
246 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
247 self.set(destination, self.get(source1).or(self.get(source2)));
248 Ok(self.step())
249 },
250 (0b0110011, 0b111, 0b0000000) => {
252 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
253 self.set(destination, self.get(source1).and(self.get(source2)));
254 Ok(self.step())
255 },
256 (0b0010011, 0b100, _) => {
258 let variant::I { destination, source, immediate } = Variant::decode(instruction);
259 self.set(destination, self.get(source).xor(immediate));
260 Ok(self.step())
261 },
262 (0b0010011, 0b110, _) => {
264 let variant::I { destination, source, immediate } = Variant::decode(instruction);
265 self.set(destination, self.get(source).or(immediate));
266 Ok(self.step())
267 },
268 (0b0010011, 0b111, _) => {
270 let variant::I { destination, source, immediate } = Variant::decode(instruction);
271 self.set(destination, self.get(source).and(immediate));
272 Ok(self.step())
273 },
274
275 (0b0110011, 0b001, 0b0000000) => {
277 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
278 self.set(destination, self.get(source1).shl(self.get(source2)));
279 Ok(self.step())
280 },
281 (0b0111011, 0b001, 0b0000000) if R::WIDTH != RegisterWidth::Bits32 => {
283 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
284 self.set(destination, R::sign_extended_word(Register32(self.get(source1).word()).shl(Register32(self.get(source2).word())).word()));
285 Ok(self.step())
286 },
287 (0b0110011, 0b101, 0b0000000) => {
289 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
290 self.set(destination, self.get(source1).shr(self.get(source2)));
291 Ok(self.step())
292 },
293 (0b0111011, 0b101, 0b0000000) if R::WIDTH != RegisterWidth::Bits32 => {
295 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
296 self.set(destination, R::sign_extended_word(Register32(self.get(source1).word()).shr(Register32(self.get(source2).word())).word()));
297 Ok(self.step())
298 },
299 (0b0110011, 0b101, 0b0100000) => {
301 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
302 self.set(destination, self.get(source1).sha(self.get(source2)));
303 Ok(self.step())
304 },
305 (0b0111011, 0b101, 0b0100000) if R::WIDTH != RegisterWidth::Bits32 => {
307 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
308 self.set(destination, R::sign_extended_word(Register32(self.get(source1).word()).sha(Register32(self.get(source2).word())).word()));
309 Ok(self.step())
310 },
311 (0b0010011, 0b001, _) => {
313 let variant::I::<R> { destination, source, immediate } = Variant::decode(instruction);
314 self.set(destination, self.get(source).shl(immediate.and(R::zero_extended_byte(0x0E))));
315 Ok(self.step())
316 },
317 (0b0011011, 0b001, _) if R::WIDTH != RegisterWidth::Bits32 => {
319 let variant::I::<R> { destination, source, immediate } = Variant::decode(instruction);
320 if immediate.byte() & 0x20 != 0 {
321 Err(Exception::ShiftWordReservedBit)
322 } else {
323 self.set(destination, R::sign_extended_word(Register32(self.get(source).word()).shl(Register32(immediate.word()).and(Register32::zero_extended_byte(0x0E))).word()));
324 Ok(self.step())
325 }
326 },
327 (0b0010011, 0b101, _) if instruction[3] & 0x40 == 0 => {
329 let variant::I::<R> { destination, source, immediate } = Variant::decode(instruction);
330 self.set(destination, self.get(source).shr(immediate.and(R::zero_extended_byte(0x0E))));
331 Ok(self.step())
332 },
333 (0b0011011, 0b101, _) if instruction[3] & 0x40 == 0 && R::WIDTH != RegisterWidth::Bits32 => {
335 let variant::I::<R> { destination, source, immediate } = Variant::decode(instruction);
336 if immediate.byte() & 0x20 != 0 {
337 Err(Exception::ShiftWordReservedBit)
338 } else {
339 self.set(destination, R::sign_extended_word(Register32(self.get(source).word()).shr(Register32(immediate.word()).and(Register32::zero_extended_byte(0x0E))).word()));
340 Ok(self.step())
341 }
342 },
343 (0b0010011, 0b101, _) if instruction[3] & 0x40 != 0 => {
345 let variant::I::<R> { destination, source, immediate } = Variant::decode(instruction);
346 self.set(destination, self.get(source).sha(immediate.and(R::zero_extended_byte(0x0E))));
347 Ok(self.step())
348 },
349 (0b0011011, 0b101, _) if instruction[3] & 0x40 != 0 && R::WIDTH != RegisterWidth::Bits32 => {
351 let variant::I::<R> { destination, source, immediate } = Variant::decode(instruction);
352 if immediate.byte() & 0x20 != 0 {
353 Err(Exception::ShiftWordReservedBit)
354 } else {
355 self.set(destination, R::sign_extended_word(Register32(self.get(source).word()).sha(Register32(immediate.word()).and(Register32::zero_extended_byte(0x0E))).word()));
356 Ok(self.step())
357 }
358 },
359
360 (0b0110111, _, _) => {
362 let variant::U { destination, immediate } = Variant::decode(instruction);
363 self.set(destination, immediate);
364 Ok(self.step())
365 },
366 (0b0010111, _, _) => {
368 let variant::U { destination, immediate } = Variant::decode(instruction);
369 self.set(destination, self.pc.add_signed(immediate));
370 Ok(self.step())
371 },
372
373 (0b0000011, 0b000, _) => {
375 let variant::I { destination, source, immediate } = Variant::decode(instruction);
376 self.set(destination, R::sign_extended_byte(mmu.get(self.get(source).add_signed(immediate).unsigned())));
377 Ok(self.step())
378 },
379 (0b0000011, 0b100, _) => {
381 let variant::I { destination, source, immediate } = Variant::decode(instruction);
382 self.set(destination, R::zero_extended_byte(mmu.get(self.get(source).add_signed(immediate).unsigned())));
383 Ok(self.step())
384 },
385 (0b0000011, 0b001, _) => {
387 let variant::I { destination, source, immediate } = Variant::decode(instruction);
388 let address = self.get(source).add_signed(immediate);
389 self.set(destination, R::sign_extended_half([mmu.get(address.unsigned()), mmu.get(address.append(1))]));
390 Ok(self.step())
391 },
392 (0b0000011, 0b101, _) => {
394 let variant::I { destination, source, immediate } = Variant::decode(instruction);
395 let address = self.get(source).add_signed(immediate);
396 self.set(destination, R::zero_extended_half([mmu.get(address.unsigned()), mmu.get(address.append(1))]));
397 Ok(self.step())
398 },
399 (0b0000011, 0b010, _) => {
401 let variant::I { destination, source, immediate } = Variant::decode(instruction);
402 let address = self.get(source).add_signed(immediate);
403 self.set(destination, R::sign_extended_word([
404 mmu.get(address.unsigned()),
405 mmu.get(address.append(1)),
406 mmu.get(address.append(2)),
407 mmu.get(address.append(3))
408 ]));
409 Ok(self.step())
410 },
411 (0b0000011, 0b110, _) if R::WIDTH != RegisterWidth::Bits32 => {
413 let variant::I { destination, source, immediate } = Variant::decode(instruction);
414 let address = self.get(source).add_signed(immediate);
415 self.set(destination, R::zero_extended_word([
416 mmu.get(address.unsigned()),
417 mmu.get(address.append(1)),
418 mmu.get(address.append(2)),
419 mmu.get(address.append(3))
420 ]));
421 Ok(self.step())
422 },
423 (0b0000011, 0b011, _) => {
425 let variant::I { destination, source, immediate } = Variant::decode(instruction);
426 let address = self.get(source).add_signed(immediate);
427 self.set(destination, R::sign_extended_double([
428 mmu.get(address.unsigned()),
429 mmu.get(address.append(1)),
430 mmu.get(address.append(2)),
431 mmu.get(address.append(3)),
432 mmu.get(address.append(4)),
433 mmu.get(address.append(5)),
434 mmu.get(address.append(6)),
435 mmu.get(address.append(7))
436 ]));
437 Ok(self.step())
438 },
439
440 (0b0100011, 0b000, _) => {
442 let variant::S { source1, source2, immediate } = Variant::decode(instruction);
443 let address = self.get(source1).add_signed(immediate);
444 mmu.set(address.unsigned(), self.get(source2).byte());
445 Ok(self.step())
446 },
447 (0b0100011, 0b001, _) => {
449 let variant::S { source1, source2, immediate } = Variant::decode(instruction);
450 let address = self.get(source1).add_signed(immediate);
451 let half = self.get(source2).half();
452 mmu.set(address.unsigned(), half[0]);
453 mmu.set(address.append(1), half[1]);
454 Ok(self.step())
455 },
456 (0b0100011, 0b010, _) => {
458 let variant::S { source1, source2, immediate } = Variant::decode(instruction);
459 let address = self.get(source1).add_signed(immediate);
460 let word = self.get(source2).word();
461 mmu.set(address.unsigned(), word[0]);
462 mmu.set(address.append(1), word[1]);
463 mmu.set(address.append(2), word[2]);
464 mmu.set(address.append(3), word[3]);
465 Ok(self.step())
466 },
467
468 (0b1101111, _, _) => {
470 let variant::J { destination, immediate } = Variant::decode(instruction);
471 self.set(destination, self.pc.add_unsigned(R::zero_extended_byte(4)));
472 Ok(self.pc = self.pc.add_signed(immediate))
473 },
474 (0b1100111, 0b000, _) => {
476 let variant::I { destination, source, immediate } = Variant::decode(instruction);
477 let to_set = self.get(source).add_signed(immediate);
478 self.set(destination, self.pc.add_unsigned(R::zero_extended_byte(4)));
479 Ok(self.pc = to_set)
480 },
481
482 (0b1100011, 0b000, _) => {
484 let variant::B { source1, source2, immediate } = Variant::decode(instruction);
485 Ok(if self.get(source1).eq(self.get(source2)) { self.pc = self.pc.add_signed(immediate) } else { self.step() })
486 },
487 (0b1100011, 0b001, _) => {
489 let variant::B { source1, source2, immediate } = Variant::decode(instruction);
490 Ok(if self.get(source1).neq(self.get(source2)) { self.pc = self.pc.add_signed(immediate) } else { self.step() })
491 },
492 (0b1100011, 0b100, _) => {
494 let variant::B { source1, source2, immediate } = Variant::decode(instruction);
495 Ok(if self.get(source1).lt_signed(self.get(source2)) { self.pc = self.pc.add_signed(immediate) } else { self.step() })
496 },
497 (0b1100011, 0b110, _) => {
499 let variant::B { source1, source2, immediate } = Variant::decode(instruction);
500 Ok(if self.get(source1).lt_unsigned(self.get(source2)) { self.pc = self.pc.add_signed(immediate) } else { self.step() })
501 },
502 (0b1100011, 0b101, _) => {
504 let variant::B { source1, source2, immediate } = Variant::decode(instruction);
505 Ok(if self.get(source1).gte_signed(self.get(source2)) { self.pc = self.pc.add_signed(immediate) } else { self.step() })
506 },
507 (0b1100011, 0b111, _) => {
509 let variant::B { source1, source2, immediate } = Variant::decode(instruction);
510 Ok(if self.get(source1).gte_unsigned(self.get(source2)) { self.pc = self.pc.add_signed(immediate) } else { self.step() })
511 },
512
513 #[cfg(feature = "ext-m")]
516 (0b0110011, 0b000, 0b0000001) => {
517 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
518 Ok(self.set(destination, self.get(source1).mul(self.get(source2))))
519 },
520 #[cfg(feature = "ext-m")]
522 (0b0110011, 0b001, 0b0000001) => {
523 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
524 Ok(self.set(destination, self.get(source1).mulh(self.get(source2))))
525 },
526 #[cfg(feature = "ext-m")]
528 (0b0110011, 0b010, 0b0000001) => {
529 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
530 Ok(self.set(destination, self.get(source1).mulhsu(self.get(source2))))
531 },
532 #[cfg(feature = "ext-m")]
534 (0b0110011, 0b011, 0b0000001) => {
535 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
536 Ok(self.set(destination, self.get(source1).mulhu(self.get(source2))))
537 },
538 #[cfg(feature = "ext-m")]
540 (0b0111011, 0b000, 0b0000001) if R::WIDTH == RegisterWidth::Bits64 => {
541 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
542 Ok(self.set(destination, R::sign_extended_word(Register32(self.get(source1).word()).mul(Register32(self.get(source2).word())).word())))
543 },
544 #[cfg(feature = "ext-m")]
546 (0b0110011, 0b100, 0b0000001) => {
547 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
548 Ok(self.set(destination, self.get(source1).div(self.get(source2))))
549 },
550 #[cfg(feature = "ext-m")]
552 (0b0110011, 0b101, 0b0000001) => {
553 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
554 Ok(self.set(destination, self.get(source1).divu(self.get(source2))))
555 },
556 #[cfg(feature = "ext-m")]
558 (0b0111011, 0b100, 0b0000001) => {
559 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
560 Ok(self.set(destination, R::sign_extended_word(Register32(self.get(source1).word()).div(Register32(self.get(source2).word())).word())))
561 },
562 #[cfg(feature = "ext-m")]
564 (0b0111011, 0b101, 0b0000001) => {
565 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
566 Ok(self.set(destination, R::sign_extended_word(Register32(self.get(source1).word()).divu(Register32(self.get(source2).word())).word())))
567 },
568 #[cfg(feature = "ext-m")]
570 (0b0110011, 0b110, 0b0000001) => {
571 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
572 Ok(self.set(destination, self.get(source1).rem(self.get(source2))))
573 },
574 #[cfg(feature = "ext-m")]
576 (0b0110011, 0b111, 0b0000001) => {
577 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
578 Ok(self.set(destination, self.get(source1).remu(self.get(source2))))
579 },
580 #[cfg(feature = "ext-m")]
582 (0b0111011, 0b110, 0b0000001) => {
583 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
584 Ok(self.set(destination, R::sign_extended_word(Register32(self.get(source1).word()).rem(Register32(self.get(source2).word())).word())))
585 },
586 #[cfg(feature = "ext-m")]
588 (0b0111011, 0b111, 0b0000001) => {
589 let variant::R { destination, source1, source2 } = Variant::decode(instruction);
590 Ok(self.set(destination, R::sign_extended_word(Register32(self.get(source1).word()).remu(Register32(self.get(source2).word())).word())))
591 },
592
593 #[cfg(feature = "ext-csr")]
596 (0b1110011, 0b001, _) => {
597 let variant::C { destination, source, csr } = Variant::decode(instruction);
598 Ok(if destination != 0 {
599 let temporary = self.get_csr(csr).expect("TODO: Exception signaling");
600 self.set_csr(csr, self.get(source));
601 self.set(destination, temporary)
602 } else {
603 self.set_csr(csr, self.get(source))
604 })
605 },
606 #[cfg(feature = "ext-csr")]
608 (0b1110011, 0b010, _) => {
609 let variant::C { destination, source, csr } = Variant::decode(instruction);
610 let temporary = self.get_csr(csr).expect("TODO: Exception signaling");
611 Ok(if source != 0 {
612 self.set_csr(csr, temporary.or(self.get(source)));
614 self.set(destination, temporary)
615 } else {
616 self.set(destination, temporary)
617 })
618 },
619 #[cfg(feature = "ext-csr")]
621 (0b1110011, 0b011, _) => {
622 let variant::C { destination, source, csr } = Variant::decode(instruction);
623 let temporary = self.get_csr(csr).expect("TODO: Exception signaling");
624 Ok(if source != 0 {
625 self.set_csr(csr, temporary.and(self.get(source).not()));
627 self.set(destination, temporary)
628 } else {
629 self.set(destination, temporary)
630 })
631 },
632 #[cfg(feature = "ext-csr")]
634 (0b1110011, 0b101, _) => {
635 let variant::C { destination, source, csr } = Variant::decode(instruction);
636 let immediate = R::zero_extended_byte(source as u8);
637 Ok(if destination != 0 {
638 let temporary = self.get_csr(csr).expect("TODO: Exception signaling");
639 self.set_csr(csr, immediate);
640 self.set(destination, temporary)
641 } else {
642 self.set_csr(csr, immediate)
643 })
644 },
645 #[cfg(feature = "ext-csr")]
647 (0b1110011, 0b110, _) => {
648 let variant::C { destination, source, csr } = Variant::decode(instruction);
649 let temporary = self.get_csr(csr).expect("TODO: Exception signaling");
650 Ok(if source != 0 {
651 self.set_csr(csr, temporary.or(R::zero_extended_byte(source as u8)));
653 self.set(destination, temporary)
654 } else {
655 self.set(destination, temporary)
656 })
657 },
658 #[cfg(feature = "ext-csr")]
660 (0b1110011, 0b111, _) => {
661 let variant::C { destination, source, csr } = Variant::decode(instruction);
662 let temporary = self.get_csr(csr).expect("TODO: Exception signaling");
663 Ok(if source != 0 {
664 self.set_csr(csr, temporary.and(R::zero_extended_byte(source as u8).not()));
666 self.set(destination, temporary)
667 } else {
668 self.set(destination, temporary)
669 })
670 },
671 (opcode, funct3, funct7) => Err(Exception::UnknownInstruction(opcode, funct3, funct7))
672 }
673 }
674}
675
676pub trait Mmu<R: Register> {
679 fn get(&self, address: R::Unsigned) -> u8;
681 fn set(&mut self, address: R::Unsigned, value: u8);
683 fn fetch(&self, address: R) -> [u8; 4] {
685 [
686 self.get(address.unsigned()),
687 self.get(address.append(1)),
688 self.get(address.append(2)),
689 self.get(address.append(3))
690 ]
691 }
692}
693
694#[derive(Copy, Clone, PartialEq, Eq)]
696pub enum Exception {
697 IllegalInstruction,
698 UnknownInstruction(u8, u8, u8),
699 ShiftWordReservedBit
700}
701impl std::fmt::Debug for Exception {
702 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
703 match self {
704 Self::IllegalInstruction => write!(f, "Illegal value in instruction"),
705 Self::UnknownInstruction(opcode, funct3, funct7) => write!(f, "UnknownInstruction(opcode: {:#b}, funct3: {:#b}, funct7: {:#b})", opcode, funct3, funct7),
706 Self::ShiftWordReservedBit => write!(f, "Shift *W instruction was used with immediate[5] set. This bit is reserved.")
707 }
708 }
709}