diff options
author | Ben Bridle <bridle.benjamin@gmail.com> | 2024-10-28 20:11:15 +1300 |
---|---|---|
committer | Ben Bridle <bridle.benjamin@gmail.com> | 2024-10-28 20:11:15 +1300 |
commit | 4738b8581e932174f9ab99d21c6a24024fb6414d (patch) | |
tree | 7e0f53318a1292bb283518c80dec647bf17946a5 | |
parent | b0d04c9b28efc90bc6f1cfcc6d2c4d3e646099fb (diff) | |
download | bedrock-core-4738b8581e932174f9ab99d21c6a24024fb6414d.zip |
Restructure the library
The main type of the library is now the BedrockEmulator type, which
contains a new BedrockCore type and an instance of a user-implemented
DeviceBus trait.
This new structure makes it possible to hot-swap a device bus while
a BedrockEmulator is running, which keeps the core and the device bus
well separated. This was important when bedrock-pc was going to have
two graphical emulator types and upgrade from one to the other once
the screen device was accessed.
The new structure also vastly simplifies the code previously required
with the old Bedrock type, which was parametric over 16 device types
and so needed each device type to be enumerated in every place the
Bedrock type was stored. The new BedrockEmulator type is only
parametric over the particular DeviceBus implementation.
-rw-r--r-- | src/bedrock.rs | 22 | ||||
-rw-r--r-- | src/core.rs | 20 | ||||
-rw-r--r-- | src/device_bus.rs | 71 | ||||
-rw-r--r-- | src/emulator.rs | 16 | ||||
-rw-r--r-- | src/lib.rs | 24 | ||||
-rw-r--r-- | src/processor.rs | 164 | ||||
-rw-r--r-- | src/signal.rs | 12 |
7 files changed, 145 insertions, 184 deletions
diff --git a/src/bedrock.rs b/src/bedrock.rs deleted file mode 100644 index 8d03e12..0000000 --- a/src/bedrock.rs +++ /dev/null @@ -1,22 +0,0 @@ -use crate::*; - - -pub struct Bedrock<D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,DA,DB,DC,DD,DE,DF> { - pub mem: ProgramMemory, - pub wst: Stack, - pub rst: Stack, - pub dev: DeviceBus<D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,DA,DB,DC,DD,DE,DF>, - pub cyc: usize, -} - -impl<D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,DA,DB,DC,DD,DE,DF> Bedrock<D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,DA,DB,DC,DD,DE,DF> { - pub fn new(device_bus: DeviceBus<D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,DA,DB,DC,DD,DE,DF>) -> Self { - Self { - mem: ProgramMemory::new(), - wst: Stack::new(), - rst: Stack::new(), - dev: device_bus, - cyc: 0, - } - } -} diff --git a/src/core.rs b/src/core.rs new file mode 100644 index 0000000..2143e3d --- /dev/null +++ b/src/core.rs @@ -0,0 +1,20 @@ +use crate::*; + + +pub struct BedrockCore { + pub mem: ProgramMemory, + pub wst: Stack, + pub rst: Stack, + pub cycle: usize, +} + +impl BedrockCore { + pub fn new() -> Self { + Self { + mem: ProgramMemory::new(), + wst: Stack::new(), + rst: Stack::new(), + cycle: 0, + } + } +} diff --git a/src/device_bus.rs b/src/device_bus.rs index aaa0717..6a04f66 100644 --- a/src/device_bus.rs +++ b/src/device_bus.rs @@ -1,6 +1,5 @@ use crate::*; - pub trait Device { fn read(&mut self, port: u8) -> u8; fn write(&mut self, port: u8, value: u8) -> Option<Signal>; @@ -13,70 +12,8 @@ impl Device for () { fn wake(&mut self) -> bool { false } } - -pub struct DeviceBus<D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,DA,DB,DC,DD,DE,DF> { - pub dev_0: D0, - pub dev_1: D1, - pub dev_2: D2, - pub dev_3: D3, - pub dev_4: D4, - pub dev_5: D5, - pub dev_6: D6, - pub dev_7: D7, - pub dev_8: D8, - pub dev_9: D9, - pub dev_a: DA, - pub dev_b: DB, - pub dev_c: DC, - pub dev_d: DD, - pub dev_e: DE, - pub dev_f: DF, -} - -impl<D0:Device, D1:Device, D2:Device, D3:Device, D4:Device, D5:Device, D6:Device, D7:Device, - D8:Device, D9:Device, DA:Device, DB:Device, DC:Device, DD:Device, DE:Device, DF:Device> -DeviceBus<D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,DA,DB,DC,DD,DE,DF> { - pub fn read_u8(&mut self, port: u8) -> u8 { - match port & 0xf0 { - 0x00 => self.dev_0.read(port & 0x0f), - 0x10 => self.dev_1.read(port & 0x0f), - 0x20 => self.dev_2.read(port & 0x0f), - 0x30 => self.dev_3.read(port & 0x0f), - 0x40 => self.dev_4.read(port & 0x0f), - 0x50 => self.dev_5.read(port & 0x0f), - 0x60 => self.dev_6.read(port & 0x0f), - 0x70 => self.dev_7.read(port & 0x0f), - 0x80 => self.dev_8.read(port & 0x0f), - 0x90 => self.dev_9.read(port & 0x0f), - 0xA0 => self.dev_a.read(port & 0x0f), - 0xB0 => self.dev_b.read(port & 0x0f), - 0xC0 => self.dev_c.read(port & 0x0f), - 0xD0 => self.dev_d.read(port & 0x0f), - 0xE0 => self.dev_e.read(port & 0x0f), - 0xF0 => self.dev_f.read(port & 0x0f), - _ => unreachable!(), - } - } - - pub fn write_u8(&mut self, port: u8, value: u8) -> Option<Signal> { - match port & 0xf0 { - 0x00 => self.dev_0.write(port & 0x0f, value), - 0x10 => self.dev_1.write(port & 0x0f, value), - 0x20 => self.dev_2.write(port & 0x0f, value), - 0x30 => self.dev_3.write(port & 0x0f, value), - 0x40 => self.dev_4.write(port & 0x0f, value), - 0x50 => self.dev_5.write(port & 0x0f, value), - 0x60 => self.dev_6.write(port & 0x0f, value), - 0x70 => self.dev_7.write(port & 0x0f, value), - 0x80 => self.dev_8.write(port & 0x0f, value), - 0x90 => self.dev_9.write(port & 0x0f, value), - 0xA0 => self.dev_a.write(port & 0x0f, value), - 0xB0 => self.dev_b.write(port & 0x0f, value), - 0xC0 => self.dev_c.write(port & 0x0f, value), - 0xD0 => self.dev_d.write(port & 0x0f, value), - 0xE0 => self.dev_e.write(port & 0x0f, value), - 0xF0 => self.dev_f.write(port & 0x0f, value), - _ => unreachable!(), - } - } +pub trait DeviceBus { + fn read(&mut self, port: u8) -> u8; + fn write(&mut self, port: u8, value: u8) -> Option<Signal>; + fn wake(&mut self) -> bool; } diff --git a/src/emulator.rs b/src/emulator.rs new file mode 100644 index 0000000..d149ddd --- /dev/null +++ b/src/emulator.rs @@ -0,0 +1,16 @@ +use crate::*; + + +pub struct BedrockEmulator<DB> { + pub core: BedrockCore, + pub dev: DB, +} + +impl<DB: DeviceBus> BedrockEmulator<DB> { + pub fn new(device_bus: DB) -> Self { + Self { + core: BedrockCore::new(), + dev: device_bus, + } + } +} @@ -1,21 +1,31 @@ -mod bedrock; -mod device_bus; mod processor; mod program_memory; mod stack; -pub use bedrock::Bedrock; -pub use device_bus::{Device, DeviceBus}; -pub use processor::Signal; pub use program_memory::ProgramMemory; pub use stack::Stack; +mod core; +mod device_bus; +mod signal; +mod emulator; + +pub use core::BedrockCore; +pub use device_bus::{Device, DeviceBus}; +pub use signal::Signal; +pub use emulator::BedrockEmulator; + + pub mod macros { #[macro_export] macro_rules! read_hh { ($v:expr) => { ($v>>24) as u8 }; } #[macro_export] macro_rules! read_hl { ($v:expr) => { ($v>>16) as u8 }; } #[macro_export] + macro_rules! read_lh { ($v:expr) => { ($v>>8) as u8 }; } + #[macro_export] + macro_rules! read_ll { ($v:expr) => { $v as u8 }; } + #[macro_export] macro_rules! read_h { ($v:expr) => { ($v>>8) as u8 }; } #[macro_export] macro_rules! read_l { ($v:expr) => { $v as u8 }; } @@ -27,6 +37,10 @@ pub mod macros { #[macro_export] macro_rules! write_hl { ($v:expr, $low:expr) => { $v = $v & 0xff00ffff | (($low as u32) << 16) }; } #[macro_export] + macro_rules! write_lh { ($v:expr, $high:expr) => { $v = $v & 0xffff00ff | (($high as u32) << 8) }; } + #[macro_export] + macro_rules! write_ll { ($v:expr, $low:expr) => { $v = $v & 0xffffff00 | ($low as u32) }; } + #[macro_export] macro_rules! write_h { ($v:expr, $high:expr) => { $v = $v & 0x00ff | (($high as u16) << 8) }; } #[macro_export] macro_rules! write_l { ($v:expr, $low:expr) => { $v = $v & 0xff00 | ($low as u16) }; } diff --git a/src/processor.rs b/src/processor.rs index dc55e4b..2934e11 100644 --- a/src/processor.rs +++ b/src/processor.rs @@ -1,44 +1,29 @@ +use emulator::BedrockEmulator; + use crate::*; use std::ops::*; -#[derive(Copy, Clone, Debug)] -pub enum Signal { - Sleep, - Fork, - Halt, - Debug1, - Debug2, - Debug3, - Debug4, - Debug5, - Debug6, -} - - -impl < - D0:Device, D1:Device, D2:Device, D3:Device, D4:Device, D5:Device, D6:Device, D7:Device, - D8:Device, D9:Device, DA:Device, DB:Device, DC:Device, DD:Device, DE:Device, DF:Device, -> Bedrock<D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,DA,DB,DC,DD,DE,DF> { - pub fn evaluate(&mut self, cycles: usize) -> Option<Signal> { - macro_rules! WPSH1 { ($x:expr) => { self.wst.push_u8($x) }; } - macro_rules! RPSH1 { ($x:expr) => { self.rst.push_u8($x) }; } +impl <DB: DeviceBus> BedrockEmulator<DB> { + pub fn evaluate(&mut self, cycles: usize, debug: bool) -> Option<Signal> { + macro_rules! WPSH1 { ($x:expr) => { self.core.wst.push_u8($x) }; } + macro_rules! RPSH1 { ($x:expr) => { self.core.rst.push_u8($x) }; } macro_rules! WPSH2 { ($x:expr,$y:expr) => { WPSH1!($x); WPSH1!($y); }; } - macro_rules! RPSH2 { ($x:expr,$y:expr) => { WPSH1!($x); WPSH1!($y); }; } - macro_rules! WPSHD { ($d:expr) => { self.wst.push_u16($d) }; } - macro_rules! RPSHD { ($d:expr) => { self.rst.push_u16($d) }; } - macro_rules! WPSHB { ($x:expr) => { self.wst.push_u8(0u8.wrapping_sub($x as u8)) }; } - macro_rules! RPSHB { ($x:expr) => { self.rst.push_u8(0u8.wrapping_sub($x as u8)) }; } + macro_rules! RPSH2 { ($x:expr,$y:expr) => { RPSH1!($x); RPSH1!($y); }; } + macro_rules! WPSHD { ($d:expr) => { self.core.wst.push_u16($d) }; } + macro_rules! RPSHD { ($d:expr) => { self.core.rst.push_u16($d) }; } + macro_rules! WPSHB { ($x:expr) => { self.core.wst.push_u8(0u8.wrapping_sub($x as u8)) }; } + macro_rules! RPSHB { ($x:expr) => { self.core.rst.push_u8(0u8.wrapping_sub($x as u8)) }; } - macro_rules! WPOP1 { ($x:ident) => { let $x = self.wst.pop_u8(); }; } - macro_rules! RPOP1 { ($x:ident) => { let $x = self.rst.pop_u8(); }; } + macro_rules! WPOP1 { ($x:ident) => { let $x = self.core.wst.pop_u8(); }; } + macro_rules! RPOP1 { ($x:ident) => { let $x = self.core.rst.pop_u8(); }; } macro_rules! WPOP2 { ($x:ident,$y:ident) => { WPOP1!($y); WPOP1!($x); }; } - macro_rules! RPOP2 { ($x:ident,$y:ident) => { WPOP1!($y); WPOP1!($x); }; } - macro_rules! WPOPD { ($d:ident) => { let $d = self.wst.pop_u16(); }; } - macro_rules! RPOPD { ($d:ident) => { let $d = self.rst.pop_u16(); }; } + macro_rules! RPOP2 { ($x:ident,$y:ident) => { RPOP1!($y); RPOP1!($x); }; } + macro_rules! WPOPD { ($d:ident) => { let $d = self.core.wst.pop_u16(); }; } + macro_rules! RPOPD { ($d:ident) => { let $d = self.core.rst.pop_u16(); }; } - macro_rules! WGETV { ($i:expr) => { self.wst.mem[self.wst.sp.wrapping_sub($i) as usize] }; } - macro_rules! RGETV { ($i:expr) => { self.rst.mem[self.rst.sp.wrapping_sub($i) as usize] }; } + macro_rules! WGETV { ($i:expr) => { self.core.wst.mem[self.core.wst.sp.wrapping_sub($i) as usize] }; } + macro_rules! RGETV { ($i:expr) => { self.core.rst.mem[self.core.rst.sp.wrapping_sub($i) as usize] }; } macro_rules! WGET1 { ($x:ident) => { let $x = WGETV!(1); }; } macro_rules! RGET1 { ($x:ident) => { let $x = RGETV!(1); }; } macro_rules! WGET1N { ($x:ident) => { let $x = WGETV!(2); }; } @@ -52,31 +37,30 @@ impl < macro_rules! WGETDN { ($d:ident) => { let $d = u16::from_be_bytes([WGETV!(4),WGETV!(3)]); }; } macro_rules! RGETDN { ($d:ident) => { let $d = u16::from_be_bytes([RGETV!(4),RGETV!(3)]); }; } - macro_rules! MEM { ($a:expr) => { self.mem.mem[$a as usize] }; } - macro_rules! MEMN { ($a:expr) => { self.mem.mem[$a.wrapping_add(1) as usize] }; } - macro_rules! DEV { ($p:expr) => { self.dev.read_u8($p) }; } - macro_rules! DEVN { ($p:expr) => { self.dev.read_u8($p.wrapping_add(1)) }; } + macro_rules! PCSET { ($a:expr) => { self.core.mem.pc=$a }; } + macro_rules! MEM { ($a:expr) => { self.core.mem.mem[$a as usize] }; } + macro_rules! MEMN { ($a:expr) => { self.core.mem.mem[$a.wrapping_add(1) as usize] }; } + macro_rules! DEV { ($p:expr) => { self.dev.read($p) }; } + macro_rules! DEVN { ($p:expr) => { self.dev.read($p.wrapping_add(1)) }; } - macro_rules! MLIT1 { ($x:ident) => { let $x = self.mem.read_u8_next(); }; } + macro_rules! MLIT1 { ($x:ident) => { let $x = self.core.mem.read_u8_next(); }; } macro_rules! MLIT2 { ($x:ident,$y:ident) => { MLIT1!($x); MLIT1!($y); }; } - macro_rules! MLITD { ($d:ident) => { let $d = self.mem.read_u16_next(); }; } + macro_rules! MLITD { ($d:ident) => { let $d = self.core.mem.read_u16_next(); }; } macro_rules! DSET1 { ($p:expr,$x:expr) => { - let s = self.dev.write_u8($p, $x); + let s = self.dev.write($p, $x); if s.is_some() { return s }; }; } macro_rules! DSET2 { ($p:expr,$x:expr,$y:expr) => { - let s1 = self.dev.write_u8($p, $x); - let s2 = self.dev.write_u8($p.wrapping_add(1), $y); - match s1.is_some() { - true => s1, - false => s2, - } + let s1 = self.dev.write($p, $x); + let s2 = self.dev.write($p.wrapping_add(1), $y); + if s1.is_some() { return s1 }; + if s2.is_some() { return s2 }; }; } macro_rules! math { - ($v:expr; ADD $i:expr) => { $v = $v.wrapping_sub($i); }; - ($v:expr; SUB $i:expr) => { $v = $v.wrapping_add($i); }; + ($v:expr; ADD $i:expr) => { $v = $v.wrapping_add($i); }; + ($v:expr; SUB $i:expr) => { $v = $v.wrapping_sub($i); }; ($v:expr; IOR $i:expr) => { $v = $v.bitor($i); }; ($v:expr; XOR $i:expr) => { $v = $v.bitxor($i); }; ($v:expr; AND $i:expr) => { $v = $v.bitand($i); }; @@ -101,21 +85,21 @@ impl < }; } - let end = self.cyc + cycles; - while self.cyc < end { - self.cyc += 1; + let end = self.core.cycle + cycles; + while self.core.cycle < end { + self.core.cycle += 1; - match self.mem.read_u8_next() { + match self.core.mem.read_u8_next() { /* HLT */ 0x00 => { return Some(Signal::Halt); } - /* JMP */ 0x01 => { WPOPD!(a); self.mem.pc=a; } - /* JCN */ 0x02 => { WPOPD!(a); WPOP1!(t); if t!=0 {self.mem.pc=a}; } - /* JCK */ 0x03 => { WPOPD!(a); WGET1!(t); if t!=0 {self.mem.pc=a}; } + /* JMP */ 0x01 => { WPOPD!(a); PCSET!(a); } + /* JCN */ 0x02 => { WPOPD!(a); WPOP1!(t); if t!=0 {PCSET!(a)}; } + /* JCK */ 0x03 => { WPOPD!(a); WGET1!(t); if t!=0 {PCSET!(a)}; } /* LDA */ 0x04 => { WPOPD!(a); WPSH1!(MEM!(a)); } /* STA */ 0x05 => { WPOPD!(a); WPOP1!(x); MEM!(a)=x; } /* LDD */ 0x06 => { WPOP1!(p); WPSH1!(DEV!(p)); } /* STD */ 0x07 => { WPOP1!(p); WPOP1!(x); DSET1!(p,x); } /* PSH */ 0x08 => { RPOP1!(x); WPSH1!(x); } - /* POP */ 0x09 => { math!(self.wst.sp; SUB 1); } + /* POP */ 0x09 => { math!(self.core.wst.sp; SUB 1); } /* CPY */ 0x0A => { RGET1!(x); WPSH1!(x); } /* SPL */ 0x0B => { WPOP1!(x); split!(x=>a,b); WPSH2!(a,b); } /* DUP */ 0x0C => { WGET1!(x); WPSH1!(x); } @@ -140,15 +124,15 @@ impl < /* REV */ 0x1F => { math!(WGETV!(1); REV); } /* NOP */ 0x20 => { } - /* JMS */ 0x21 => { WPOPD!(a); RPSHD!(self.mem.pc); self.mem.pc=a; } - /* JCS */ 0x22 => { WPOPD!(a); WPOP1!(t); if t!=0 {RPSHD!(self.mem.pc); self.mem.pc=a}; } - /* JCK* */ 0x23 => { WPOPD!(a); WGETD!(t); if t!=0 {self.mem.pc=a}; } + /* JMS */ 0x21 => { WPOPD!(a); RPSHD!(self.core.mem.pc); PCSET!(a); } + /* JCS */ 0x22 => { WPOPD!(a); WPOP1!(t); if t!=0 {RPSHD!(self.core.mem.pc); PCSET!(a)}; } + /* JCK* */ 0x23 => { WPOPD!(a); WGETD!(t); if t!=0 {PCSET!(a)}; } /* LDA* */ 0x24 => { WPOPD!(a); WPSH2!(MEM!(a),MEMN!(a)); } /* STA* */ 0x25 => { WPOPD!(a); WPOP2!(x,y); MEM!(a)=x; MEMN!(a)=y; } /* LDD* */ 0x26 => { WPOP1!(p); WPSH2!(DEV!(p),DEVN!(p)); } /* STD* */ 0x27 => { WPOP1!(p); WPOP2!(x,y); DSET2!(p,x,y); } /* PSH* */ 0x28 => { RPOP2!(x,y); WPSH2!(x,y); } - /* POP* */ 0x29 => { math!(self.wst.sp; SUB 2); } + /* POP* */ 0x29 => { math!(self.core.wst.sp; SUB 2); } /* CPY* */ 0x2A => { RGET2!(x,y); WPSH2!(x,y); } /* SPL* */ 0x2B => { WPOP2!(x,y); split!(x=>a,b); split!(y=>c,d); WPSH2!(a,b); WPSH2!(c,d); } /* DUP* */ 0x2C => { WGET2!(x,y); WPSH2!(x,y); } @@ -172,16 +156,16 @@ impl < /* TAL* */ 0x3E => { WPOPD!(x); WPSH1!(x.count_ones() as u8); } /* REV* */ 0x3F => { WPOPD!(x); WPSHD!(x.reverse_bits()); } - /* DB1 */ 0x40 => { return Some(Signal::Debug1); } - /* JMP: */ 0x41 => { MLITD!(a); self.mem.pc=a; } - /* JCN: */ 0x42 => { MLITD!(a); WPOP1!(t); if t!=0 {self.mem.pc=a}; } - /* JCK: */ 0x43 => { MLITD!(a); WGET1!(t); if t!=0 {self.mem.pc=a}; } + /* DB1 */ 0x40 => { if debug { return Some(Signal::Debug1); } } + /* JMP: */ 0x41 => { MLITD!(a); PCSET!(a); } + /* JCN: */ 0x42 => { MLITD!(a); WPOP1!(t); if t!=0 {PCSET!(a)}; } + /* JCK: */ 0x43 => { MLITD!(a); WGET1!(t); if t!=0 {PCSET!(a)}; } /* LDA: */ 0x44 => { MLITD!(a); WPSH1!(MEM!(a)); } /* STA: */ 0x45 => { MLITD!(a); WPOP1!(x); MEM!(a)=x; } /* LDD: */ 0x46 => { MLIT1!(p); WPSH1!(DEV!(p)); } /* STD: */ 0x47 => { MLIT1!(p); WPOP1!(x); DSET1!(p,x); } /* PSH: */ 0x48 => { MLIT1!(x); WPSH1!(x); } - /* POP: */ 0x49 => { math!(self.mem.pc; ADD 1); } + /* POP: */ 0x49 => { math!(self.core.mem.pc; ADD 1); } /* CPY: */ 0x4A => { MLIT1!(x); WPSH1!(x); RPSH1!(x); } /* SPL: */ 0x4B => { MLIT1!(x); split!(x=>a,b); WPSH2!(a,b); } /* DUP: */ 0x4C => { MLIT1!(x); WPSH1!(x); WPSH1!(x); } @@ -205,16 +189,16 @@ impl < /* TAL: */ 0x5E => { MLIT1!(x); WPSH1!(x.count_ones() as u8); } /* REV: */ 0x5F => { MLIT1!(x); WPSH1!(x.reverse_bits()); } - /* DB2 */ 0x60 => { return Some(Signal::Debug2); } - /* JMS: */ 0x61 => { MLITD!(a); RPSHD!(self.mem.pc); self.mem.pc=a; } - /* JCS: */ 0x62 => { MLITD!(a); WPOP1!(t); if t!=0 {RPSHD!(self.mem.pc); self.mem.pc=a}; } - /* JCK*: */ 0x63 => { MLITD!(a); WGETD!(t); if t!=0 {self.mem.pc=a}; } + /* DB2 */ 0x60 => { if debug { return Some(Signal::Debug2); } } + /* JMS: */ 0x61 => { MLITD!(a); RPSHD!(self.core.mem.pc); PCSET!(a); } + /* JCS: */ 0x62 => { MLITD!(a); WPOP1!(t); if t!=0 {RPSHD!(self.core.mem.pc); PCSET!(a)}; } + /* JCK*: */ 0x63 => { MLITD!(a); WGETD!(t); if t!=0 {PCSET!(a)}; } /* LDA*: */ 0x64 => { MLITD!(a); WPSH2!(MEM!(a),MEMN!(a)); } /* STA*: */ 0x65 => { MLITD!(a); WPOP2!(x,y); MEM!(a)=x; MEMN!(a)=y; } /* LDD*: */ 0x66 => { MLIT1!(p); WPSH2!(DEV!(p),DEVN!(p)); } /* STD*: */ 0x67 => { MLIT1!(p); WPOP2!(x,y); DSET2!(p,x,y); } /* PSH*: */ 0x68 => { MLIT2!(x,y); WPSH2!(x,y); } - /* POP*: */ 0x69 => { math!(self.mem.pc; ADD 2); } + /* POP*: */ 0x69 => { math!(self.core.mem.pc; ADD 2); } /* CPY*: */ 0x6A => { MLIT2!(x,y); WPSH2!(x,y); RPSH2!(x,y); } /* SPL*: */ 0x6B => { MLIT2!(x,y); split!(x=>a,b); split!(y=>c,d); WPSH2!(a,b); WPSH2!(c,d); } /* DUP*: */ 0x6C => { MLIT2!(x,y); WPSH2!(x,y); WPSH2!(x,y); } @@ -238,16 +222,16 @@ impl < /* TAL*: */ 0x7E => { MLITD!(x); WPSH1!(x.count_ones() as u8); } /* REV*: */ 0x7F => { MLITD!(x); WPSHD!(x.reverse_bits()); } - /* DB3 */ 0x80 => { return Some(Signal::Debug3); } - /* JMPr */ 0x81 => { RPOPD!(a); self.mem.pc=a; } - /* JCNr */ 0x82 => { RPOPD!(a); RPOP1!(t); if t!=0 {self.mem.pc=a}; } - /* JCKr */ 0x83 => { RPOPD!(a); RGET1!(t); if t!=0 {self.mem.pc=a}; } + /* DB3 */ 0x80 => { if debug { return Some(Signal::Debug3); } } + /* JMPr */ 0x81 => { RPOPD!(a); PCSET!(a); } + /* JCNr */ 0x82 => { RPOPD!(a); RPOP1!(t); if t!=0 {PCSET!(a)}; } + /* JCKr */ 0x83 => { RPOPD!(a); RGET1!(t); if t!=0 {PCSET!(a)}; } /* LDAr */ 0x84 => { RPOPD!(a); RPSH1!(MEM!(a)); } /* STAr */ 0x85 => { RPOPD!(a); RPOP1!(x); MEM!(a)=x; } /* LDDr */ 0x86 => { RPOP1!(p); RPSH1!(DEV!(p)); } /* STDr */ 0x87 => { RPOP1!(p); RPOP1!(x); DSET1!(p,x); } /* PSHr */ 0x88 => { WPOP1!(x); RPSH1!(x); } - /* POPr */ 0x89 => { math!(self.rst.sp; SUB 1); } + /* POPr */ 0x89 => { math!(self.core.rst.sp; SUB 1); } /* CPYr */ 0x8A => { WGET1!(x); RPSH1!(x); } /* SPLr */ 0x8B => { RPOP1!(x); split!(x=>a,b); RPSH2!(a,b); } /* DUPr */ 0x8C => { RGET1!(x); RPSH1!(x); } @@ -271,16 +255,16 @@ impl < /* TALr */ 0x9E => { math!(RGETV!(1); TAL); } /* REVr */ 0x9F => { math!(RGETV!(1); REV); } - /* DB4 */ 0xA0 => { return Some(Signal::Debug4); } - /* JMSr */ 0xA1 => { RPOPD!(a); WPSHD!(self.mem.pc); self.mem.pc=a; } - /* JCSr */ 0xA2 => { RPOPD!(a); RPOP1!(t); if t!=0 {WPSHD!(self.mem.pc); self.mem.pc=a}; } - /* JCKr* */ 0xA3 => { RPOPD!(a); RGETD!(t); if t!=0 {self.mem.pc=a}; } + /* DB4 */ 0xA0 => { if debug { return Some(Signal::Debug4); } } + /* JMSr */ 0xA1 => { RPOPD!(a); WPSHD!(self.core.mem.pc); PCSET!(a); } + /* JCSr */ 0xA2 => { RPOPD!(a); RPOP1!(t); if t!=0 {WPSHD!(self.core.mem.pc); PCSET!(a)}; } + /* JCKr* */ 0xA3 => { RPOPD!(a); RGETD!(t); if t!=0 {PCSET!(a)}; } /* LDAr* */ 0xA4 => { RPOPD!(a); RPSH2!(MEM!(a),MEMN!(a)); } /* STAr* */ 0xA5 => { RPOPD!(a); RPOP2!(x,y); MEM!(a)=x; MEMN!(a)=y; } /* LDDr* */ 0xA6 => { RPOP1!(p); RPSH2!(DEV!(p),DEVN!(p)); } /* STDr* */ 0xA7 => { RPOP1!(p); RPOP2!(x,y); DSET2!(p,x,y); } /* PSHr* */ 0xA8 => { WPOP2!(x,y); RPSH2!(x,y); } - /* POPr* */ 0xA9 => { math!(self.rst.sp; SUB 2); } + /* POPr* */ 0xA9 => { math!(self.core.rst.sp; SUB 2); } /* CPYr* */ 0xAA => { WGET2!(x,y); RPSH2!(x,y); } /* SPLr* */ 0xAB => { RPOP2!(x,y); split!(x=>a,b); split!(y=>c,d); RPSH2!(a,b); RPSH2!(c,d); } /* DUPr* */ 0xAC => { RGET2!(x,y); RPSH2!(x,y); } @@ -304,16 +288,16 @@ impl < /* TALr* */ 0xBE => { RPOPD!(x); RPSH1!(x.count_ones() as u8); } /* REVr* */ 0xBF => { RPOPD!(x); RPSHD!(x.reverse_bits()); } - /* DB5 */ 0xC0 => { return Some(Signal::Debug5); } - /* JMPr: */ 0xC1 => { MLITD!(a); self.mem.pc=a; } - /* JCNr: */ 0xC2 => { MLITD!(a); RPOP1!(t); if t!=0 {self.mem.pc=a}; } - /* JCKr: */ 0xC3 => { MLITD!(a); RGET1!(t); if t!=0 {self.mem.pc=a}; } + /* DB5 */ 0xC0 => { if debug { return Some(Signal::Debug5); } } + /* JMPr: */ 0xC1 => { MLITD!(a); PCSET!(a); } + /* JCNr: */ 0xC2 => { MLITD!(a); RPOP1!(t); if t!=0 {PCSET!(a)}; } + /* JCKr: */ 0xC3 => { MLITD!(a); RGET1!(t); if t!=0 {PCSET!(a)}; } /* LDAr: */ 0xC4 => { MLITD!(a); RPSH1!(MEM!(a)); } /* STAr: */ 0xC5 => { MLITD!(a); RPOP1!(x); MEM!(a)=x; } /* LDDr: */ 0xC6 => { MLIT1!(p); RPSH1!(DEV!(p)); } /* STDr: */ 0xC7 => { MLIT1!(p); RPOP1!(x); DSET1!(p,x); } /* PSHr: */ 0xC8 => { MLIT1!(x); RPSH1!(x); } - /* POPr: */ 0xC9 => { math!(self.mem.pc; ADD 1); } + /* POPr: */ 0xC9 => { math!(self.core.mem.pc; ADD 1); } /* CPYr: */ 0xCA => { MLIT1!(x); RPSH1!(x); WPSH1!(x); } /* SPLr: */ 0xCB => { MLIT1!(x); split!(x=>a,b); RPSH2!(a,b); } /* DUPr: */ 0xCC => { MLIT1!(x); RPSH1!(x); RPSH1!(x); } @@ -337,16 +321,16 @@ impl < /* TALr: */ 0xDE => { MLIT1!(x); RPSH1!(x.count_ones() as u8); } /* REVr: */ 0xDF => { MLIT1!(x); RPSH1!(x.reverse_bits()); } - /* DB6 */ 0xE0 => { return Some(Signal::Debug6); } - /* JMSr: */ 0xE1 => { MLITD!(a); WPSHD!(self.mem.pc); self.mem.pc=a; } - /* JCSr: */ 0xE2 => { MLITD!(a); RPOP1!(t); if t!=0 {WPSHD!(self.mem.pc); self.mem.pc=a}; } - /* JCKr*: */ 0xE3 => { MLITD!(a); RGETD!(t); if t!=0 {self.mem.pc=a}; } + /* DB6 */ 0xE0 => { if debug { return Some(Signal::Debug6); } } + /* JMSr: */ 0xE1 => { MLITD!(a); WPSHD!(self.core.mem.pc); PCSET!(a); } + /* JCSr: */ 0xE2 => { MLITD!(a); RPOP1!(t); if t!=0 {WPSHD!(self.core.mem.pc); PCSET!(a)}; } + /* JCKr*: */ 0xE3 => { MLITD!(a); RGETD!(t); if t!=0 {PCSET!(a)}; } /* LDAr*: */ 0xE4 => { MLITD!(a); RPSH2!(MEM!(a),MEMN!(a)); } /* STAr*: */ 0xE5 => { MLITD!(a); RPOP2!(x,y); MEM!(a)=x; MEMN!(a)=y; } /* LDDr*: */ 0xE6 => { MLIT1!(p); RPSH2!(DEV!(p),DEVN!(p)); } /* STDr*: */ 0xE7 => { MLIT1!(p); RPOP2!(x,y); DSET2!(p,x,y); } /* PSHr*: */ 0xE8 => { MLIT2!(x,y); RPSH2!(x,y); } - /* POPr*: */ 0xE9 => { math!(self.mem.pc; ADD 2); } + /* POPr*: */ 0xE9 => { math!(self.core.mem.pc; ADD 2); } /* CPYr*: */ 0xEA => { MLIT2!(x,y); RPSH2!(x,y); WPSH2!(x,y); } /* SPLr*: */ 0xEB => { MLIT2!(x,y); split!(x=>a,b); split!(y=>c,d); RPSH2!(a,b); RPSH2!(c,d); } /* DUPr*: */ 0xEC => { MLIT2!(x,y); RPSH2!(x,y); RPSH2!(x,y); } diff --git a/src/signal.rs b/src/signal.rs new file mode 100644 index 0000000..9959901 --- /dev/null +++ b/src/signal.rs @@ -0,0 +1,12 @@ +#[derive(Copy, Clone, Debug)] +pub enum Signal { + Sleep, + Fork, + Halt, + Debug1, + Debug2, + Debug3, + Debug4, + Debug5, + Debug6, +} |