monistode_emulator/
risc_processor.rs

1use monistode_binutils::{Architecture, Executable};
2
3use crate::tightly_packed_array;
4
5use super::{
6    arithmetic,
7    common::{Processor, ProcessorContinue},
8    flag_register::{implement_flag_register, FlagRegister, ProcessorFlags},
9    memory::{two_byte_memory, Memory, TwoByteMemory},
10    stack::{two_byte_stack, Stack, TwoByteStack},
11};
12use num_derive::FromPrimitive;
13use num_traits::FromPrimitive;
14
15#[derive(Debug, FromPrimitive)]
16enum Opcode {
17    Halt = 0b00000,
18    Load = 0b000001,
19    Store = 0b000010,
20    MovRegImm = 0b000110,
21    MovRegReg = 0b000101,
22    Push = 0b101000,
23    Pop = 0b101001,
24    Add = 0b000011,
25    Addc = 0b100100,
26    Sub = 0b000100,
27    Mul = 0b001010,
28    Div = 0b001011,
29    And = 0b001100,
30    Or = 0b001101,
31    Xor = 0b001110,
32    Not = 0b001111,
33    Lsh = 0b010000,
34    Rsh = 0b010001,
35    CallAddr = 0b010010,
36    CallRegAddr = 0b010011,
37    Ret = 0b010100,
38    CmpRegReg = 0b010101,
39    CmpRegImm = 0b010110,
40    TestRegReg = 0b010111,
41    TestRegImm = 0b011000,
42    JmpAddr = 0b011001,
43    JmpReg = 0b011010,
44    Je = 0b001000,
45    Jne = 0b011011,
46    Jg = 0b011100,
47    Jge = 0b011101,
48    Jl = 0b011110,
49    Jle = 0b011111,
50    In = 0b100000,
51    OutImmImm = 0b100001,
52    OutImmReg = 0b100010,
53    Nop = 0b100011,
54}
55
56macro_rules! with_registers {
57    ($processor:ident, $args_head:ident, $op:expr) => {{
58        let next_byte = $processor.next();
59        // I'm not gonna do the checks for valid padding
60        let register_3 = (next_byte >> 1) & 0b111;
61        let register_2 = (next_byte >> 4) & 0b111;
62        let register_1 = (next_byte >> 7) & 0b1 | $args_head << 1;
63        $op(register_1, register_2, register_3)
64    }};
65}
66
67macro_rules! with_immediate {
68    ($processor: ident, $args_head:ident, $op:expr) => {{
69        let mut immediate = ($args_head as u16) << 14;
70        immediate = immediate | ($processor.next() as u16) << 6;
71        immediate = immediate | ($processor.next() as u16) >> 2;
72        $op(immediate)
73    }};
74}
75
76macro_rules! with_two_immediates {
77    ($processor: ident, $args_head:ident, $op:expr) => {{
78        let mut immediate_1 = ($args_head as u16) << 14;
79        immediate_1 = immediate_1 | ($processor.next() as u16) << 6;
80        let intersecting_byte = $processor.next();
81        immediate_1 = immediate_1 | (intersecting_byte as u16) >> 2;
82        let mut immediate_2 = (intersecting_byte as u16) << 14;
83        immediate_2 = immediate_2 | ($processor.next() as u16) << 6;
84        immediate_2 = immediate_2 | ($processor.next() as u16) >> 2;
85        $op(immediate_1, immediate_2)
86    }};
87}
88
89macro_rules! with_immediate_and_register {
90    ($processor: ident, $args_head:ident, $op:expr) => {{
91        let mut immediate = ($args_head as u16) << 14;
92        immediate = immediate | ($processor.next() as u16) << 6;
93        let intersecting_byte = $processor.next();
94        immediate = immediate | (intersecting_byte as u16) >> 2;
95        let mut register = (intersecting_byte << 1) & 0b110;
96        register = register | ($processor.next() >> 7) & 0b1;
97        $op(immediate, register)
98    }};
99}
100
101macro_rules! with_reg_and_immediate {
102    ($processor: ident, $args_head:ident, $op:expr) => {{
103        with_registers!(
104            $processor,
105            $args_head,
106            |register_1, register_2, register_3| {
107                let mut immediate = ($processor.next() as u16) << 8;
108                immediate = immediate | ($processor.next() as u16);
109                $op(register_1, register_2, register_3, immediate)
110            }
111        )
112    }};
113}
114
115macro_rules! unary_arithmetic {
116    ($processor:ident, $args_head:ident, $op:expr) => {{
117        with_registers!($processor, $args_head, |register_1, register_2, _| {
118            let Some(value_2) = $processor.get_register_value(register_2) else {
119                return ProcessorContinue::Error;
120            };
121            let result = $op(&mut $processor.registers.fr, value_2);
122            $processor.output_into_register(register_1, result)
123        })
124    }};
125}
126
127macro_rules! arithmetic {
128    ($processor:ident, $args_head:ident, $op:expr) => {{
129        with_registers!(
130            $processor,
131            $args_head,
132            |register_1, register_2, register_3| {
133                let Some(value_2) = $processor.get_register_value(register_2) else {
134                    return ProcessorContinue::Error;
135                };
136                let Some(value_3) = $processor.get_register_value(register_3) else {
137                    return ProcessorContinue::Error;
138                };
139                let result = $op(&mut $processor.registers.fr, value_2, value_3);
140                $processor.output_into_register(register_1, result)
141            }
142        )
143    }};
144}
145
146implement_flag_register!(RiscProcessorFlagRegister(u8));
147
148pub struct RiscRegisters {
149    pub pc: u16,
150    pub fr: RiscProcessorFlagRegister,
151    pub r: [u16; 4],
152    pub sp: u16,
153}
154
155pub struct RiscProcessor {
156    pub memory: Memory<u8>,
157    pub registers: RiscRegisters,
158}
159
160impl RiscProcessor {
161    pub fn new() -> RiscProcessor {
162        RiscProcessor {
163            memory: Memory::new(0, 65536),
164            registers: RiscRegisters {
165                pc: 0,
166                fr: RiscProcessorFlagRegister::new(),
167                r: [0; 4],
168                sp: 1024,
169            },
170        }
171    }
172
173    two_byte_stack!(memory_stack[sp: u16] -> u8, based on memory, growing downward);
174    two_byte_memory!(two_byte_memory: memory[u16] -> 2 * u8);
175
176    fn get_register_value(&self, register_id: u8) -> Option<u16> {
177        self.registers
178            .r
179            .get(register_id as usize)
180            .copied()
181            .or(match register_id {
182                4 => Some(self.registers.sp),
183                _ => None,
184            })
185    }
186
187    fn set_register_value(&mut self, register_id: u8, value: u16) -> bool {
188        match register_id {
189            0..=3 => {
190                self.registers.r[register_id as usize] = value;
191                true
192            }
193            4 => {
194                self.registers.sp = value;
195                true
196            }
197            _ => false,
198        }
199    }
200
201    fn output_into_register(&mut self, register_id: u8, value: u16) -> ProcessorContinue {
202        if self.set_register_value(register_id, value) {
203            ProcessorContinue::KeepRunning
204        } else {
205            ProcessorContinue::Error
206        }
207    }
208}
209
210impl Processor<u8, u16, u16, u16> for RiscProcessor {
211    fn next(&mut self) -> u8 {
212        let instruction = self.memory[self.registers.pc as usize];
213        self.registers.pc = self.registers.pc.wrapping_add(1);
214        instruction
215    }
216    fn at_pc_plus(&self, offset: u16) -> u8 {
217        self.memory[self.registers.pc.wrapping_add(offset) as usize]
218    }
219    fn pc(&self) -> u16 {
220        self.registers.pc
221    }
222
223    fn peek_stack(&mut self, n: u8) -> u16 {
224        self.memory_stack().peek_down_by(n * 2)
225    }
226
227    fn run_command<T, U>(&mut self, output: T, input: U) -> ProcessorContinue
228    where
229        T: Fn(u16, u16),
230        U: Fn(u16) -> u16,
231    {
232        let next_byte = self.next();
233        let next_instruction = next_byte >> 2;
234        let next_instruction_as_enum = match Opcode::from_u8(next_instruction.into()) {
235            Some(opcode) => opcode,
236            None => {
237                return ProcessorContinue::Error;
238            }
239        };
240
241        let args_head = next_byte & 0b11;
242
243        match next_instruction_as_enum {
244            Opcode::Halt => ProcessorContinue::Halt,
245            Opcode::Load => with_registers!(self, args_head, |register_1, register_2, _| {
246                let Some(address) = self.get_register_value(register_2) else {
247                    return ProcessorContinue::Error;
248                };
249                let value = self.two_byte_memory().read(address);
250                self.output_into_register(register_1, value)
251            }),
252            Opcode::Store => with_registers!(self, args_head, |register_1, register_2, _| {
253                let Some(address) = self.get_register_value(register_1) else {
254                    return ProcessorContinue::Error;
255                };
256                let Some(value) = self.get_register_value(register_2) else {
257                    return ProcessorContinue::Error;
258                };
259                self.two_byte_memory().write(address, value);
260                ProcessorContinue::KeepRunning
261            }),
262            Opcode::MovRegImm => {
263                with_reg_and_immediate!(self, args_head, |register_1, _, _, immediate| {
264                    self.output_into_register(register_1, immediate)
265                })
266            }
267            Opcode::MovRegReg => with_registers!(self, args_head, |register_1, register_2, _| {
268                let Some(value) = self.get_register_value(register_2) else {
269                    return ProcessorContinue::Error;
270                };
271                self.output_into_register(register_1, value)
272            }),
273            Opcode::Push => with_registers!(self, args_head, |register_1, _, _| {
274                let Some(value) = self.get_register_value(register_1) else {
275                    return ProcessorContinue::Error;
276                };
277                self.memory_stack().push(value);
278                ProcessorContinue::KeepRunning
279            }),
280            Opcode::Pop => with_registers!(self, args_head, |register_1, _, _| {
281                let value = self.memory_stack().pop();
282                self.output_into_register(register_1, value)
283            }),
284            Opcode::Add => arithmetic!(self, args_head, arithmetic::add),
285            Opcode::Addc => arithmetic!(self, args_head, arithmetic::addc),
286            Opcode::Sub => arithmetic!(self, args_head, arithmetic::sub),
287            Opcode::Mul => arithmetic!(self, args_head, arithmetic::mul),
288            Opcode::Div => arithmetic!(self, args_head, arithmetic::div),
289            Opcode::And => arithmetic!(self, args_head, arithmetic::and),
290            Opcode::Or => arithmetic!(self, args_head, arithmetic::or),
291            Opcode::Xor => arithmetic!(self, args_head, arithmetic::xor),
292            Opcode::Not => unary_arithmetic!(self, args_head, arithmetic::not),
293            Opcode::Lsh => arithmetic!(self, args_head, arithmetic::shl),
294            Opcode::Rsh => arithmetic!(self, args_head, arithmetic::shr),
295            Opcode::CallAddr => with_immediate!(self, args_head, |immediate| {
296                let return_address = self.registers.pc;
297                self.memory_stack().push(return_address);
298                self.registers.pc = immediate;
299                ProcessorContinue::KeepRunning
300            }),
301            Opcode::CallRegAddr => with_registers!(self, args_head, |register_1, _, _| {
302                let Some(address) = self.get_register_value(register_1) else {
303                    return ProcessorContinue::Error;
304                };
305                let return_address = self.registers.pc;
306                self.memory_stack().push(return_address);
307                self.registers.pc = address;
308                ProcessorContinue::KeepRunning
309            }),
310            Opcode::Ret => {
311                let return_address = self.memory_stack().pop();
312                self.registers.pc = return_address;
313                ProcessorContinue::KeepRunning
314            }
315            Opcode::CmpRegReg => with_registers!(self, args_head, |register_1, register_2, _| {
316                let Some(value_1) = self.get_register_value(register_1) else {
317                    return ProcessorContinue::Error;
318                };
319                let Some(value_2) = self.get_register_value(register_2) else {
320                    return ProcessorContinue::Error;
321                };
322                arithmetic::cmp(&mut self.registers.fr, value_1, value_2);
323                ProcessorContinue::KeepRunning
324            }),
325            Opcode::CmpRegImm => {
326                with_reg_and_immediate!(self, args_head, |register_1, _, _, immediate| {
327                    let Some(value) = self.get_register_value(register_1) else {
328                        return ProcessorContinue::Error;
329                    };
330                    arithmetic::cmp(&mut self.registers.fr, value, immediate);
331                    ProcessorContinue::KeepRunning
332                })
333            }
334            Opcode::TestRegReg => with_registers!(self, args_head, |register_1, register_2, _| {
335                let Some(value_1) = self.get_register_value(register_1) else {
336                    return ProcessorContinue::Error;
337                };
338                let Some(value_2) = self.get_register_value(register_2) else {
339                    return ProcessorContinue::Error;
340                };
341                arithmetic::test(&mut self.registers.fr, value_1, value_2);
342                ProcessorContinue::KeepRunning
343            }),
344            Opcode::TestRegImm => {
345                with_reg_and_immediate!(self, args_head, |register_1, _, _, immediate| {
346                    let Some(value) = self.get_register_value(register_1) else {
347                        return ProcessorContinue::Error;
348                    };
349                    arithmetic::test(&mut self.registers.fr, value, immediate);
350                    ProcessorContinue::KeepRunning
351                })
352            }
353            Opcode::JmpAddr => with_immediate!(self, args_head, |immediate| {
354                self.registers.pc = immediate;
355                ProcessorContinue::KeepRunning
356            }),
357            Opcode::JmpReg => with_registers!(self, args_head, |register_1, _, _| {
358                let Some(address) = self.get_register_value(register_1) else {
359                    return ProcessorContinue::Error;
360                };
361                self.registers.pc = address;
362                ProcessorContinue::KeepRunning
363            }),
364            Opcode::Je => with_immediate!(self, args_head, |immediate| {
365                if self.registers.fr.get(ProcessorFlags::ZF) {
366                    self.registers.pc = immediate;
367                }
368                ProcessorContinue::KeepRunning
369            }),
370            Opcode::Jne => with_immediate!(self, args_head, |immediate| {
371                if !self.registers.fr.get(ProcessorFlags::ZF) {
372                    self.registers.pc = immediate;
373                }
374                ProcessorContinue::KeepRunning
375            }),
376            Opcode::Jg => with_immediate!(self, args_head, |address| {
377                if !self.registers.fr.get(ProcessorFlags::ZF)
378                    && (self.registers.fr.get(ProcessorFlags::SF)
379                        == self.registers.fr.get(ProcessorFlags::OF))
380                {
381                    self.registers.pc = address;
382                }
383                ProcessorContinue::KeepRunning
384            }),
385            Opcode::Jge => with_immediate!(self, args_head, |address| {
386                if !self.registers.fr.get(ProcessorFlags::CF) {
387                    self.registers.pc = address;
388                }
389                ProcessorContinue::KeepRunning
390            }),
391            Opcode::Jl => with_immediate!(self, args_head, |address| {
392                if self.registers.fr.get(ProcessorFlags::SF)
393                    != self.registers.fr.get(ProcessorFlags::OF)
394                {
395                    self.registers.pc = address;
396                }
397                ProcessorContinue::KeepRunning
398            }),
399            Opcode::Jle => with_immediate!(self, args_head, |address| {
400                if self.registers.fr.get(ProcessorFlags::ZF)
401                    || self.registers.fr.get(ProcessorFlags::CF)
402                {
403                    self.registers.pc = address;
404                }
405                ProcessorContinue::KeepRunning
406            }),
407            Opcode::In => {
408                with_reg_and_immediate!(self, args_head, |register_1, _, _, immediate| self
409                    .output_into_register(register_1, input(immediate)))
410            }
411            Opcode::OutImmImm => with_two_immediates!(self, args_head, |port, data| {
412                output(port, data);
413                ProcessorContinue::KeepRunning
414            }),
415            Opcode::OutImmReg => with_immediate_and_register!(self, args_head, |port, register| {
416                let Some(data) = self.get_register_value(register) else {
417                    return ProcessorContinue::Error;
418                };
419                output(port, data);
420                ProcessorContinue::KeepRunning
421            }),
422            Opcode::Nop => ProcessorContinue::KeepRunning,
423        }
424    }
425
426    fn load_executable(&mut self, executable: &Executable) -> Result<(), String> {
427        if !matches!(executable.architecture(), Architecture::Risc) {
428            return Err("Executable is not risc architecture".to_string());
429        }
430        for segment in executable.segments() {
431            let array = tightly_packed_array::TightlyPackedArray::new(segment.data.clone(), 8);
432            for i in 0..segment.address_space_size {
433                self.memory[(segment.address_space_start + i) as usize] = array.at(i as usize);
434            }
435        }
436        self.registers.pc = executable.entry_point() as u16;
437        Ok(())
438    }
439}