Skip to main content

rysk_core/
system.rs

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
7/// A single RISCV core.
8/// Includes a single program counter and 32 registers.
9/// Const generics will allow support of the E extensions for 16 registers.
10pub struct Core<R: Register> {
11    /// The 32 general-purpose registers.
12    /// Although all registers are general purpose in RISCV, their usage is still dictated by the standard calling convention.
13    /// Register 0 always has a value of 0.
14    registers: [R; 32],
15
16    /// The program counter
17    pub pc: R,
18
19    /// CSR registers
20    #[cfg(feature = "ext-csr")]
21    csr: Csr<R>
22}
23impl<R: Register + Default + Copy + Clone> Core<R> {
24    /// Creates a new core starting execution at the given address.
25    /// address must be aligned to 4 bytes else a panic will occur during execution.
26    #[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    /// Creates a new core starting execution at the given address with the given hart ID.
35    /// Hart ID's must be unique to ensure correct program behaviour. There must be a hart with ID 0 on a given system.
36    /// `address` must be aligned to 4 bytes else a panic will occur during execution.
37    #[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    /// Increments the program counter by the instruction size of 4 bytes
47    pub fn step(&mut self) {
48        self.pc = self.pc.add_unsigned(R::zero_extended_byte(4))
49    }
50
51    /// Get the register `x{index}`
52    /// # Safety
53    /// A panic will occur if index is larger than 31
54    #[inline(always)]
55    pub fn get(&self, index: usize) -> R {
56        self.registers[index]
57    }
58
59    /// Set register `x{index}` to be equal to `register`
60    /// # Safety
61    /// A panic will occur if index is larger than 31
62    #[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    /// Get a value from a CSR. May have side-effects
70    #[cfg(feature = "ext-csr")]
71    pub fn get_csr(&self, index: usize) -> Result<R, Exception> {
72        match index {
73            // mstatus
74            0x300 => unimplemented!(),
75            // misa
76            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            // medeleg
95            0x302 => Ok(self.csr.medeleg),
96            // mideleg
97            0x303 => Ok(self.csr.mideleg),
98            // mie
99            0x304 => Ok(self.csr.mie),
100            // mtvec
101            0x305 => Ok(self.csr.mtvec),
102            // mcounteren
103            0x306 => Ok(R::zero_extended_word(self.csr.mcounteren.word())),
104
105            // mscratch
106            0x340 => Ok(self.csr.mscratch),
107            // mepc
108            0x341 => Ok(self.csr.mepc),
109            // mcause
110            0x342 => Ok(self.csr.mcause),
111            // mtval
112            0x343 => Ok(self.csr.mtval),
113            // mip
114            0x344 => Ok(self.csr.mip),
115
116            // mcycle and mcycleh
117            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            // minstret - Currently the same as mcycle
121            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            // Unused performance counters
125            0xB03..=0xB1F => Ok(R::default()),
126            0xB83..=0xB9F if R::WIDTH == RegisterWidth::Bits32 => Ok(R::default()),
127            // Unused performance event selectors
128            0xB23..=0xB3F => Ok(R::default()),
129
130            // mvendorid
131            // Requires a JEDEC vendor ID
132            0xF11 => Ok(R::default()),
133            // marchid
134            // In the future an Architecture ID shall be requested
135            0xF12 => Ok(R::default()),
136            // mimpid
137            // The version of rysk-core
138            0xF13 => Ok(R::zero_extended_word([version::PATCH, version::MINOR, version::MAJOR, 0])),
139            // mhartid
140            0xF14 => Ok(self.csr.mhartid),
141            _ => Err(Exception::IllegalInstruction)
142        }
143    }
144
145    /// Set a CSR to the specified value with program-defined access. May have side-effects
146    #[cfg(feature = "ext-csr")]
147    pub fn set_csr(&mut self, index: usize, value: R) {
148        match index {
149            // mie
150            0x304 => {
151                // WPRI fields must be hardwired to zero
152                self.csr.mie = value.and(R::zero_extended_half([!0x44, !0xF4]))
153            },
154            // mip
155            0x344 => {
156                // WPRI fields must be hardwired to zero
157                self.csr.mip = value.and(R::zero_extended_half([!0x44, !0xF4]))
158            },
159            _ => ()
160        }
161    }
162
163    /// Decode and execute an instruction
164    #[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        // Increment the cycle counter
172        #[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            // ADD
178            (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            // ADDW
184            (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            // SUB
190            (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            // SUBW
196            (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            // SLT
202            (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            // SLTU
208            (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            // ADDI
214            (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            // ADDIW
220            (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            // SLTI
226            (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            // SLTIU
232            (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            // XOR
239            (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            // OR
245            (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            // AND
251            (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            // XORI
257            (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            // ORI
263            (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            // ANDI
269            (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            // SLL
276            (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            // SLLW
282            (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            // SRL
288            (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            // SRLW
294            (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            // SRA
300            (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            // SRAW
306            (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            // SLLI
312            (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            // SLLIW
318            (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            // SRLI
328            (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            // SRLIW
334            (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            // SRAI
344            (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            // SRAIW
350            (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            // LUI
361            (0b0110111, _, _) => {
362                let variant::U { destination, immediate } = Variant::decode(instruction);
363                self.set(destination, immediate);
364                Ok(self.step())
365            },
366            // AUIPC
367            (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            // LB
374            (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            // LBU
380            (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            // LH
386            (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            // LHU
393            (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            // LW
400            (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            // LWU
412            (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            // LD
424            (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            // SB
441            (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            // SH
448            (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            // SW
457            (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            // JAL
469            (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            // JALR
475            (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            // BEQ
483            (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            // BNE
488            (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            // BLT
493            (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            // BLTU
498            (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            // BGE
503            (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            // BGEU
508            (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            // M Extension
514            // MUL
515            #[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            // MULH
521            #[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            // MULHSU
527            #[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            // MULHU
533            #[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            // MULW
539            #[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            // DIV
545            #[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            // DIVU
551            #[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            // DIVW
557            #[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            // DIVUW
563            #[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            // REM
569            #[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            // REMU
575            #[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            // REMW
581            #[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            // REMUW
587            #[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            // Zicsr Extension
594            // CSRRW
595            #[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            // CSRRS
607            #[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                    // Source is a bitmask which sets bits in the csr
613                    self.set_csr(csr, temporary.or(self.get(source)));
614                    self.set(destination, temporary)
615                } else {
616                    self.set(destination, temporary)
617                })
618            },
619            // CSRRC
620            #[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                    // Source is a bitmask which clears bits in the csr
626                    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            // CSRRWI
633            #[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            // CSRRSI
646            #[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                    // Source is a bitmask which sets bits in the csr
652                    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            // CSRRCI
659            #[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                    // Source is a bitmask which clears bits in the csr
665                    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
676/// A Memory Management Unit (MMU) handles memory accesses on the system.
677/// Devices and memory regions other than working memory (ie. RAM) may be mapped by way of the MMU.
678pub trait Mmu<R: Register> {
679    /// Get the byte at the given address
680    fn get(&self, address: R::Unsigned) -> u8;
681    /// Set the byte at the given address
682    fn set(&mut self, address: R::Unsigned, value: u8);
683    /// Fetch an instruction to execute
684    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/// An exception thrown by a hart during instruction decoding and execution
695#[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}