monistode_emulator/
acc_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 = 0b000000,
18    Load = 0b000001,
19    LoadImm = 0b10010000,
20    Loadf = 0b000010,
21    LoadIR1 = 0b1000001,
22    LoadIR2 = 0b1000010,
23    MovAccIR1 = 0b011111,
24    MovAccIR2 = 0b100000,
25    StoreIR1 = 0b000011,
26    StoreIR1Imm = 0b10010001,
27    StoreIR2 = 0b100011,
28    StoreIR2Imm = 0b11110010,
29    Storef = 0b000100,
30    MovIR1Acc = 0b100001,
31    MovIR2Acc = 0b100010,
32    MovIR2IR1 = 0b111111,
33    MovIR1IR2 = 0b1000000,
34    MovImm = 0b10000000,
35    Push = 0b000101,
36    Pop = 0b000111,
37    Pushf = 0b000110,
38    Popf = 0b001000,
39    PushIR1 = 0b111101,
40    PopIR1 = 0b001001,
41    PushIR2 = 0b100100,
42    PopIR2 = 0b100101,
43    AddAddr = 0b001010,
44    AddIR1 = 0b100110,
45    AddIR2 = 0b100111,
46    SubAddr = 0b001011,
47    SubIR1 = 0b101000,
48    SubIR2 = 0b101001,
49    MulAddr = 0b001110,
50    MulIR1 = 0b101010,
51    MulIR2 = 0b101011,
52    DivAddr = 0b001111,
53    DivIR1 = 0b101100,
54    DivIR2 = 0b101101,
55    Inc = 0b001100,
56    IncIR1 = 0b101110,
57    IncIR2 = 0b101111,
58    Dec = 0b001101,
59    DecIR1 = 0b110000,
60    DecIR2 = 0b110001,
61    AndAddr = 0b010000,
62    AndIR1 = 0b110010,
63    AndIR2 = 0b110011,
64    OrAddr = 0b010001,
65    OrIR1 = 0b110100,
66    OrIR2 = 0b110101,
67    XorAddr = 0b010010,
68    XorIR1 = 0b110110,
69    XorIR2 = 0b110111,
70    NotAddr = 0b010011,
71    NotIR1 = 0b111000,
72    NotIR2 = 0b111110,
73    Lsh = 0b10000001,
74    Rsh = 0b10000010,
75    CallAddr = 0b10000100,
76    Call = 0b010100,
77    Ret = 0b010101,
78    CmpAddr = 0b010110,
79    CmpImm = 0b10000101,
80    CmpIR1 = 0b111001,
81    CmpIR2 = 0b111010,
82    TestImm = 0b10000110,
83    TestAddr = 0b10001111,
84    TestIR1 = 0b111011,
85    TestIR2 = 0b111100,
86    JmpAddr = 0b10000111,
87    Jmp = 0b010111,
88    JeAddr = 0b10001000,
89    Je = 0b011000,
90    JneAddr = 0b10001001,
91    Jne = 0b011001,
92    JgAddr = 0b10001010,
93    Jg = 0b011010,
94    JgeAddr = 0b10001011,
95    Jge = 0b011011,
96    JlAddr = 0b10001100,
97    Jl = 0b011100,
98    JleAddr = 0b10001101,
99    Jle = 0b011101,
100    In = 0b10001110,
101    Out = 0b10011000,
102}
103
104macro_rules! with_immediate {
105    ($processor:ident, $op:expr) => {{
106        let immediate = $processor.load_immediate();
107        $op(immediate);
108        ProcessorContinue::KeepRunning
109    }};
110}
111
112macro_rules! arithmetic_imm {
113    ($processor:ident, $op:expr) => {{
114        let immediate = $processor.load_immediate();
115        let acc = $processor.registers.acc;
116        let result = $op(&mut $processor.registers.fr, acc, immediate);
117        $processor.registers.acc = result;
118        ProcessorContinue::KeepRunning
119    }};
120}
121
122macro_rules! arithmetic_addr {
123    ($processor:ident, $op:expr) => {{
124        let address = $processor.load_immediate();
125        let value = $processor.two_byte_memory().read(address);
126        let acc = $processor.registers.acc;
127        let result = $op(&mut $processor.registers.fr, acc, value);
128        $processor.registers.acc = result;
129        ProcessorContinue::KeepRunning
130    }};
131}
132
133macro_rules! arithmetic_ir1 {
134    ($processor:ident, $op:expr) => {{
135        let address = $processor.registers.ir1;
136        let value = $processor.two_byte_memory().read(address);
137        let acc = $processor.registers.acc;
138        let result = $op(&mut $processor.registers.fr, acc, value);
139        $processor.registers.acc = result;
140        ProcessorContinue::KeepRunning
141    }};
142}
143
144macro_rules! arithmetic_ir2 {
145    ($processor:ident, $op:expr) => {{
146        let address = $processor.registers.ir2;
147        let value = $processor.two_byte_memory().read(address);
148        let acc = $processor.registers.acc;
149        let result = $op(&mut $processor.registers.fr, acc, value);
150        $processor.registers.acc = result;
151        ProcessorContinue::KeepRunning
152    }};
153}
154
155macro_rules! arithmetic_acc {
156    ($processor:ident, $op:expr) => {{
157        let acc = $processor.registers.acc;
158        let result = $op(&mut $processor.registers.fr, acc);
159        $processor.registers.acc = result;
160        ProcessorContinue::KeepRunning
161    }};
162}
163
164macro_rules! arithmetic_ir1_single_operand {
165    ($processor:ident, $op:expr) => {{
166        let previous = $processor.registers.ir1;
167        let result = $op(&mut $processor.registers.fr, previous);
168        $processor.registers.ir1 = result;
169        ProcessorContinue::KeepRunning
170    }};
171}
172
173macro_rules! arithmetic_ir2_single_operand {
174    ($processor:ident, $op:expr) => {{
175        let previous = $processor.registers.ir2;
176        let result = $op(&mut $processor.registers.fr, previous);
177        $processor.registers.ir2 = result;
178        ProcessorContinue::KeepRunning
179    }};
180}
181
182macro_rules! arithmetic_acc_addr_into_acc {
183    ($processor:ident, $op:expr) => {{
184        let address = $processor.registers.acc;
185        let value = $processor.two_byte_memory().read(address);
186        let result = $op(&mut $processor.registers.fr, value);
187        $processor.registers.acc = result;
188        ProcessorContinue::KeepRunning
189    }};
190}
191
192macro_rules! arithmetic_ir1_into_acc {
193    ($processor:ident, $op:expr) => {{
194        let address = $processor.registers.ir1;
195        let value = $processor.two_byte_memory().read(address);
196        let result = $op(&mut $processor.registers.fr, value);
197        $processor.registers.acc = result;
198        ProcessorContinue::KeepRunning
199    }};
200}
201
202macro_rules! arithmetic_ir2_into_acc {
203    ($processor:ident, $op:expr) => {{
204        let address = $processor.registers.ir2;
205        let value = $processor.two_byte_memory().read(address);
206        let result = $op(&mut $processor.registers.fr, value);
207        $processor.registers.acc = result;
208        ProcessorContinue::KeepRunning
209    }};
210}
211
212implement_flag_register!(AccProcessorFlagRegister(u8));
213
214pub struct AccRegisters {
215    pub pc: u16,
216    pub fr: AccProcessorFlagRegister,
217    pub sp: u16,
218    pub ir1: u16,
219    pub ir2: u16,
220    pub acc: u16,
221}
222
223pub struct AccProcessor {
224    pub memory: Memory<u8>,
225    pub registers: AccRegisters,
226}
227
228impl AccProcessor {
229    pub fn new() -> AccProcessor {
230        AccProcessor {
231            memory: Memory::new(0, 65536),
232            registers: AccRegisters {
233                pc: 0,
234                fr: AccProcessorFlagRegister::new(),
235                sp: 1024,
236                ir1: 0,
237                ir2: 0,
238                acc: 0,
239            },
240        }
241    }
242
243    two_byte_stack!(memory_stack[sp: u16] -> u8, based on memory, growing downward);
244    two_byte_memory!(two_byte_memory: memory[u16] -> 2 * u8);
245
246    fn load_immediate(&mut self) -> u16 {
247        let immediate = self.next() as u16;
248        immediate << 8 | self.next() as u16
249    }
250}
251
252impl Processor<u8, u16, u16, u16> for AccProcessor {
253    fn next(&mut self) -> u8 {
254        let instruction = self.memory[self.registers.pc as usize];
255        self.registers.pc = self.registers.pc.wrapping_add(1);
256        instruction
257    }
258
259    fn at_pc_plus(&self, offset: u16) -> u8 {
260        self.memory[self.registers.pc.wrapping_add(offset) as usize]
261    }
262
263    fn pc(&self) -> u16 {
264        self.registers.pc
265    }
266
267    fn peek_stack(&mut self, n: u8) -> u16 {
268        self.memory_stack().peek_down_by(n * 2)
269    }
270
271    fn run_command<T, U>(&mut self, output: T, input: U) -> ProcessorContinue
272    where
273        T: Fn(u16, u16),
274        U: Fn(u16) -> u16,
275    {
276        let next_instruction = self.next();
277        let next_instruction_as_enum = match Opcode::from_u8(next_instruction.into()) {
278            Some(opcode) => opcode,
279            None => {
280                return ProcessorContinue::Error;
281            }
282        };
283        match next_instruction_as_enum {
284            Opcode::Halt => ProcessorContinue::Halt,
285            Opcode::Load => {
286                let address = self.registers.acc;
287                self.registers.acc = self.two_byte_memory().read(address);
288                ProcessorContinue::KeepRunning
289            }
290            Opcode::LoadImm => with_immediate!(self, |immediate| {
291                self.registers.acc = immediate;
292            }),
293            Opcode::Loadf => {
294                let value: u8 = self.registers.fr.into();
295                self.registers.acc = value as u16;
296                ProcessorContinue::KeepRunning
297            }
298            Opcode::LoadIR1 => {
299                let address = self.registers.ir1;
300                self.registers.acc = self.two_byte_memory().read(address);
301                ProcessorContinue::KeepRunning
302            }
303            Opcode::LoadIR2 => {
304                let address = self.registers.ir2;
305                self.registers.acc = self.two_byte_memory().read(address);
306                ProcessorContinue::KeepRunning
307            }
308            Opcode::MovAccIR1 => {
309                self.registers.acc = self.registers.ir1;
310                ProcessorContinue::KeepRunning
311            }
312            Opcode::MovAccIR2 => {
313                self.registers.acc = self.registers.ir2;
314                ProcessorContinue::KeepRunning
315            }
316            Opcode::StoreIR1 => {
317                let address = self.registers.ir1;
318                let value = self.registers.acc;
319                self.two_byte_memory().write(address, value);
320                ProcessorContinue::KeepRunning
321            }
322            Opcode::StoreIR1Imm => with_immediate!(self, |immediate| {
323                let address = self.registers.ir1;
324                self.two_byte_memory().write(address, immediate);
325            }),
326            Opcode::StoreIR2 => {
327                let address = self.registers.ir2;
328                let value = self.registers.acc;
329                self.two_byte_memory().write(address, value);
330                ProcessorContinue::KeepRunning
331            }
332            Opcode::StoreIR2Imm => with_immediate!(self, |immediate| {
333                let address = self.registers.ir2;
334                self.two_byte_memory().write(address, immediate);
335            }),
336            Opcode::Storef => {
337                let value = (self.registers.acc & 0xFF) as u8;
338                self.registers.fr.0 = value;
339                ProcessorContinue::KeepRunning
340            }
341            Opcode::MovIR1Acc => {
342                self.registers.ir1 = self.registers.acc;
343                ProcessorContinue::KeepRunning
344            }
345            Opcode::MovIR2Acc => {
346                self.registers.ir2 = self.registers.acc;
347                ProcessorContinue::KeepRunning
348            }
349            Opcode::MovIR2IR1 => {
350                self.registers.ir2 = self.registers.ir1;
351                ProcessorContinue::KeepRunning
352            }
353            Opcode::MovIR1IR2 => {
354                self.registers.ir1 = self.registers.ir2;
355                ProcessorContinue::KeepRunning
356            }
357            Opcode::MovImm => with_immediate!(self, |immediate| {
358                self.registers.acc = immediate;
359            }),
360            Opcode::Push => {
361                let value = self.registers.acc;
362                self.memory_stack().push(value);
363                ProcessorContinue::KeepRunning
364            }
365            Opcode::Pop => {
366                let value = self.memory_stack().pop();
367                self.registers.acc = value;
368                ProcessorContinue::KeepRunning
369            }
370            Opcode::Pushf => {
371                let value = self.registers.fr.0 as u16;
372                self.memory_stack().push(value);
373                ProcessorContinue::KeepRunning
374            }
375            Opcode::Popf => {
376                let value = self.memory_stack().pop();
377                self.registers.fr.0 = value as u8;
378                ProcessorContinue::KeepRunning
379            }
380            Opcode::PushIR1 => {
381                let value = self.registers.ir1;
382                self.memory_stack().push(value);
383                ProcessorContinue::KeepRunning
384            }
385            Opcode::PopIR1 => {
386                let value = self.memory_stack().pop();
387                self.registers.ir1 = value;
388                ProcessorContinue::KeepRunning
389            }
390            Opcode::PushIR2 => {
391                let value = self.registers.ir2;
392                self.memory_stack().push(value);
393                ProcessorContinue::KeepRunning
394            }
395            Opcode::PopIR2 => {
396                let value = self.memory_stack().pop();
397                self.registers.ir2 = value;
398                ProcessorContinue::KeepRunning
399            }
400            Opcode::AddAddr => arithmetic_addr!(self, arithmetic::add),
401            Opcode::AddIR1 => arithmetic_ir1!(self, arithmetic::add),
402            Opcode::AddIR2 => arithmetic_ir2!(self, arithmetic::add),
403            Opcode::SubAddr => arithmetic_addr!(self, arithmetic::sub),
404            Opcode::SubIR1 => arithmetic_ir1!(self, arithmetic::sub),
405            Opcode::SubIR2 => arithmetic_ir2!(self, arithmetic::sub),
406            Opcode::MulAddr => arithmetic_addr!(self, arithmetic::mul),
407            Opcode::MulIR1 => arithmetic_ir1!(self, arithmetic::mul),
408            Opcode::MulIR2 => arithmetic_ir2!(self, arithmetic::mul),
409            Opcode::DivAddr => arithmetic_addr!(self, arithmetic::div),
410            Opcode::DivIR1 => arithmetic_ir1!(self, arithmetic::div),
411            Opcode::DivIR2 => arithmetic_ir2!(self, arithmetic::div),
412            Opcode::Inc => arithmetic_acc!(self, arithmetic::inc),
413            Opcode::IncIR1 => arithmetic_ir1_single_operand!(self, arithmetic::inc),
414            Opcode::IncIR2 => arithmetic_ir2_single_operand!(self, arithmetic::inc),
415            Opcode::Dec => arithmetic_acc!(self, arithmetic::dec),
416            Opcode::DecIR1 => arithmetic_ir1_single_operand!(self, arithmetic::dec),
417            Opcode::DecIR2 => arithmetic_ir2_single_operand!(self, arithmetic::dec),
418            Opcode::AndAddr => arithmetic_addr!(self, arithmetic::and),
419            Opcode::AndIR1 => arithmetic_ir1!(self, arithmetic::and),
420            Opcode::AndIR2 => arithmetic_ir2!(self, arithmetic::and),
421            Opcode::OrAddr => arithmetic_addr!(self, arithmetic::or),
422            Opcode::OrIR1 => arithmetic_ir1!(self, arithmetic::or),
423            Opcode::OrIR2 => arithmetic_ir2!(self, arithmetic::or),
424            Opcode::XorAddr => arithmetic_addr!(self, arithmetic::xor),
425            Opcode::XorIR1 => arithmetic_ir1!(self, arithmetic::xor),
426            Opcode::XorIR2 => arithmetic_ir2!(self, arithmetic::xor),
427            Opcode::NotAddr => arithmetic_acc_addr_into_acc!(self, arithmetic::not),
428            Opcode::NotIR1 => arithmetic_ir1_into_acc!(self, arithmetic::not),
429            Opcode::NotIR2 => arithmetic_ir2_into_acc!(self, arithmetic::not),
430            Opcode::Lsh => arithmetic_imm!(self, arithmetic::shl),
431            Opcode::Rsh => arithmetic_imm!(self, arithmetic::shr),
432            Opcode::CallAddr => with_immediate!(self, |address| {
433                let return_address = self.registers.pc;
434                self.memory_stack().push(return_address);
435                self.registers.pc = address;
436                ProcessorContinue::KeepRunning
437            }),
438            Opcode::Call => {
439                let return_address = self.registers.pc;
440                self.memory_stack().push(return_address);
441                self.registers.pc = self.registers.acc;
442                ProcessorContinue::KeepRunning
443            }
444            Opcode::Ret => {
445                let return_address = self.memory_stack().pop();
446                self.registers.pc = return_address;
447                ProcessorContinue::KeepRunning
448            }
449            Opcode::CmpAddr => arithmetic_addr!(self, arithmetic::cmp),
450            Opcode::CmpImm => arithmetic_imm!(self, arithmetic::cmp),
451            Opcode::CmpIR1 => arithmetic_ir1!(self, arithmetic::cmp),
452            Opcode::CmpIR2 => arithmetic_ir2!(self, arithmetic::cmp),
453            Opcode::TestImm => arithmetic_imm!(self, arithmetic::test),
454            Opcode::TestAddr => arithmetic_addr!(self, arithmetic::test),
455            Opcode::TestIR1 => arithmetic_ir1!(self, arithmetic::test),
456            Opcode::TestIR2 => arithmetic_ir2!(self, arithmetic::test),
457            Opcode::JmpAddr => with_immediate!(self, |address| {
458                self.registers.pc = address;
459            }),
460            Opcode::Jmp => {
461                self.registers.pc = self.registers.acc;
462                ProcessorContinue::KeepRunning
463            }
464            Opcode::JeAddr => with_immediate!(self, |address| {
465                if self.registers.fr.get(ProcessorFlags::ZF) {
466                    self.registers.pc = address;
467                }
468            }),
469            Opcode::Je => {
470                if self.registers.fr.get(ProcessorFlags::ZF) {
471                    self.registers.pc = self.registers.acc;
472                }
473                ProcessorContinue::KeepRunning
474            }
475            Opcode::JneAddr => with_immediate!(self, |address| {
476                if !self.registers.fr.get(ProcessorFlags::ZF) {
477                    self.registers.pc = address;
478                }
479            }),
480            Opcode::Jne => {
481                if !self.registers.fr.get(ProcessorFlags::ZF) {
482                    self.registers.pc = self.registers.acc;
483                }
484                ProcessorContinue::KeepRunning
485            }
486            Opcode::JgAddr => with_immediate!(self, |address| {
487                if !self.registers.fr.get(ProcessorFlags::ZF)
488                    && (self.registers.fr.get(ProcessorFlags::SF)
489                        == self.registers.fr.get(ProcessorFlags::OF))
490                {
491                    self.registers.pc = address;
492                }
493            }),
494            Opcode::Jg => {
495                if !self.registers.fr.get(ProcessorFlags::ZF)
496                    && (self.registers.fr.get(ProcessorFlags::SF)
497                        == self.registers.fr.get(ProcessorFlags::OF))
498                {
499                    self.registers.pc = self.registers.acc;
500                }
501                ProcessorContinue::KeepRunning
502            }
503            Opcode::JgeAddr => with_immediate!(self, |address| {
504                if !self.registers.fr.get(ProcessorFlags::CF) {
505                    self.registers.pc = address;
506                }
507            }),
508            Opcode::Jge => {
509                if !self.registers.fr.get(ProcessorFlags::CF) {
510                    self.registers.pc = self.registers.acc;
511                }
512                ProcessorContinue::KeepRunning
513            }
514            Opcode::JlAddr => with_immediate!(self, |address| {
515                if self.registers.fr.get(ProcessorFlags::SF)
516                    != self.registers.fr.get(ProcessorFlags::OF)
517                {
518                    self.registers.pc = address;
519                }
520            }),
521            Opcode::Jl => {
522                if self.registers.fr.get(ProcessorFlags::SF)
523                    != self.registers.fr.get(ProcessorFlags::OF)
524                {
525                    self.registers.pc = self.registers.acc;
526                }
527                ProcessorContinue::KeepRunning
528            }
529            Opcode::JleAddr => with_immediate!(self, |address| {
530                if self.registers.fr.get(ProcessorFlags::ZF)
531                    || self.registers.fr.get(ProcessorFlags::CF)
532                {
533                    self.registers.pc = address;
534                }
535            }),
536            Opcode::Jle => {
537                if self.registers.fr.get(ProcessorFlags::ZF)
538                    || self.registers.fr.get(ProcessorFlags::CF)
539                {
540                    self.registers.pc = self.registers.acc;
541                }
542                ProcessorContinue::KeepRunning
543            }
544            Opcode::In => with_immediate!(self, |port| {
545                self.registers.acc = input(port);
546            }),
547            Opcode::Out => with_immediate!(self, |port| {
548                output(port, self.registers.acc);
549            }),
550        }
551    }
552
553    fn load_executable(&mut self, executable: &Executable) -> Result<(), String> {
554        if !matches!(executable.architecture(), Architecture::Accumulator) {
555            return Err("Executable is not accumulator architecture".to_string());
556        }
557        for segment in executable.segments() {
558            let array = tightly_packed_array::TightlyPackedArray::new(segment.data.clone(), 8);
559            for i in 0..segment.address_space_size {
560                self.memory[(segment.address_space_start + i) as usize] = array.at(i as usize);
561            }
562        }
563        self.registers.pc = executable.entry_point() as u16;
564        Ok(())
565    }
566}