monistode_emulator/
cisc_processor.rs

1use monistode_binutils::Executable;
2
3use super::{
4    arithmetic,
5    common::{Processor, ProcessorContinue},
6    flag_register::{implement_flag_register, FlagRegister, ProcessorFlags},
7    memory::{two_byte_memory, Memory, TwoByteMemory},
8    stack::{two_byte_stack, Stack, TwoByteStack},
9};
10use num_derive::FromPrimitive;
11use num_traits::FromPrimitive;
12
13#[derive(Debug, FromPrimitive)]
14enum Opcode {
15    Halt = 0b00000000,
16    MovRegImm = 0b10000000,
17    MovRegReg = 0b01100000,
18    MovRegRegAdr = 0b01100001,
19    MovRegRegAdrOff = 0b10100000,
20    MovRegAdrReg = 0b01100010,
21    MovRegAdrImm = 0b10000001,
22    MovRegAdrOffReg = 0b10100001,
23    MovRegAdrOffImm = 0b11000000,
24    PushReg = 0b00000001,
25    PushImm = 0b01000000,
26    PopReg = 0b00000010,
27    EnterImm = 0b01000001,
28    Leave = 00100000,
29    AddRegRegAdr = 0b01100011,
30    AddRegReg = 0b01100100,
31    AddRegRegAdrOff = 0b10100010,
32    AddRegAdrReg = 0b01100101,
33    SubRegRegAdr = 0b01100110,
34    SubRegReg = 0b01100111,
35    SubRegRegAdrOff = 0b10100011,
36    SubRegAdrReg = 0b01101000,
37    IncReg = 0b00011111,
38    IncRegAdr = 0b00000100,
39    IncRegAdrOff = 0b100000010,
40    DecReg = 0b00000101,
41    DecRegAdr = 0b00000110,
42    DecRegAdrOff = 0b10000011,
43    MulRegReg = 0b01101001,
44    MulRegRegAdr = 0b01101010,
45    MulRegAdrReg = 0b01101011,
46    MulRegImm = 0b10000100,
47    MulRegRegAdrOff = 0b10100100,
48    DivRegReg = 0b01101100,
49    DivRegRegAdr = 0b01101101,
50    DivRegAdrReg = 0b01101110,
51    DivRegImm = 0b10000101,
52    DivRegRegAdrOff = 0b10100101,
53    AndRegReg = 0b01101111,
54    AndRegRegAdr = 0b01110000,
55    OrRegReg = 0b01110001,
56    OrRegRegAdr = 0b01110010,
57    XorRegReg = 0b01110011,
58    XorRegRegAdr = 0b01110100,
59    NotReg = 0b00000111,
60    NotRegAdr = 0b00001000,
61    LshRegImm = 0b10000110,
62    LshRegAdrImm = 0b10000111,
63    LshRegAdrOffImm = 0b11000001,
64    RshRegImm = 0b10001000,
65    RshRegAdrImm = 0b10001001,
66    RshRegAdrOffImm = 0b11000010,
67    CallImm = 0b01000010,
68    CallReg = 0b00001001,
69    CallRegOff = 145,
70    Ret = 0b00100001,
71    CmpRegReg = 0b01110101,
72    CmpRegImm = 0b10001011,
73    CmpRegRegAdr = 146,
74    CmpRegRegAdrOff = 0b10100110,
75    TestRegReg = 0b01110111,
76    TestRegRegAdr = 0b01111000,
77    TestRegRegAdrOff = 0b10100111,
78    JmpImm = 0b01000011,
79    JmpReg = 0b00001010,
80    JmpRegOff = 0b10001100,
81    JeImm = 0b01000100,
82    JneImm = 0b01000101,
83    JgImm = 0b01000110,
84    JgeImm = 0b01000111,
85    JlImm = 0b01001000,
86    JleImm = 0b01001001,
87    InRegPort = 0b10001101,
88    InRegAdrPort = 0b10001110,
89    InRegAdrOffPort = 0b11000011,
90    OutPortImm = 0b11001111,
91    OutPortReg = 0b10001111,
92    OutPortRegAdr = 0b10010000,
93    OutPortRegAdrOff = 0b11000100,
94    //Load4SimdregAddr = 0b00001011,
95    //Store4SimdregAddr = 0b00001100,
96    //Add4Simdreg1Simdreg2 = 0b01111010,
97    //Sub4Simdreg1Simdreg2 = 0b01111011,
98    //Mul4Simdreg1Imdreg2 = 0b01111101,
99    //Div4Simdreg1Simdreg2 = 255,
100    Nop = 0b00100010,
101}
102
103macro_rules! with_register_value {
104    ($processor:ident, $op:expr) => {{
105        let register_value = match $processor.load_register() {
106            Some(value) => value,
107            None => return ProcessorContinue::Error,
108        };
109        $op(register_value);
110        ProcessorContinue::KeepRunning
111    }};
112}
113
114macro_rules! with_register_id_and_register_value {
115    ($processor:ident, $op:expr) => {{
116        let (register_id, address_register_id) = $processor.load_two_register_ids();
117        let value = match $processor.get_register_value(address_register_id) {
118            Some(value) => value,
119            None => return ProcessorContinue::Error,
120        };
121        $op(register_id, value)
122    }};
123}
124
125macro_rules! with_two_register_values {
126    ($processor:ident, $op:expr) => {{
127        let (register_id1, register_id2) = $processor.load_two_register_ids();
128        let value1 = match $processor.get_register_value(register_id1) {
129            Some(value) => value,
130            None => return ProcessorContinue::Error,
131        };
132        let value2 = match $processor.get_register_value(register_id2) {
133            Some(value) => value,
134            None => return ProcessorContinue::Error,
135        };
136        $op(value1, value2)
137    }};
138}
139
140macro_rules! with_register_id_and_register_address {
141    ($processor:ident, $op:expr) => {{
142        let (register_id, address_register_id) = $processor.load_two_register_ids();
143        let value = match $processor.get_register_value(address_register_id) {
144            Some(value) => $processor.two_byte_memory().read(value),
145            None => return ProcessorContinue::Error,
146        };
147        $op(register_id, value)
148    }};
149}
150
151macro_rules! with_register_address {
152    ($processor:ident, $op:expr) => {{
153        let value = $processor.load_register_address();
154        match value {
155            Some(value) => {
156                $op(value);
157                ProcessorContinue::KeepRunning
158            }
159            None => ProcessorContinue::Error,
160        }
161    }};
162}
163
164macro_rules! with_register_id_and_register_address_offset {
165    ($processor:ident, $op:expr) => {{
166        let (register_id, address_register_id) = $processor.load_two_register_ids();
167        let address_register_value = match $processor.get_register_value(address_register_id) {
168            Some(value) => value,
169            None => return ProcessorContinue::Error,
170        };
171        with_immediate_raw!($processor, |immediate| {
172            let value = $processor
173                .two_byte_memory()
174                .read(address_register_value.wrapping_add(immediate));
175            $op(register_id, value)
176        })
177    }};
178}
179
180macro_rules! with_register_address_offset {
181    ($processor:ident, $op:expr) => {{
182        let value = $processor.load_register_address_offset();
183        $op(value);
184        ProcessorContinue::KeepRunning
185    }};
186}
187
188macro_rules! with_register_address_offset_as_address {
189    ($processor:ident, $op:expr) => {{
190        let register_value = match $processor.load_register() {
191            Some(value) => value,
192            None => return ProcessorContinue::Error,
193        };
194        with_immediate!($processor, |immediate| {
195            $op(register_value.wrapping_add(immediate));
196        })
197    }};
198}
199
200macro_rules! with_register_id {
201    ($processor:ident, $op:expr) => {{
202        let register_id = $processor.next();
203        $op(register_id);
204        ProcessorContinue::KeepRunning
205    }};
206}
207
208macro_rules! with_immediate_raw {
209    ($processor:ident, $op:expr) => {{
210        let immediate = $processor.load_immediate();
211        $op(immediate)
212    }};
213}
214
215macro_rules! with_immediate {
216    ($processor:ident, $op:expr) => {{
217        let immediate = $processor.load_immediate();
218        $op(immediate);
219        ProcessorContinue::KeepRunning
220    }};
221}
222
223macro_rules! save_to_register {
224    ($processor:ident, $op:expr) => {{
225        let register_id = $processor.next();
226        let value = $op();
227        match $processor.save_register(register_id, value) {
228            Ok(_) => ProcessorContinue::KeepRunning,
229            Err(_) => ProcessorContinue::Error,
230        }
231    }};
232}
233
234macro_rules! save_to_register_address {
235    ($processor:ident, $op:expr) => {{
236        let address = match $processor.load_register() {
237            Some(value) => value,
238            None => return ProcessorContinue::Error,
239        };
240        let value = $op();
241        $processor.two_byte_memory().write(address, value);
242        ProcessorContinue::KeepRunning
243    }};
244}
245
246macro_rules! save_to_register_address_offset {
247    ($processor:ident, $op:expr) => {{
248        let address = match $processor.load_register() {
249            Some(value) => value,
250            None => return ProcessorContinue::Error,
251        };
252        let offset = $processor.load_immediate();
253        let value = $op();
254        $processor
255            .two_byte_memory()
256            .write(address.wrapping_add(offset), value);
257        ProcessorContinue::KeepRunning
258    }};
259}
260
261macro_rules! save_optional_to_register_address_offset {
262    ($processor:ident, $op:expr) => {{
263        let address = match $processor.load_register() {
264            Some(value) => value,
265            None => return ProcessorContinue::Error,
266        };
267        let offset = $processor.load_immediate();
268        let value = match $op() {
269            Some(value) => value,
270            None => return ProcessorContinue::Error,
271        };
272        $processor
273            .two_byte_memory()
274            .write(address.wrapping_add(offset), value);
275        ProcessorContinue::KeepRunning
276    }};
277}
278
279macro_rules! push_result {
280    ($processor:ident, $op:expr) => {{
281        let value = $op();
282        $processor.memory_stack().push(value);
283        ProcessorContinue::KeepRunning
284    }};
285}
286
287macro_rules! push_optional_result {
288    ($processor:ident, $op:expr) => {{
289        let value = match $op() {
290            Some(value) => value,
291            None => return ProcessorContinue::Error,
292        };
293        $processor.memory_stack().push(value);
294        ProcessorContinue::KeepRunning
295    }};
296}
297
298implement_flag_register!(CiscProcessorFlagRegister(u8));
299
300macro_rules! arithmetic_reg_reg_addr {
301    ($processor: ident, $op: expr) => {{
302        with_register_id_and_register_address!($processor, |register_id, b| {
303            let a = match $processor.get_register_value(register_id) {
304                Some(value) => value,
305                None => return ProcessorContinue::Error,
306            };
307            let result = $op(&mut $processor.registers.fr, a, b);
308            match $processor.save_register(register_id, result) {
309                Ok(_) => ProcessorContinue::KeepRunning,
310                Err(_) => ProcessorContinue::Error,
311            }
312        })
313    }};
314}
315
316macro_rules! arithmetic_reg_addr_reg {
317    ($processor: ident, $op: expr) => {{
318        with_two_register_values!($processor, |address, b| {
319            let a = $processor.two_byte_memory().read(address);
320            let result = $op(&mut $processor.registers.fr, a, b);
321            $processor.two_byte_memory().write(address, result);
322            ProcessorContinue::KeepRunning
323        })
324    }};
325}
326
327macro_rules! arithmetic_reg_reg {
328    ($processor: ident, $op: expr) => {{
329        with_register_id_and_register_value!($processor, |register_id, b| {
330            let a = match $processor.get_register_value(register_id) {
331                Some(value) => value,
332                None => return ProcessorContinue::Error,
333            };
334            let result = $op(&mut $processor.registers.fr, a, b);
335            match $processor.save_register(register_id, result) {
336                Ok(_) => ProcessorContinue::KeepRunning,
337                Err(_) => ProcessorContinue::Error,
338            }
339        })
340    }};
341}
342
343macro_rules! arithmetic_reg_reg_addr_off {
344    ($processor: ident, $op: expr) => {{
345        with_register_id_and_register_address_offset!($processor, |register_id, b| {
346            let a = match $processor.get_register_value(register_id) {
347                Some(value) => value,
348                None => return ProcessorContinue::Error,
349            };
350            let result = $op(&mut $processor.registers.fr, a, b);
351            match $processor.save_register(register_id, result) {
352                Ok(_) => ProcessorContinue::KeepRunning,
353                Err(_) => ProcessorContinue::Error,
354            }
355        })
356    }};
357}
358
359macro_rules! arithmetic_reg_imm {
360    ($processor: ident, $op: expr) => {{
361        with_register_id!($processor, |register_id| {
362            with_immediate!($processor, |b| {
363                let a = match $processor.get_register_value(register_id) {
364                    Some(value) => value,
365                    None => return ProcessorContinue::Error,
366                };
367                let result = $op(&mut $processor.registers.fr, a, b);
368                match $processor.save_register(register_id, result) {
369                    Ok(_) => ProcessorContinue::KeepRunning,
370                    Err(_) => ProcessorContinue::Error,
371                }
372            })
373        })
374    }};
375}
376
377macro_rules! arithmetic_reg_addr_imm {
378    ($processor: ident, $op: expr) => {{
379        with_register_value!($processor, |address| {
380            with_immediate!($processor, |b| {
381                let a = $processor.two_byte_memory().read(address);
382                let result = $op(&mut $processor.registers.fr, a, b);
383                $processor.two_byte_memory().write(address, result);
384                ProcessorContinue::KeepRunning
385            })
386        })
387    }};
388}
389
390macro_rules! arithmetic_reg_addr_offset_imm {
391    ($processor: ident, $op: expr) => {{
392        with_register_address_offset_as_address!($processor, |address| {
393            with_immediate!($processor, |b| {
394                let a = $processor.two_byte_memory().read(address);
395                let result = $op(&mut $processor.registers.fr, a, b);
396                $processor.two_byte_memory().write(address, result);
397                ProcessorContinue::KeepRunning
398            })
399        })
400    }};
401}
402
403macro_rules! arithmetic_reg {
404    ($processor: ident, $op: expr) => {{
405        with_register_id!($processor, |register_id| {
406            let a = match $processor.get_register_value(register_id) {
407                Some(value) => value,
408                None => return ProcessorContinue::Error,
409            };
410            let result = $op(&mut $processor.registers.fr, a);
411            match $processor.save_register(register_id, result) {
412                Ok(_) => ProcessorContinue::KeepRunning,
413                Err(_) => ProcessorContinue::Error,
414            }
415        })
416    }};
417}
418
419macro_rules! arithmetic_reg_addr {
420    ($processor: ident, $op: expr) => {{
421        with_register_value!($processor, |address| {
422            let a = $processor.two_byte_memory().read(address);
423            let result = $op(&mut $processor.registers.fr, a);
424            $processor.two_byte_memory().write(address, result);
425            ProcessorContinue::KeepRunning
426        })
427    }};
428}
429
430macro_rules! arithmetic_reg_addr_offset {
431    ($processor: ident, $op: expr) => {{
432        with_register_address_offset_as_address!($processor, |address| {
433            let a = $processor.two_byte_memory().read(address);
434            let result = $op(&mut $processor.registers.fr, a);
435            $processor.two_byte_memory().write(address, result);
436            ProcessorContinue::KeepRunning
437        })
438    }};
439}
440
441pub struct CiscRegisters {
442    pub pc: u16,
443    pub fr: CiscProcessorFlagRegister,
444    pub r: [u16; 4],
445    pub bp: u16,
446    pub sp: u16,
447}
448
449pub struct CiscProcessor {
450    pub memory: Memory<u8>,
451    pub registers: CiscRegisters,
452}
453
454impl CiscProcessor {
455    pub fn new() -> CiscProcessor {
456        CiscProcessor {
457            memory: Memory::new(0, 65536),
458            registers: CiscRegisters {
459                pc: 0,
460                fr: CiscProcessorFlagRegister::new(),
461                r: [0; 4],
462                bp: 0,
463                sp: 1024,
464            },
465        }
466    }
467
468    two_byte_stack!(memory_stack[sp: u16] -> u8, based on memory, growing downward);
469    two_byte_memory!(two_byte_memory: memory[u16] -> 2 * u8);
470
471    fn load_immediate(&mut self) -> u16 {
472        let immediate = self.next() as u16;
473        immediate << 8 | self.next() as u16
474    }
475
476    fn load_register(&mut self) -> Option<u16> {
477        let register = self.next();
478        self.registers
479            .r
480            .get(register as usize)
481            .copied()
482            .or(match register {
483                4 => Some(self.registers.bp),
484                5 => Some(self.registers.sp),
485                _ => None,
486            })
487    }
488
489    fn load_two_register_ids(&mut self) -> (u8, u8) {
490        let registers = self.next();
491        return (registers >> 4, registers & 0b00001111);
492    }
493
494    fn get_register_value(&self, register_id: u8) -> Option<u16> {
495        self.registers
496            .r
497            .get(register_id as usize)
498            .copied()
499            .or(match register_id {
500                4 => Some(self.registers.bp),
501                5 => Some(self.registers.sp),
502                _ => None,
503            })
504    }
505
506    fn load_register_address(&mut self) -> Option<u16> {
507        let register = self.next();
508        let address = self
509            .registers
510            .r
511            .get(register as usize)
512            .copied()
513            .or(match register {
514                4 => Some(self.registers.bp),
515                5 => Some(self.registers.sp),
516                _ => None,
517            });
518        address.map(|address| self.two_byte_memory().read(address))
519    }
520
521    fn load_register_address_offset(&mut self) -> Option<u16> {
522        let register = self.next();
523        let offset = self.load_immediate();
524        let address = self
525            .registers
526            .r
527            .get(register as usize)
528            .copied()
529            .or(match register {
530                4 => Some(self.registers.bp),
531                5 => Some(self.registers.sp),
532                _ => None,
533            });
534        address.map(|address| self.two_byte_memory().read(address.wrapping_add(offset)))
535    }
536
537    fn save_register(&mut self, register_id: u8, value: u16) -> Result<(), ()> {
538        if register_id > 5 {
539            return Err(());
540        }
541        if register_id == 4 {
542            self.registers.bp = value;
543            return Ok(());
544        }
545        if register_id == 5 {
546            self.registers.sp = value;
547            return Ok(());
548        }
549        self.registers.r[register_id as usize] = value;
550        Ok(())
551    }
552}
553
554impl Processor<u8, u16, u16, u16> for CiscProcessor {
555    fn next(&mut self) -> u8 {
556        let instruction = self.memory[self.registers.pc as usize];
557        self.registers.pc = self.registers.pc.wrapping_add(1);
558        instruction
559    }
560
561    fn at_pc_plus(&self, offset: u16) -> u8 {
562        self.memory[self.registers.pc.wrapping_add(offset) as usize]
563    }
564
565    fn pc(&self) -> u16 {
566        self.registers.pc
567    }
568
569    fn peek_stack(&mut self, n: u8) -> u16 {
570        self.memory_stack().peek_down_by(n * 2)
571    }
572
573    fn run_command<T, U>(&mut self, output: T, input: U) -> ProcessorContinue
574    where
575        T: Fn(u16, u16),
576        U: Fn(u16) -> u16,
577    {
578        let next_instruction = self.next();
579        let next_instruction_as_enum = match Opcode::from_u8(next_instruction.into()) {
580            Some(opcode) => opcode,
581            None => {
582                return ProcessorContinue::Error;
583            }
584        };
585        match next_instruction_as_enum {
586            Opcode::Halt => ProcessorContinue::Halt,
587            Opcode::MovRegImm => save_to_register!(self, || self.load_immediate()),
588            Opcode::MovRegReg => {
589                with_register_id_and_register_value!(self, |destination, value| {
590                    match self.save_register(destination, value) {
591                        Ok(_) => ProcessorContinue::KeepRunning,
592                        Err(_) => ProcessorContinue::Error,
593                    }
594                })
595            }
596            Opcode::MovRegRegAdr => {
597                with_register_id_and_register_address!(self, |destination, value| {
598                    match self.save_register(destination, value) {
599                        Ok(_) => ProcessorContinue::KeepRunning,
600                        Err(_) => ProcessorContinue::Error,
601                    }
602                })
603            }
604            Opcode::MovRegRegAdrOff => {
605                with_register_id_and_register_address_offset!(self, |destination, value| {
606                    match self.save_register(destination, value) {
607                        Ok(_) => ProcessorContinue::KeepRunning,
608                        Err(_) => ProcessorContinue::Error,
609                    }
610                })
611            }
612            Opcode::MovRegAdrReg => {
613                let (destination, source) = self.load_two_register_ids();
614                let value = match self.get_register_value(source) {
615                    Some(value) => value,
616                    None => return ProcessorContinue::Error,
617                };
618                match self.save_register(destination, value) {
619                    Ok(_) => ProcessorContinue::KeepRunning,
620                    Err(_) => ProcessorContinue::Error,
621                }
622            }
623            Opcode::MovRegAdrImm => save_to_register_address!(self, || self.load_immediate()),
624            Opcode::MovRegAdrOffReg => {
625                save_optional_to_register_address_offset!(self, || self.load_register())
626            }
627            Opcode::MovRegAdrOffImm => {
628                save_to_register_address_offset!(self, || self.load_immediate())
629            }
630            Opcode::PushReg => push_optional_result!(self, || self.load_register()),
631            Opcode::PushImm => push_result!(self, || self.load_immediate()),
632            Opcode::PopReg => save_to_register!(self, || self.memory_stack().pop()),
633            Opcode::EnterImm => {
634                let offset = self.load_immediate();
635                let bp = self.registers.bp;
636                self.memory_stack().push(bp);
637                self.registers.bp = self.registers.sp;
638                self.registers.sp = self.registers.sp.wrapping_sub(offset);
639                ProcessorContinue::KeepRunning
640            }
641            Opcode::Leave => {
642                let bp = self.memory_stack().pop();
643                self.registers.sp = self.registers.bp;
644                self.registers.bp = bp;
645                ProcessorContinue::KeepRunning
646            }
647
648            // Arithmetic operations:
649            Opcode::AddRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::add),
650            Opcode::AddRegReg => arithmetic_reg_reg!(self, arithmetic::add),
651            Opcode::AddRegRegAdrOff => arithmetic_reg_reg_addr_off!(self, arithmetic::add),
652            Opcode::AddRegAdrReg => arithmetic_reg_addr_reg!(self, arithmetic::add),
653
654            Opcode::SubRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::sub),
655            Opcode::SubRegReg => arithmetic_reg_reg!(self, arithmetic::sub),
656            Opcode::SubRegRegAdrOff => arithmetic_reg_reg_addr_off!(self, arithmetic::sub),
657            Opcode::SubRegAdrReg => arithmetic_reg_addr_reg!(self, arithmetic::sub),
658
659            Opcode::IncReg => arithmetic_reg!(self, arithmetic::inc),
660            Opcode::IncRegAdr => arithmetic_reg_addr!(self, arithmetic::inc),
661            Opcode::IncRegAdrOff => arithmetic_reg_addr_offset!(self, arithmetic::inc),
662            Opcode::DecReg => arithmetic_reg!(self, arithmetic::dec),
663            Opcode::DecRegAdr => arithmetic_reg_addr!(self, arithmetic::dec),
664            Opcode::DecRegAdrOff => arithmetic_reg_addr_offset!(self, arithmetic::dec),
665
666            Opcode::MulRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::mul),
667            Opcode::MulRegReg => arithmetic_reg_reg!(self, arithmetic::mul),
668            Opcode::MulRegRegAdrOff => arithmetic_reg_reg_addr_off!(self, arithmetic::mul),
669            Opcode::MulRegImm => arithmetic_reg_imm!(self, arithmetic::mul),
670            Opcode::MulRegAdrReg => arithmetic_reg_addr_reg!(self, arithmetic::mul),
671
672            Opcode::DivRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::div),
673            Opcode::DivRegReg => arithmetic_reg_reg!(self, arithmetic::div),
674            Opcode::DivRegRegAdrOff => arithmetic_reg_reg_addr_off!(self, arithmetic::div),
675            Opcode::DivRegImm => arithmetic_reg_imm!(self, arithmetic::div),
676            Opcode::DivRegAdrReg => arithmetic_reg_addr_reg!(self, arithmetic::div),
677
678            Opcode::AndRegReg => arithmetic_reg_reg!(self, arithmetic::and),
679            Opcode::AndRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::and),
680            Opcode::OrRegReg => arithmetic_reg_reg!(self, arithmetic::or),
681            Opcode::OrRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::or),
682            Opcode::XorRegReg => arithmetic_reg_reg!(self, arithmetic::xor),
683            Opcode::XorRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::xor),
684            Opcode::NotReg => arithmetic_reg!(self, arithmetic::not),
685            Opcode::NotRegAdr => arithmetic_reg_addr!(self, arithmetic::not),
686
687            Opcode::LshRegImm => arithmetic_reg_imm!(self, arithmetic::shl),
688            Opcode::LshRegAdrImm => arithmetic_reg_addr_imm!(self, arithmetic::shl),
689            Opcode::LshRegAdrOffImm => arithmetic_reg_addr_offset_imm!(self, arithmetic::shl),
690
691            Opcode::RshRegImm => arithmetic_reg_imm!(self, arithmetic::shr),
692            Opcode::RshRegAdrImm => arithmetic_reg_addr_imm!(self, arithmetic::shr),
693            Opcode::RshRegAdrOffImm => arithmetic_reg_addr_offset_imm!(self, arithmetic::shr),
694
695            // End of arithmetic operations, other than for comparisons
696            Opcode::CallImm => with_immediate!(self, |immediate| {
697                let pc = self.registers.pc;
698                self.memory_stack().push(pc);
699                self.registers.pc = immediate;
700            }),
701            Opcode::CallReg => with_register_value!(self, |value| {
702                let pc = self.registers.pc;
703                self.memory_stack().push(pc);
704                self.registers.pc = value;
705            }),
706            Opcode::CallRegOff => with_register_address_offset_as_address!(self, |address| {
707                let pc = self.registers.pc;
708                self.memory_stack().push(pc);
709                self.registers.pc = address;
710            }),
711            Opcode::Ret => {
712                let pc = self.memory_stack().pop();
713                self.registers.pc = pc;
714                ProcessorContinue::KeepRunning
715            }
716
717            // Comparison operations
718            Opcode::CmpRegReg => arithmetic_reg_reg!(self, arithmetic::cmp),
719            Opcode::CmpRegImm => arithmetic_reg_imm!(self, arithmetic::cmp),
720            Opcode::CmpRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::cmp),
721            Opcode::CmpRegRegAdrOff => arithmetic_reg_reg_addr_off!(self, arithmetic::cmp),
722            Opcode::TestRegReg => arithmetic_reg_reg!(self, arithmetic::test),
723            Opcode::TestRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::test),
724            Opcode::TestRegRegAdrOff => arithmetic_reg_reg_addr_off!(self, arithmetic::test),
725            // End of comparison operations
726            Opcode::JmpImm => with_immediate!(self, |immediate| self.registers.pc = immediate),
727            Opcode::JmpReg => with_register_value!(self, |value| self.registers.pc = value),
728            Opcode::JmpRegOff => {
729                with_register_address_offset_as_address!(self, |address| self.registers.pc =
730                    address)
731            }
732            Opcode::JeImm => with_immediate!(self, |immediate| {
733                if self.registers.fr.get(ProcessorFlags::ZF) {
734                    self.registers.pc = immediate;
735                }
736            }),
737            Opcode::JneImm => with_immediate!(self, |immediate| {
738                if !self.registers.fr.get(ProcessorFlags::ZF) {
739                    self.registers.pc = immediate;
740                }
741            }),
742            Opcode::JgImm => with_immediate!(self, |immediate| {
743                if !self.registers.fr.get(ProcessorFlags::ZF)
744                    && (self.registers.fr.get(ProcessorFlags::SF)
745                        == self.registers.fr.get(ProcessorFlags::OF))
746                {
747                    self.registers.pc = immediate;
748                }
749            }),
750            Opcode::JgeImm => with_immediate!(self, |immediate| {
751                if !self.registers.fr.get(ProcessorFlags::CF) {
752                    self.registers.pc = immediate;
753                }
754            }),
755            Opcode::JlImm => with_immediate!(self, |immediate| {
756                if self.registers.fr.get(ProcessorFlags::SF)
757                    != self.registers.fr.get(ProcessorFlags::OF)
758                {
759                    self.registers.pc = immediate;
760                }
761            }),
762            Opcode::JleImm => with_immediate!(self, |immediate| {
763                if self.registers.fr.get(ProcessorFlags::ZF)
764                    || self.registers.fr.get(ProcessorFlags::CF)
765                {
766                    self.registers.pc = immediate;
767                }
768            }),
769
770            Opcode::InRegPort => {
771                save_to_register!(self, || with_immediate_raw!(self, input))
772            }
773            Opcode::InRegAdrPort => {
774                save_to_register_address!(self, || with_immediate_raw!(self, input))
775            }
776            Opcode::InRegAdrOffPort => {
777                save_to_register_address_offset!(self, || with_immediate_raw!(self, input))
778            }
779            Opcode::OutPortImm => {
780                with_immediate!(self, |port| with_register_value!(self, |immediate| {
781                    output(port, immediate)
782                }))
783            }
784            Opcode::OutPortReg => {
785                with_immediate!(self, |port| with_register_value!(self, |value| output(
786                    port, value
787                )))
788            }
789            Opcode::OutPortRegAdr => {
790                with_immediate!(self, |port| with_register_address!(self, |address| output(
791                    port, address
792                )))
793            }
794            Opcode::OutPortRegAdrOff => {
795                with_immediate_raw!(self, |port| with_register_address_offset!(self, |value| {
796                    match value {
797                        Some(value) => {
798                            output(port, value);
799                            ProcessorContinue::KeepRunning
800                        }
801                        None => ProcessorContinue::Error,
802                    }
803                }))
804            }
805            Opcode::Nop => ProcessorContinue::KeepRunning,
806        }
807    }
808
809    fn load_executable(&mut self, executable: &Executable) -> Result<(), String> {
810        unimplemented!()
811    }
812}