summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Bridle <bridle.benjamin@gmail.com>2024-09-30 12:28:24 +1300
committerBen Bridle <bridle.benjamin@gmail.com>2024-09-30 15:00:01 +1300
commitf4f129a75208ccf5d6a19b1cb81c56d4d95fd61f (patch)
treeb3b95f78edeb2cc48ccf207069631468b2705d55
parentf5986d0a37dd8c2526432e5e5e3af7083840447d (diff)
downloadbedrock-core-f4f129a75208ccf5d6a19b1cb81c56d4d95fd61f.zip
Make Bedrock parametric over devices
The core Bedrock struct is now parametric over individual Device structs, rather than over a single DeviceBus. This change was made so that devices can be implemented separately to one another. The implementation of the evaluate method has also been changed to make it potentially slightly more efficient, by replacing pop-then-push combinations with get operations.
-rw-r--r--src/bedrock.rs20
-rw-r--r--src/device_bus.rs85
-rw-r--r--src/lib.rs28
-rw-r--r--src/processor.rs657
-rw-r--r--src/program_memory.rs (renamed from src/memory.rs)26
-rw-r--r--src/stack.rs73
6 files changed, 476 insertions, 413 deletions
diff --git a/src/bedrock.rs b/src/bedrock.rs
new file mode 100644
index 0000000..19ccae6
--- /dev/null
+++ b/src/bedrock.rs
@@ -0,0 +1,20 @@
+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>,
+}
+
+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,
+ }
+ }
+}
diff --git a/src/device_bus.rs b/src/device_bus.rs
index 38a1a24..aaa0717 100644
--- a/src/device_bus.rs
+++ b/src/device_bus.rs
@@ -1,19 +1,82 @@
use crate::*;
-pub trait DeviceBus {
- fn read_u8(&mut self, port: u8) -> u8;
- fn write_u8(&mut self, value: u8, port: u8) -> Option<Signal>;
+pub trait Device {
+ fn read(&mut self, port: u8) -> u8;
+ fn write(&mut self, port: u8, value: u8) -> Option<Signal>;
+ fn wake(&mut self) -> bool;
+}
+
+impl Device for () {
+ fn read(&mut self, _: u8) -> u8 { 0 }
+ fn write(&mut self, _: u8, _: u8) -> Option<Signal> { None }
+ 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,
+}
- fn read_u16(&mut self, port: u8) -> u16 {
- let high = self.read_u8(port);
- let low = self.read_u8(port.wrapping_add(1));
- u16::from_be_bytes([high, low])
+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!(),
+ }
}
- fn write_u16(&mut self, value: u16, port: u8) -> Option<Signal> {
- let [h, l] = value.to_be_bytes();
- self.write_u8(h, port);
- self.write_u8(l, port.wrapping_add(1))
+ 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!(),
+ }
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 9161ba3..131078d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,26 +1,12 @@
+mod bedrock;
mod device_bus;
-mod memory;
mod processor;
+mod program_memory;
mod stack;
-pub use device_bus::*;
-pub use memory::*;
-pub use processor::*;
-pub use stack::*;
+pub use bedrock::Bedrock;
+pub use device_bus::{Device, DeviceBus};
+pub use processor::Signal;
+pub use program_memory::ProgramMemory;
+pub use stack::Stack;
-#[derive(Copy, Clone, Debug)]
-pub enum Signal {
- Debug(DebugVariant),
- Sleep,
- Halt,
-}
-
-#[derive(Copy, Clone, Debug)]
-pub enum DebugVariant {
- DB1,
- DB2,
- DB3,
- DB4,
- DB5,
- DB6,
-}
diff --git a/src/processor.rs b/src/processor.rs
index 16e5125..6c5362a 100644
--- a/src/processor.rs
+++ b/src/processor.rs
@@ -1,326 +1,371 @@
use crate::*;
use std::ops::*;
-pub struct Processor<D> {
- pub mem: Memory,
- pub wst: Stack,
- pub rst: Stack,
- pub dev: D,
- pub cycles: usize,
+
+#[derive(Copy, Clone, Debug)]
+pub enum Signal {
+ Sleep,
+ Fork,
+ Halt,
+ Debug1,
+ Debug2,
+ Debug3,
+ Debug4,
+ Debug5,
+ Debug6,
}
-impl<D: DeviceBus> Processor<D> {
- pub fn new(device_bus: D) -> Self {
- Self {
- mem: Memory::new(),
- wst: Stack::new(),
- rst: Stack::new(),
- dev: device_bus,
- cycles: 0,
- }
- }
- pub fn load_program(&mut self, bytecode: &[u8]) {
- self.mem.load_program(bytecode);
- }
+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) }; }
+ 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(if $x {0xff} else {0x00}) }; }
+ macro_rules! RPSHB { ($x:expr) => { self.rst.push_u8(if $x {0xff} else {0x00}) }; }
- pub fn evaluate(&mut self, num_cycles: usize) -> Option<Signal> {
- macro_rules! w_psh_8 { ($v:expr) => { self.wst.push_u8($v) }; }
- macro_rules! r_psh_8 { ($v:expr) => { self.rst.push_u8($v) }; }
- macro_rules! w_psh_16 { ($v:expr) => { self.wst.push_u16($v) }; }
- macro_rules! r_psh_16 { ($v:expr) => { self.rst.push_u16($v) }; }
- macro_rules! w_pop_8 { ($v:ident) => { let $v = self.wst.pop_u8(); }; }
- macro_rules! r_pop_8 { ($v:ident) => { let $v = self.rst.pop_u8(); }; }
- macro_rules! w_pop_16 { ($v:ident) => { let $v = self.wst.pop_u16(); }; }
- macro_rules! r_pop_16 { ($v:ident) => { let $v = self.rst.pop_u16(); }; }
- macro_rules! w_get_8 { ($v:ident) => { let $v = self.wst.get_u8(); }; }
- macro_rules! r_get_8 { ($v:ident) => { let $v = self.rst.get_u8(); }; }
- macro_rules! w_get_16 { ($v:ident) => { let $v = self.wst.get_u16(); }; }
- macro_rules! r_get_16 { ($v:ident) => { let $v = self.rst.get_u16(); }; }
- macro_rules! m_read_8 { ($a:expr) => { self.mem.read_u8($a) }; }
- macro_rules! m_read_16 { ($a:expr) => { self.mem.read_u16($a) }; }
- macro_rules! m_lit_8 { ($l:ident) => { let $l = self.mem.read_u8_next(); }; }
- macro_rules! m_lit_16 { ($l:ident) => { let $l = self.mem.read_u16_next(); }; }
- macro_rules! m_write_8 { ($v:expr,$a:expr) => { self.mem.write_u8($v,$a); }; }
- macro_rules! m_write_16 { ($v:expr,$a:expr) => { self.mem.write_u16($v,$a); }; }
- macro_rules! d_read_8 { ($p:expr) => { self.dev.read_u8($p) }; }
- macro_rules! d_read_16 { ($p:expr) => { self.dev.read_u16($p) }; }
- macro_rules! d_write_8 { ($v:expr,$p:expr) => { let s = self.dev.write_u8( $v, $p); if s.is_some() { return s }; }; }
- macro_rules! d_write_16 { ($v:expr,$p:expr) => { let s = self.dev.write_u16($v, $p); if s.is_some() { return s }; }; }
- macro_rules! jump { ($a:expr) => { self.mem.write_pc($a) }; }
- macro_rules! pc { () => { self.mem.read_pc() }; }
- macro_rules! truth { ($x:expr) => { if $x {0xff} else {0x00} }; }
- macro_rules! nyb { ($v:expr=>$h:ident,$l:ident) => { let $h=($v>>4); let $l=($v&0x0f); } }
- macro_rules! shf { ($x:expr,$y:expr) => { { nyb!($y=>l,r); $x.checked_shr(r as u32).unwrap_or(0).checked_shl(l as u32).unwrap_or(0) } } ; }
- macro_rules! shc { ($x:expr,$y:expr) => { { nyb!($y=>l,r); $x.rotate_right(r as u32).rotate_left(l as u32) } }; }
+ macro_rules! WPOP1 { ($x:ident) => { let $x = self.wst.pop_u8(); }; }
+ macro_rules! RPOP1 { ($x:ident) => { let $x = self.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(); }; }
- for _ in 0..num_cycles {
- self.cycles += 1;
+ 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! 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); }; }
+ macro_rules! RGET1N { ($x:ident) => { let $x = RGETV!(2); }; }
+ macro_rules! WGET2 { ($x:ident,$y:ident) => { let $x = WGETV!(2); let $y = WGETV!(1); }; }
+ macro_rules! RGET2 { ($x:ident,$y:ident) => { let $x = RGETV!(2); let $y = RGETV!(1); }; }
+ macro_rules! WGET2N { ($x:ident,$y:ident) => { let $x = WGETV!(4); let $y = WGETV!(3); }; }
+ macro_rules! RGET2N { ($x:ident,$y:ident) => { let $x = RGETV!(4); let $y = RGETV!(3); }; }
+ macro_rules! WGETD { ($d:ident) => { let $d = u16::from_be_bytes([WGETV!(2),WGETV!(1)]); }; }
+ macro_rules! RGETD { ($d:ident) => { let $d = u16::from_be_bytes([RGETV!(2),RGETV!(1)]); }; }
+ 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! MLIT1 { ($x:ident) => { let $x = self.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! DSET1 { ($p:expr,$x:expr) => {
+ let s = self.dev.write_u8($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,
+ }
+ }; }
+
+ 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; 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); };
+ ($v:expr; NOT ) => { $v = $v.not(); };
+ ($v:expr; TAL ) => { $v = $v.count_ones() as u8; };
+ ($v:expr; REV ) => { $v = $v.reverse_bits(); };
+ }
+
+ macro_rules! split {
+ ($v:expr=>$h:ident,$l:ident) => {
+ let $h=($v>>4); let $l=($v&0x0f);
+ }
+ }
+ macro_rules! shf {
+ ($x:expr,$y:expr) => {
+ { split!($y=>l,r); $x.checked_shr(r as u32).unwrap_or(0).checked_shl(l as u32).unwrap_or(0) }
+ };
+ }
+ macro_rules! shc {
+ ($x:expr,$y:expr) => {
+ { split!($y=>l,r); $x.rotate_right(r as u32).rotate_left(l as u32) }
+ };
+ }
+ for _ in 0..cycles {
match self.mem.read_u8_next() {
- /* HLT */ 0x00 => { return Some(Signal::Halt); }
- /* JMP */ 0x01 => { w_pop_16!(a); jump!(a); }
- /* JCN */ 0x02 => { w_pop_16!(a); w_pop_8!(t); if t!=0 {jump!(a)}; }
- /* JCK */ 0x03 => { w_pop_16!(a); w_get_8!(t); if t!=0 {jump!(a)}; }
- /* LDA */ 0x04 => { w_pop_16!(a); w_psh_8!(m_read_8!(a)); }
- /* STA */ 0x05 => { w_pop_16!(a); w_pop_8!(v); m_write_8!(v,a); }
- /* LDD */ 0x06 => { w_pop_8!(p); w_psh_8!(d_read_8!(p)); }
- /* STD */ 0x07 => { w_pop_8!(p); w_pop_8!(v); d_write_8!(v,p); }
- /* PSH */ 0x08 => { r_pop_8!(x); w_psh_8!(x); }
- /* POP */ 0x09 => { self.wst.sp = self.wst.sp.wrapping_sub(1); }
- /* CPY */ 0x0A => { r_get_8!(x); w_psh_8!(x); }
- /* SPL */ 0x0B => { w_pop_8!(x); nyb!(x=>a,b); w_psh_8!(a); w_psh_8!(b); }
- /* DUP */ 0x0C => { w_get_8!(x); w_psh_8!(x); }
- /* OVR */ 0x0D => { w_pop_8!(y); w_get_8!(x); w_psh_8!(y); w_psh_8!(x); }
- /* SWP */ 0x0E => { w_pop_8!(y); w_pop_8!(x); w_psh_8!(y); w_psh_8!(x); }
- /* ROT */ 0x0F => { w_pop_8!(z); w_pop_8!(y); w_pop_8!(x); w_psh_8!(y); w_psh_8!(z); w_psh_8!(x); }
- /* ADD */ 0x10 => { w_pop_8!(y); w_pop_8!(x); w_psh_8!(x.wrapping_add(y)); }
- /* SUB */ 0x11 => { w_pop_8!(y); w_pop_8!(x); w_psh_8!(x.wrapping_sub(y)); }
- /* INC */ 0x12 => { self.wst.inc_u8(); }
- /* DEC */ 0x13 => { self.wst.dec_u8(); }
- /* LTH */ 0x14 => { w_pop_8!(y); w_pop_8!(x); w_psh_8!(truth!(x < y)); }
- /* GTH */ 0x15 => { w_pop_8!(y); w_pop_8!(x); w_psh_8!(truth!(x > y)); }
- /* EQU */ 0x16 => { w_pop_8!(y); w_pop_8!(x); w_psh_8!(truth!(x==y)); }
- /* NQK */ 0x17 => { w_pop_8!(y); w_get_8!(x); w_psh_8!(y); w_psh_8!(truth!(x!=y)); }
- /* IOR */ 0x18 => { w_pop_8!(y); w_pop_8!(x); w_psh_8!(x.bitor(y)); }
- /* XOR */ 0x19 => { w_pop_8!(y); w_pop_8!(x); w_psh_8!(x.bitxor(y)); }
- /* AND */ 0x1A => { w_pop_8!(y); w_pop_8!(x); w_psh_8!(x.bitand(y)); }
- /* NOT */ 0x1B => { self.wst.not_u8(); }
- /* SHF */ 0x1C => { w_pop_8!(y); w_pop_8!(x); w_psh_8!(shf!(x,y)); }
- /* SHC */ 0x1D => { w_pop_8!(y); w_pop_8!(x); w_psh_8!(shc!(x,y)); }
- /* TAL */ 0x1E => { self.wst.tal_u8(); }
- /* REV */ 0x1F => { self.wst.rev_u8(); }
+ /* 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}; }
+ /* 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); }
+ /* CPY */ 0x0A => { RGET1!(x); WPSH1!(x); }
+ /* SPL */ 0x0B => { WPOP1!(x); split!(x=>a,b); WPSH2!(a,b); }
+ /* DUP */ 0x0C => { WGET1!(x); WPSH1!(x); }
+ /* OVR */ 0x0D => { WGET1N!(x); WPSH1!(x); }
+ /* SWP */ 0x0E => { WPOP1!(y); WPOP1!(x); WPSH1!(y); WPSH1!(x); }
+ /* ROT */ 0x0F => { WPOP1!(z); WPOP1!(y); WPOP1!(x); WPSH1!(y); WPSH1!(z); WPSH1!(x); }
+ /* ADD */ 0x10 => { WPOP1!(y); math!(WGETV!(1); ADD y); }
+ /* SUB */ 0x11 => { WPOP1!(y); math!(WGETV!(1); SUB y); }
+ /* INC */ 0x12 => { math!(WGETV!(1); ADD 1); }
+ /* DEC */ 0x13 => { math!(WGETV!(1); SUB 1); }
+ /* LTH */ 0x14 => { WPOP1!(y); WPOP1!(x); WPSHB!(x < y); }
+ /* GTH */ 0x15 => { WPOP1!(y); WPOP1!(x); WPSHB!(x > y); }
+ /* EQU */ 0x16 => { WPOP1!(y); WPOP1!(x); WPSHB!(x==y); }
+ /* NQK */ 0x17 => { WGET2!(x,y); WPSHB!(x!=y); }
+ /* IOR */ 0x18 => { WPOP1!(y); math!(WGETV!(1); IOR y); }
+ /* XOR */ 0x19 => { WPOP1!(y); math!(WGETV!(1); XOR y); }
+ /* AND */ 0x1A => { WPOP1!(y); math!(WGETV!(1); AND y); }
+ /* NOT */ 0x1B => { math!(WGETV!(1); NOT); }
+ /* SHF */ 0x1C => { WPOP1!(y); WPOP1!(x); WPSH1!(shf!(x,y)); }
+ /* SHC */ 0x1D => { WPOP1!(y); WPOP1!(x); WPSH1!(shc!(x,y)); }
+ /* TAL */ 0x1E => { math!(WGETV!(1); TAL); }
+ /* REV */ 0x1F => { math!(WGETV!(1); REV); }
- /* NOP */ 0x20 => { }
- /* JMS */ 0x21 => { w_pop_16!(a); r_psh_16!(pc!()); jump!(a); }
- /* JCS */ 0x22 => { w_pop_16!(a); w_pop_8!(t); if t!=0 {r_psh_16!(pc!()); jump!(a)}; }
- /* JCK* */ 0x23 => { w_pop_16!(a); w_get_16!(t); if t!=0 {jump!(a)}; }
- /* LDA* */ 0x24 => { w_pop_16!(a); w_psh_16!(m_read_16!(a)); }
- /* STA* */ 0x25 => { w_pop_16!(a); w_pop_16!(v); m_write_16!(v,a); }
- /* LDD* */ 0x26 => { w_pop_8!(p); w_psh_16!(d_read_16!(p)); }
- /* STD* */ 0x27 => { w_pop_8!(p); w_pop_16!(v); d_write_16!(v,p); }
- /* PSH* */ 0x28 => { r_pop_16!(x); w_psh_16!(x); }
- /* POP* */ 0x29 => { self.wst.sp = self.wst.sp.wrapping_sub(2); }
- /* CPY* */ 0x2A => { r_get_16!(x); w_psh_16!(x); }
- /* SPL* */ 0x2B => { w_pop_8!(y); w_pop_8!(x); nyb!(x=>a,b); nyb!(y=>c,d); w_psh_8!(a); w_psh_8!(b); w_psh_8!(c); w_psh_8!(d); }
- /* DUP* */ 0x2C => { w_get_16!(x); w_psh_16!(x); }
- /* OVR* */ 0x2D => { w_pop_16!(y); w_get_16!(x); w_psh_16!(y); w_psh_16!(x); }
- /* SWP* */ 0x2E => { w_pop_16!(y); w_pop_16!(x); w_psh_16!(y); w_psh_16!(x); }
- /* ROT* */ 0x2F => { w_pop_16!(z); w_pop_16!(y); w_pop_16!(x); w_psh_16!(y); w_psh_16!(z); w_psh_16!(x); }
- /* ADD* */ 0x30 => { w_pop_16!(y); w_pop_16!(x); w_psh_16!(x.wrapping_add(y)); }
- /* SUB* */ 0x31 => { w_pop_16!(y); w_pop_16!(x); w_psh_16!(x.wrapping_sub(y)); }
- /* INC* */ 0x32 => { w_pop_16!(x); w_psh_16!(x.wrapping_add(1)); }
- /* DEC* */ 0x33 => { w_pop_16!(x); w_psh_16!(x.wrapping_sub(1)); }
- /* LTH* */ 0x34 => { w_pop_16!(y); w_pop_16!(x); w_psh_8!(truth!(x < y)); }
- /* GTH* */ 0x35 => { w_pop_16!(y); w_pop_16!(x); w_psh_8!(truth!(x > y)); }
- /* EQU* */ 0x36 => { w_pop_16!(y); w_pop_16!(x); w_psh_8!(truth!(x==y)); }
- /* NQK* */ 0x37 => { w_pop_16!(y); w_get_16!(x); w_psh_16!(y); w_psh_8!(truth!(x!=y)); }
- /* IOR* */ 0x38 => { w_pop_16!(y); w_pop_16!(x); w_psh_16!(x.bitor(y)); }
- /* XOR* */ 0x39 => { w_pop_16!(y); w_pop_16!(x); w_psh_16!(x.bitxor(y)); }
- /* AND* */ 0x3A => { w_pop_16!(y); w_pop_16!(x); w_psh_16!(x.bitand(y)); }
- /* NOT* */ 0x3B => { self.wst.not_u16(); }
- /* SHF* */ 0x3C => { w_pop_8!(y); w_pop_16!(x); w_psh_16!(shf!(x,y)); }
- /* SHC* */ 0x3D => { w_pop_8!(y); w_pop_16!(x); w_psh_16!(shc!(x,y)); }
- /* TAL* */ 0x3E => { w_pop_16!(x); w_psh_8!(x.count_ones() as u8); }
- /* REV* */ 0x3F => { w_pop_16!(x); w_psh_16!(x.reverse_bits()); }
+ /* 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}; }
+ /* 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); }
+ /* 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); }
+ /* OVR* */ 0x2D => { WGET2N!(x,y); WPSH2!(x,y); }
+ /* SWP* */ 0x2E => { WPOP2!(c,d); WPOP2!(a,b); WPSH2!(c,d); WPSH2!(a,b); }
+ /* ROT* */ 0x2F => { WPOP2!(e,f); WPOP2!(c,d); WPOP2!(a,b); WPSH2!(c,d); WPSH2!(e,f); WPSH2!(a,b); }
+ /* ADD* */ 0x30 => { WPOPD!(y); WPOPD!(x); WPSHD!(x.wrapping_add(y)); }
+ /* SUB* */ 0x31 => { WPOPD!(y); WPOPD!(x); WPSHD!(x.wrapping_sub(y)); }
+ /* INC* */ 0x32 => { WPOPD!(x); WPSHD!(x.wrapping_add(1)); }
+ /* DEC* */ 0x33 => { WPOPD!(x); WPSHD!(x.wrapping_sub(1)); }
+ /* LTH* */ 0x34 => { WPOPD!(y); WPOPD!(x); WPSHB!(x < y); }
+ /* GTH* */ 0x35 => { WPOPD!(y); WPOPD!(x); WPSHB!(x > y); }
+ /* EQU* */ 0x36 => { WPOPD!(y); WPOPD!(x); WPSHB!(x==y); }
+ /* NQK* */ 0x37 => { WGETD!(y); WGETDN!(x); WPSHB!(x!=y); }
+ /* IOR* */ 0x38 => { WPOP2!(x,y); math!(WGETV!(2); IOR x); math!(WGETV!(1); IOR y); }
+ /* XOR* */ 0x39 => { WPOP2!(x,y); math!(WGETV!(2); XOR x); math!(WGETV!(1); XOR y); }
+ /* AND* */ 0x3A => { WPOP2!(x,y); math!(WGETV!(2); AND x); math!(WGETV!(1); AND y); }
+ /* NOT* */ 0x3B => { math!(WGETV!(2); NOT); math!(WGETV!(1); NOT); }
+ /* SHF* */ 0x3C => { WPOP1!(y); WPOPD!(x); WPSHD!(shf!(x,y)); }
+ /* SHC* */ 0x3D => { WPOP1!(y); WPOPD!(x); WPSHD!(shc!(x,y)); }
+ /* TAL* */ 0x3E => { WPOPD!(x); WPSH1!(x.count_ones() as u8); }
+ /* REV* */ 0x3F => { WPOPD!(x); WPSHD!(x.reverse_bits()); }
- /* DB1 */ 0x40 => { return Some(Signal::Debug(DebugVariant::DB1)); }
- /* JMP: */ 0x41 => { m_lit_16!(a); jump!(a); }
- /* JCN: */ 0x42 => { m_lit_16!(a); w_pop_8!(t); if t!=0 {jump!(a)}; }
- /* JCK: */ 0x43 => { m_lit_16!(a); w_get_8!(t); if t!=0 {jump!(a)}; }
- /* LDA: */ 0x44 => { m_lit_16!(a); w_psh_8!(m_read_8!(a)); }
- /* STA: */ 0x45 => { m_lit_16!(a); w_pop_8!(v); m_write_8!(v,a); }
- /* LDD: */ 0x46 => { m_lit_8!(p); w_psh_8!(d_read_8!(p)); }
- /* STD: */ 0x47 => { m_lit_8!(p); w_pop_8!(v); d_write_8!(v,p); }
- /* PSH: */ 0x48 => { m_lit_8!(x); w_psh_8!(x); }
- /* POP: */ 0x49 => { self.mem.pc = self.mem.pc.wrapping_add(1); }
- /* CPY: */ 0x4A => { m_lit_8!(x); w_psh_8!(x); r_psh_8!(x); }
- /* SPL: */ 0x4B => { m_lit_8!(x); nyb!(x=>a,b); w_psh_8!(a); w_psh_8!(b); }
- /* DUP: */ 0x4C => { m_lit_8!(x); w_psh_8!(x); w_psh_8!(x); }
- /* OVR: */ 0x4D => { m_lit_8!(y); w_get_8!(x); w_psh_8!(y); w_psh_8!(x); }
- /* SWP: */ 0x4E => { m_lit_8!(y); w_pop_8!(x); w_psh_8!(y); w_psh_8!(x); }
- /* ROT: */ 0x4F => { m_lit_8!(z); w_pop_8!(y); w_pop_8!(x); w_psh_8!(y); w_psh_8!(z); w_psh_8!(x); }
- /* ADD: */ 0x50 => { m_lit_8!(y); w_pop_8!(x); w_psh_8!(x.wrapping_add(y)); }
- /* SUB: */ 0x51 => { m_lit_8!(y); w_pop_8!(x); w_psh_8!(x.wrapping_sub(y)); }
- /* INC: */ 0x52 => { m_lit_8!(x); w_psh_8!(x.wrapping_add(1)); }
- /* DEC: */ 0x53 => { m_lit_8!(x); w_psh_8!(x.wrapping_sub(1)); }
- /* LTH: */ 0x54 => { m_lit_8!(y); w_pop_8!(x); w_psh_8!(truth!(x < y)); }
- /* GTH: */ 0x55 => { m_lit_8!(y); w_pop_8!(x); w_psh_8!(truth!(x > y)); }
- /* EQU: */ 0x56 => { m_lit_8!(y); w_pop_8!(x); w_psh_8!(truth!(x==y)); }
- /* NQK: */ 0x57 => { m_lit_8!(y); w_get_8!(x); w_psh_8!(y); w_psh_8!(truth!(x!=y)); }
- /* IOR: */ 0x58 => { m_lit_8!(y); w_pop_8!(x); w_psh_8!(x.bitor(y)); }
- /* XOR: */ 0x59 => { m_lit_8!(y); w_pop_8!(x); w_psh_8!(x.bitxor(y)); }
- /* AND: */ 0x5A => { m_lit_8!(y); w_pop_8!(x); w_psh_8!(x.bitand(y)); }
- /* NOT: */ 0x5B => { m_lit_8!(x); w_psh_8!(x.not()); }
- /* SHF: */ 0x5C => { m_lit_8!(y); w_pop_8!(x); w_psh_8!(shf!(x,y)); }
- /* SHC: */ 0x5D => { m_lit_8!(y); w_pop_8!(x); w_psh_8!(shc!(x,y)); }
- /* TAL: */ 0x5E => { m_lit_8!(x); w_psh_8!(x.count_ones() as u8); }
- /* REV: */ 0x5F => { m_lit_8!(x); w_psh_8!(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}; }
+ /* 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); }
+ /* 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); }
+ /* OVR: */ 0x4D => { MLIT1!(y); WGET1!(x); WPSH1!(y); WPSH1!(x); }
+ /* SWP: */ 0x4E => { MLIT1!(y); WPOP1!(x); WPSH1!(y); WPSH1!(x); }
+ /* ROT: */ 0x4F => { MLIT1!(z); WPOP1!(y); WPOP1!(x); WPSH1!(y); WPSH1!(z); WPSH1!(x); }
+ /* ADD: */ 0x50 => { MLIT1!(y); math!(WGETV!(1); ADD y); }
+ /* SUB: */ 0x51 => { MLIT1!(y); math!(WGETV!(1); SUB y); }
+ /* INC: */ 0x52 => { MLIT1!(x); WPSH1!(x.wrapping_add(1)); }
+ /* DEC: */ 0x53 => { MLIT1!(x); WPSH1!(x.wrapping_sub(1)); }
+ /* LTH: */ 0x54 => { MLIT1!(y); WPOP1!(x); WPSHB!(x < y); }
+ /* GTH: */ 0x55 => { MLIT1!(y); WPOP1!(x); WPSHB!(x > y); }
+ /* EQU: */ 0x56 => { MLIT1!(y); WPOP1!(x); WPSHB!(x==y); }
+ /* NQK: */ 0x57 => { MLIT1!(y); WGET1!(x); WPSH1!(y); WPSHB!(x!=y); }
+ /* IOR: */ 0x58 => { MLIT1!(y); math!(WGETV!(1); IOR y); }
+ /* XOR: */ 0x59 => { MLIT1!(y); math!(WGETV!(1); XOR y); }
+ /* AND: */ 0x5A => { MLIT1!(y); math!(WGETV!(1); AND y); }
+ /* NOT: */ 0x5B => { MLIT1!(x); WPSH1!(x.not()); }
+ /* SHF: */ 0x5C => { MLIT1!(y); WPOP1!(x); WPSH1!(shf!(x,y)); }
+ /* SHC: */ 0x5D => { MLIT1!(y); WPOP1!(x); WPSH1!(shc!(x,y)); }
+ /* TAL: */ 0x5E => { MLIT1!(x); WPSH1!(x.count_ones() as u8); }
+ /* REV: */ 0x5F => { MLIT1!(x); WPSH1!(x.reverse_bits()); }
- /* DB2 */ 0x60 => { return Some(Signal::Debug(DebugVariant::DB2)); }
- /* JMS: */ 0x61 => { m_lit_16!(a); r_psh_16!(pc!()); jump!(a); }
- /* JCS: */ 0x62 => { m_lit_16!(a); w_pop_8!(t); if t!=0 {r_psh_16!(pc!()); jump!(a)}; }
- /* JCK*: */ 0x63 => { m_lit_16!(a); w_get_16!(t); if t!=0 {jump!(a)}; }
- /* LDA*: */ 0x64 => { m_lit_16!(a); w_psh_16!(m_read_16!(a)); }
- /* STA*: */ 0x65 => { m_lit_16!(a); w_pop_16!(v); m_write_16!(v,a); }
- /* LDD*: */ 0x66 => { m_lit_8!(p); w_psh_16!(d_read_16!(p)); }
- /* STD*: */ 0x67 => { m_lit_8!(p); w_pop_16!(v); d_write_16!(v,p); }
- /* PSH*: */ 0x68 => { m_lit_16!(x); w_psh_16!(x); }
- /* POP*: */ 0x69 => { self.mem.pc = self.mem.pc.wrapping_add(2); }
- /* CPY*: */ 0x6A => { m_lit_16!(x); w_psh_16!(x); r_psh_16!(x); }
- /* SPL*: */ 0x6B => { m_lit_8!(x); m_lit_8!(y); nyb!(x=>a,b); nyb!(y=>c,d); w_psh_8!(a); w_psh_8!(b); w_psh_8!(c); w_psh_8!(d); }
- /* DUP*: */ 0x6C => { m_lit_16!(x); w_psh_16!(x); w_psh_16!(x); }
- /* OVR*: */ 0x6D => { m_lit_16!(y); w_get_16!(x); w_psh_16!(y); w_psh_16!(x); }
- /* SWP*: */ 0x6E => { m_lit_16!(y); w_pop_16!(x); w_psh_16!(y); w_psh_16!(x); }
- /* ROT*: */ 0x6F => { m_lit_16!(z); w_pop_16!(y); w_pop_16!(x); w_psh_16!(y); w_psh_16!(z); w_psh_16!(x); }
- /* ADD*: */ 0x70 => { m_lit_16!(y); w_pop_16!(x); w_psh_16!(x.wrapping_add(y)); }
- /* SUB*: */ 0x71 => { m_lit_16!(y); w_pop_16!(x); w_psh_16!(x.wrapping_sub(y)); }
- /* INC*: */ 0x72 => { m_lit_16!(x); w_psh_16!(x.wrapping_add(1)); }
- /* DEC*: */ 0x73 => { m_lit_16!(x); w_psh_16!(x.wrapping_sub(1)); }
- /* LTH*: */ 0x74 => { m_lit_16!(y); w_pop_16!(x); w_psh_8!(truth!(x < y)); }
- /* GTH*: */ 0x75 => { m_lit_16!(y); w_pop_16!(x); w_psh_8!(truth!(x > y)); }
- /* EQU*: */ 0x76 => { m_lit_16!(y); w_pop_16!(x); w_psh_8!(truth!(x==y)); }
- /* NQK*: */ 0x77 => { m_lit_16!(y); w_get_16!(x); w_psh_16!(y); w_psh_8!(truth!(x!=y)); }
- /* IOR*: */ 0x78 => { m_lit_16!(y); w_pop_16!(x); w_psh_16!(x.bitor(y)); }
- /* XOR*: */ 0x79 => { m_lit_16!(y); w_pop_16!(x); w_psh_16!(x.bitxor(y)); }
- /* AND*: */ 0x7A => { m_lit_16!(y); w_pop_16!(x); w_psh_16!(x.bitand(y)); }
- /* NOT*: */ 0x7B => { m_lit_16!(x); w_psh_16!(x.not()); }
- /* SHF*: */ 0x7C => { m_lit_8!(y); w_pop_16!(x); w_psh_16!(shf!(x,y)); }
- /* SHC*: */ 0x7D => { m_lit_8!(y); w_pop_16!(x); w_psh_16!(shc!(x,y)); }
- /* TAL*: */ 0x7E => { m_lit_16!(x); w_psh_8!(x.count_ones() as u8); }
- /* REV*: */ 0x7F => { m_lit_16!(x); w_psh_16!(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}; }
+ /* 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); }
+ /* 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); }
+ /* OVR*: */ 0x6D => { MLIT2!(c,d); WGET2!(a,b); WPSH2!(c,d); WPSH2!(a,b); }
+ /* SWP*: */ 0x6E => { MLIT2!(c,d); WPOP2!(a,b); WPSH2!(c,d); WPSH2!(a,b); }
+ /* ROT*: */ 0x6F => { MLIT2!(e,f); WPOP2!(c,d); WPOP2!(a,b); WPSH2!(c,d); WPSH2!(e,f); WPSH2!(a,b); }
+ /* ADD*: */ 0x70 => { MLITD!(y); WPOPD!(x); WPSHD!(x.wrapping_add(y)); }
+ /* SUB*: */ 0x71 => { MLITD!(y); WPOPD!(x); WPSHD!(x.wrapping_sub(y)); }
+ /* INC*: */ 0x72 => { MLITD!(x); WPSHD!(x.wrapping_add(1)); }
+ /* DEC*: */ 0x73 => { MLITD!(x); WPSHD!(x.wrapping_sub(1)); }
+ /* LTH*: */ 0x74 => { MLITD!(y); WPOPD!(x); WPSHB!(x < y); }
+ /* GTH*: */ 0x75 => { MLITD!(y); WPOPD!(x); WPSHB!(x > y); }
+ /* EQU*: */ 0x76 => { MLITD!(y); WPOPD!(x); WPSHB!(x==y); }
+ /* NQK*: */ 0x77 => { MLITD!(y); WGETD!(x); WPSHD!(y); WPSHB!(x!=y); }
+ /* IOR*: */ 0x78 => { MLIT2!(x,y); math!(WGETV!(2); IOR x); math!(WGETV!(1); IOR y); }
+ /* XOR*: */ 0x79 => { MLIT2!(x,y); math!(WGETV!(2); XOR x); math!(WGETV!(1); XOR y); }
+ /* AND*: */ 0x7A => { MLIT2!(x,y); math!(WGETV!(2); AND x); math!(WGETV!(1); AND y); }
+ /* NOT*: */ 0x7B => { MLITD!(x); WPSHD!(x.not()); }
+ /* SHF*: */ 0x7C => { MLIT1!(y); WPOPD!(x); WPSHD!(shf!(x,y)); }
+ /* SHC*: */ 0x7D => { MLIT1!(y); WPOPD!(x); WPSHD!(shc!(x,y)); }
+ /* TAL*: */ 0x7E => { MLITD!(x); WPSH1!(x.count_ones() as u8); }
+ /* REV*: */ 0x7F => { MLITD!(x); WPSHD!(x.reverse_bits()); }
- /* DB3 */ 0x80 => { return Some(Signal::Debug(DebugVariant::DB3)); }
- /* JMPr */ 0x81 => { r_pop_16!(a); jump!(a); }
- /* JCNr */ 0x82 => { r_pop_16!(a); r_pop_8!(t); if t!=0 {jump!(a)}; }
- /* JCKr */ 0x83 => { r_pop_16!(a); r_get_8!(t); if t!=0 {jump!(a)}; }
- /* LDAr */ 0x84 => { r_pop_16!(a); r_psh_8!(m_read_8!(a)); }
- /* STAr */ 0x85 => { r_pop_16!(a); r_pop_8!(v); m_write_8!(v,a); }
- /* LDDr */ 0x86 => { r_pop_8!(p); r_psh_8!(d_read_8!(p)); }
- /* STDr */ 0x87 => { r_pop_8!(p); r_pop_8!(v); d_write_8!(v,p); }
- /* PSHr */ 0x88 => { w_pop_8!(x); r_psh_8!(x); }
- /* POPr */ 0x89 => { self.rst.sp = self.rst.sp.wrapping_sub(1); }
- /* CPYr */ 0x8A => { w_get_8!(x); r_psh_8!(x); }
- /* SPLr */ 0x8B => { r_pop_8!(x); nyb!(x=>a,b); r_psh_8!(a); r_psh_8!(b); }
- /* DUPr */ 0x8C => { r_get_8!(x); r_psh_8!(x); }
- /* OVRr */ 0x8D => { r_pop_8!(y); r_get_8!(x); r_psh_8!(y); r_psh_8!(x); }
- /* SWPr */ 0x8E => { r_pop_8!(y); r_pop_8!(x); r_psh_8!(y); r_psh_8!(x); }
- /* ROTr */ 0x8F => { r_pop_8!(z); r_pop_8!(y); r_pop_8!(x); r_psh_8!(y); r_psh_8!(z); r_psh_8!(x); }
- /* ADDr */ 0x90 => { r_pop_8!(y); r_pop_8!(x); r_psh_8!(x.wrapping_add(y)); }
- /* SUBr */ 0x91 => { r_pop_8!(y); r_pop_8!(x); r_psh_8!(x.wrapping_sub(y)); }
- /* INCr */ 0x92 => { self.rst.inc_u8(); }
- /* DECr */ 0x93 => { self.rst.dec_u8(); }
- /* LTHr */ 0x94 => { r_pop_8!(y); r_pop_8!(x); r_psh_8!(truth!(x < y)); }
- /* GTHr */ 0x95 => { r_pop_8!(y); r_pop_8!(x); r_psh_8!(truth!(x > y)); }
- /* EQUr */ 0x96 => { r_pop_8!(y); r_pop_8!(x); r_psh_8!(truth!(x==y)); }
- /* NQKr */ 0x97 => { r_pop_8!(y); r_get_8!(x); r_psh_8!(y); r_psh_8!(truth!(x!=y)); }
- /* IORr */ 0x98 => { r_pop_8!(y); r_pop_8!(x); r_psh_8!(x.bitor(y)); }
- /* XORr */ 0x99 => { r_pop_8!(y); r_pop_8!(x); r_psh_8!(x.bitxor(y)); }
- /* ANDr */ 0x9A => { r_pop_8!(y); r_pop_8!(x); r_psh_8!(x.bitand(y)); }
- /* NOTr */ 0x9B => { self.rst.not_u8(); }
- /* SHFr */ 0x9C => { r_pop_8!(y); r_pop_8!(x); r_psh_8!(shf!(x,y)); }
- /* SHCr */ 0x9D => { r_pop_8!(y); r_pop_8!(x); r_psh_8!(shc!(x,y)); }
- /* TALr */ 0x9E => { self.rst.tal_u8(); }
- /* REVr */ 0x9F => { self.rst.rev_u8(); }
+ /* 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}; }
+ /* 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); }
+ /* CPYr */ 0x8A => { WGET1!(x); RPSH1!(x); }
+ /* SPLr */ 0x8B => { RPOP1!(x); split!(x=>a,b); RPSH2!(a,b); }
+ /* DUPr */ 0x8C => { RGET1!(x); RPSH1!(x); }
+ /* OVRr */ 0x8D => { RGET1N!(x); RPSH1!(x); }
+ /* SWPr */ 0x8E => { RPOP1!(y); RPOP1!(x); RPSH1!(y); RPSH1!(x); }
+ /* ROTr */ 0x8F => { RPOP1!(z); RPOP1!(y); RPOP1!(x); RPSH1!(y); RPSH1!(z); RPSH1!(x); }
+ /* ADDr */ 0x90 => { RPOP1!(y); math!(RGETV!(1); ADD y); }
+ /* SUBr */ 0x91 => { RPOP1!(y); math!(RGETV!(1); SUB y); }
+ /* INCr */ 0x92 => { math!(RGETV!(1); ADD 1); }
+ /* DECr */ 0x93 => { math!(RGETV!(1); SUB 1); }
+ /* LTHr */ 0x94 => { RPOP1!(y); RPOP1!(x); RPSHB!(x < y); }
+ /* GTHr */ 0x95 => { RPOP1!(y); RPOP1!(x); RPSHB!(x > y); }
+ /* EQUr */ 0x96 => { RPOP1!(y); RPOP1!(x); RPSHB!(x==y); }
+ /* NQKr */ 0x97 => { RGET2!(x,y); RPSHB!(x!=y); }
+ /* IORr */ 0x98 => { RPOP1!(y); math!(RGETV!(1); IOR y); }
+ /* XORr */ 0x99 => { RPOP1!(y); math!(RGETV!(1); XOR y); }
+ /* ANDr */ 0x9A => { RPOP1!(y); math!(RGETV!(1); AND y); }
+ /* NOTr */ 0x9B => { math!(RGETV!(1); NOT); }
+ /* SHFr */ 0x9C => { RPOP1!(y); RPOP1!(x); RPSH1!(shf!(x,y)); }
+ /* SHCr */ 0x9D => { RPOP1!(y); RPOP1!(x); RPSH1!(shc!(x,y)); }
+ /* TALr */ 0x9E => { math!(RGETV!(1); TAL); }
+ /* REVr */ 0x9F => { math!(RGETV!(1); REV); }
- /* DB4 */ 0xA0 => { return Some(Signal::Debug(DebugVariant::DB4)); }
- /* JMSr */ 0xA1 => { r_pop_16!(a); w_psh_16!(pc!()); jump!(a); }
- /* JCSr */ 0xA2 => { r_pop_16!(a); r_pop_8!(t); if t!=0 {w_psh_16!(pc!()); jump!(a)}; }
- /* JCKr* */ 0xA3 => { r_pop_16!(a); r_get_16!(t); if t!=0 {jump!(a)}; }
- /* LDAr* */ 0xA4 => { r_pop_16!(a); r_psh_16!(m_read_16!(a)); }
- /* STAr* */ 0xA5 => { r_pop_16!(a); r_pop_16!(v); m_write_16!(v,a); }
- /* LDDr* */ 0xA6 => { r_pop_8!(p); r_psh_16!(d_read_16!(p)); }
- /* STDr* */ 0xA7 => { r_pop_8!(p); r_pop_16!(v); d_write_16!(v,p); }
- /* PSHr* */ 0xA8 => { w_pop_16!(x); r_psh_16!(x); }
- /* POPr* */ 0xA9 => { self.rst.sp = self.rst.sp.wrapping_sub(2); }
- /* CPYr* */ 0xAA => { w_get_16!(x); r_psh_16!(x); }
- /* SPLr* */ 0xAB => { r_pop_8!(y); r_pop_8!(x); nyb!(x=>a,b); nyb!(y=>c,d); r_psh_8!(a); r_psh_8!(b); r_psh_8!(c); r_psh_8!(d); }
- /* DUPr* */ 0xAC => { r_get_16!(x); r_psh_16!(x); }
- /* OVRr* */ 0xAD => { r_pop_16!(y); r_get_16!(x); r_psh_16!(y); r_psh_16!(x); }
- /* SWPr* */ 0xAE => { r_pop_16!(y); r_pop_16!(x); r_psh_16!(y); r_psh_16!(x); }
- /* ROTr* */ 0xAF => { r_pop_16!(z); r_pop_16!(y); r_pop_16!(x); r_psh_16!(y); r_psh_16!(z); r_psh_16!(x); }
- /* ADDr* */ 0xB0 => { r_pop_16!(y); r_pop_16!(x); r_psh_16!(x.wrapping_add(y)); }
- /* SUBr* */ 0xB1 => { r_pop_16!(y); r_pop_16!(x); r_psh_16!(x.wrapping_sub(y)); }
- /* INCr* */ 0xB2 => { r_pop_16!(x); r_psh_16!(x.wrapping_add(1)); }
- /* DECr* */ 0xB3 => { r_pop_16!(x); r_psh_16!(x.wrapping_sub(1)); }
- /* LTHr* */ 0xB4 => { r_pop_16!(y); r_pop_16!(x); r_psh_8!(truth!(x < y)); }
- /* GTHr* */ 0xB5 => { r_pop_16!(y); r_pop_16!(x); r_psh_8!(truth!(x > y)); }
- /* EQUr* */ 0xB6 => { r_pop_16!(y); r_pop_16!(x); r_psh_8!(truth!(x==y)); }
- /* NQKr* */ 0xB7 => { r_pop_16!(y); r_get_16!(x); r_psh_16!(y); r_psh_8!(truth!(x!=y)); }
- /* IORr* */ 0xB8 => { r_pop_16!(y); r_pop_16!(x); r_psh_16!(x.bitor(y)); }
- /* XORr* */ 0xB9 => { r_pop_16!(y); r_pop_16!(x); r_psh_16!(x.bitxor(y)); }
- /* ANDr* */ 0xBA => { r_pop_16!(y); r_pop_16!(x); r_psh_16!(x.bitand(y)); }
- /* NOTr* */ 0xBB => { self.rst.not_u16(); }
- /* SHFr* */ 0xBC => { r_pop_8!(y); r_pop_16!(x); r_psh_16!(shf!(x,y)); }
- /* SHCr* */ 0xBD => { r_pop_8!(y); r_pop_16!(x); r_psh_16!(shc!(x,y)); }
- /* TALr* */ 0xBE => { r_pop_16!(x); r_psh_8!(x.count_ones() as u8); }
- /* REV* */ 0xBF => { r_pop_16!(x); r_psh_16!(x.reverse_bits()); }
+ /* 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}; }
+ /* 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); }
+ /* 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); }
+ /* OVRr* */ 0xAD => { RGET2N!(x,y); RPSH2!(x,y); }
+ /* SWPr* */ 0xAE => { RPOP2!(c,d); RPOP2!(a,b); RPSH2!(c,d); RPSH2!(a,b); }
+ /* ROTr* */ 0xAF => { RPOP2!(e,f); RPOP2!(c,d); RPOP2!(a,b); RPSH2!(c,d); RPSH2!(e,f); RPSH2!(a,b); }
+ /* ADDr* */ 0xB0 => { RPOPD!(y); RPOPD!(x); RPSHD!(x.wrapping_add(y)); }
+ /* SUBr* */ 0xB1 => { RPOPD!(y); RPOPD!(x); RPSHD!(x.wrapping_sub(y)); }
+ /* INCr* */ 0xB2 => { RPOPD!(x); RPSHD!(x.wrapping_add(1)); }
+ /* DECr* */ 0xB3 => { RPOPD!(x); RPSHD!(x.wrapping_sub(1)); }
+ /* LTHr* */ 0xB4 => { RPOPD!(y); RPOPD!(x); RPSHB!(x < y); }
+ /* GTHr* */ 0xB5 => { RPOPD!(y); RPOPD!(x); RPSHB!(x > y); }
+ /* EQUr* */ 0xB6 => { RPOPD!(y); RPOPD!(x); RPSHB!(x==y); }
+ /* NQKr* */ 0xB7 => { RGETD!(y); RGETDN!(x); RPSHB!(x!=y); }
+ /* IORr* */ 0xB8 => { RPOP2!(x,y); math!(RGETV!(2); IOR x); math!(RGETV!(1); IOR y); }
+ /* XORr* */ 0xB9 => { RPOP2!(x,y); math!(RGETV!(2); XOR x); math!(RGETV!(1); XOR y); }
+ /* ANDr* */ 0xBA => { RPOP2!(x,y); math!(RGETV!(2); AND x); math!(RGETV!(1); AND y); }
+ /* NOTr* */ 0xBB => { math!(RGETV!(2); NOT); math!(RGETV!(1); NOT); }
+ /* SHFr* */ 0xBC => { RPOP1!(y); RPOPD!(x); RPSHD!(shf!(x,y)); }
+ /* SHCr* */ 0xBD => { RPOP1!(y); RPOPD!(x); RPSHD!(shc!(x,y)); }
+ /* TALr* */ 0xBE => { RPOPD!(x); RPSH1!(x.count_ones() as u8); }
+ /* REVr* */ 0xBF => { RPOPD!(x); RPSHD!(x.reverse_bits()); }
- /* DB5 */ 0xC0 => { return Some(Signal::Debug(DebugVariant::DB5)); }
- /* JMPr: */ 0xC1 => { m_lit_16!(a); jump!(a); }
- /* JCNr: */ 0xC2 => { m_lit_16!(a); r_pop_8!(t); if t!=0 {jump!(a)}; }
- /* JCKr: */ 0xC3 => { m_lit_16!(a); r_get_8!(t); if t!=0 {jump!(a)}; }
- /* LDAr: */ 0xC4 => { m_lit_16!(a); r_psh_8!(m_read_8!(a)); }
- /* STAr: */ 0xC5 => { m_lit_16!(a); r_pop_8!(v); m_write_8!(v,a); }
- /* LDDr: */ 0xC6 => { m_lit_8!(p); r_psh_8!(d_read_8!(p)); }
- /* STDr: */ 0xC7 => { m_lit_8!(p); r_pop_8!(v); d_write_8!(v,p); }
- /* PSHr: */ 0xC8 => { m_lit_8!(x); r_psh_8!(x); }
- /* POPr: */ 0xC9 => { self.mem.pc = self.mem.pc.wrapping_add(1); }
- /* CPYr: */ 0xCA => { m_lit_8!(x); w_psh_8!(x); r_psh_8!(x); }
- /* SPLr: */ 0xCB => { m_lit_8!(x); nyb!(x=>a,b); r_psh_8!(a); r_psh_8!(b); }
- /* DUPr: */ 0xCC => { m_lit_8!(x); r_psh_8!(x); r_psh_8!(x); }
- /* OVRr: */ 0xCD => { m_lit_8!(y); r_get_8!(x); r_psh_8!(y); r_psh_8!(x); }
- /* SWPr: */ 0xCE => { m_lit_8!(y); r_pop_8!(x); r_psh_8!(y); r_psh_8!(x); }
- /* ROTr: */ 0xCF => { m_lit_8!(z); r_pop_8!(y); r_pop_8!(x); r_psh_8!(y); r_psh_8!(z); r_psh_8!(x); }
- /* ADDr: */ 0xD0 => { m_lit_8!(y); r_pop_8!(x); r_psh_8!(x.wrapping_add(y)); }
- /* SUBr: */ 0xD1 => { m_lit_8!(y); r_pop_8!(x); r_psh_8!(x.wrapping_sub(y)); }
- /* INCr: */ 0xD2 => { m_lit_8!(x); r_psh_8!(x.wrapping_add(1)); }
- /* DECr: */ 0xD3 => { m_lit_8!(x); r_psh_8!(x.wrapping_sub(1)); }
- /* LTHr: */ 0xD4 => { m_lit_8!(y); r_pop_8!(x); r_psh_8!(truth!(x < y)); }
- /* GTHr: */ 0xD5 => { m_lit_8!(y); r_pop_8!(x); r_psh_8!(truth!(x > y)); }
- /* EQUr: */ 0xD6 => { m_lit_8!(y); r_pop_8!(x); r_psh_8!(truth!(x==y)); }
- /* NQKr: */ 0xD7 => { m_lit_8!(y); r_get_8!(x); r_psh_8!(y); r_psh_8!(truth!(x!=y)); }
- /* IORr: */ 0xD8 => { m_lit_8!(y); r_pop_8!(x); r_psh_8!(x.bitor(y)); }
- /* XORr: */ 0xD9 => { m_lit_8!(y); r_pop_8!(x); r_psh_8!(x.bitxor(y)); }
- /* ANDr: */ 0xDA => { m_lit_8!(y); r_pop_8!(x); r_psh_8!(x.bitand(y)); }
- /* NOTr: */ 0xDB => { m_lit_8!(x); r_psh_8!(x.not()); }
- /* SHFr: */ 0xDC => { m_lit_8!(y); r_pop_8!(x); r_psh_8!(shf!(x,y)); }
- /* SHCr: */ 0xDD => { m_lit_8!(y); r_pop_8!(x); r_psh_8!(shc!(x,y)); }
- /* TALr: */ 0xDE => { m_lit_8!(x); r_psh_8!(x.count_ones() as u8); }
- /* REVr: */ 0xDF => { m_lit_8!(x); r_psh_8!(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}; }
+ /* 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); }
+ /* 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); }
+ /* OVRr: */ 0xCD => { MLIT1!(y); RGET1!(x); RPSH1!(y); RPSH1!(x); }
+ /* SWPr: */ 0xCE => { MLIT1!(y); RPOP1!(x); RPSH1!(y); RPSH1!(x); }
+ /* ROTr: */ 0xCF => { MLIT1!(z); RPOP1!(y); RPOP1!(x); RPSH1!(y); RPSH1!(z); RPSH1!(x); }
+ /* ADDr: */ 0xD0 => { MLIT1!(y); math!(RGETV!(1); ADD y); }
+ /* SUBr: */ 0xD1 => { MLIT1!(y); math!(RGETV!(1); SUB y); }
+ /* INCr: */ 0xD2 => { MLIT1!(x); RPSH1!(x.wrapping_add(1)); }
+ /* DECr: */ 0xD3 => { MLIT1!(x); RPSH1!(x.wrapping_sub(1)); }
+ /* LTHr: */ 0xD4 => { MLIT1!(y); RPOP1!(x); RPSHB!(x < y); }
+ /* GTHr: */ 0xD5 => { MLIT1!(y); RPOP1!(x); RPSHB!(x > y); }
+ /* EQUr: */ 0xD6 => { MLIT1!(y); RPOP1!(x); RPSHB!(x==y); }
+ /* NQKr: */ 0xD7 => { MLIT1!(y); RGET1!(x); RPSH1!(y); RPSHB!(x!=y); }
+ /* IORr: */ 0xD8 => { MLIT1!(y); math!(RGETV!(1); IOR y); }
+ /* XORr: */ 0xD9 => { MLIT1!(y); math!(RGETV!(1); XOR y); }
+ /* ANDr: */ 0xDA => { MLIT1!(y); math!(RGETV!(1); AND y); }
+ /* NOTr: */ 0xDB => { MLIT1!(x); RPSH1!(x.not()); }
+ /* SHFr: */ 0xDC => { MLIT1!(y); RPOP1!(x); RPSH1!(shf!(x,y)); }
+ /* SHCr: */ 0xDD => { MLIT1!(y); RPOP1!(x); RPSH1!(shc!(x,y)); }
+ /* TALr: */ 0xDE => { MLIT1!(x); RPSH1!(x.count_ones() as u8); }
+ /* REVr: */ 0xDF => { MLIT1!(x); RPSH1!(x.reverse_bits()); }
- /* DB6 */ 0xE0 => { return Some(Signal::Debug(DebugVariant::DB6)); }
- /* JMSr: */ 0xE1 => { m_lit_16!(a); w_psh_16!(pc!()); jump!(a); }
- /* JCSr: */ 0xE2 => { m_lit_16!(a); r_pop_8!(t); if t!=0 {w_psh_16!(pc!()); jump!(a)}; }
- /* JCKr*: */ 0xE3 => { m_lit_16!(a); r_get_16!(t); if t!=0 {jump!(a)}; }
- /* LDAr*: */ 0xE4 => { m_lit_16!(a); r_psh_16!(m_read_16!(a)); }
- /* STAr*: */ 0xE5 => { m_lit_16!(a); r_pop_16!(v); m_write_16!(v,a); }
- /* LDDr*: */ 0xE6 => { m_lit_8!(p); r_psh_16!(d_read_16!(p)); }
- /* STDr*: */ 0xE7 => { m_lit_8!(p); r_pop_16!(v); d_write_16!(v,p); }
- /* PSHr*: */ 0xE8 => { m_lit_16!(x); r_psh_16!(x); }
- /* POPr*: */ 0xE9 => { self.mem.pc = self.mem.pc.wrapping_add(2); }
- /* CPYr*: */ 0xEA => { m_lit_16!(x); w_psh_16!(x); r_psh_16!(x); }
- /* SPLr*: */ 0xEB => { m_lit_8!(x); m_lit_8!(y); nyb!(x=>a,b); nyb!(y=>c,d); r_psh_8!(a); r_psh_8!(b); r_psh_8!(c); r_psh_8!(d); }
- /* DUPr*: */ 0xEC => { m_lit_16!(x); r_psh_16!(x); r_psh_16!(x); }
- /* OVRr*: */ 0xED => { m_lit_16!(y); r_get_16!(x); r_psh_16!(y); r_psh_16!(x); }
- /* SWPr*: */ 0xEE => { m_lit_16!(y); r_pop_16!(x); r_psh_16!(y); r_psh_16!(x); }
- /* ROTr*: */ 0xEF => { m_lit_16!(z); r_pop_16!(y); r_pop_16!(x); r_psh_16!(y); r_psh_16!(z); r_psh_16!(x); }
- /* ADDr*: */ 0xF0 => { m_lit_16!(y); r_pop_16!(x); r_psh_16!(x.wrapping_add(y)); }
- /* SUBr*: */ 0xF1 => { m_lit_16!(y); r_pop_16!(x); r_psh_16!(x.wrapping_sub(y)); }
- /* INCr*: */ 0xF2 => { m_lit_16!(x); r_psh_16!(x.wrapping_add(1)); }
- /* DECr*: */ 0xF3 => { m_lit_16!(x); r_psh_16!(x.wrapping_sub(1)); }
- /* LTHr*: */ 0xF4 => { m_lit_16!(y); r_pop_16!(x); r_psh_8!(truth!(x < y)); }
- /* GTHr*: */ 0xF5 => { m_lit_16!(y); r_pop_16!(x); r_psh_8!(truth!(x > y)); }
- /* EQUr*: */ 0xF6 => { m_lit_16!(y); r_pop_16!(x); r_psh_8!(truth!(x==y)); }
- /* NQKr*: */ 0xF7 => { m_lit_16!(y); r_get_16!(x); r_psh_16!(y); r_psh_8!(truth!(x!=y)); }
- /* IORr*: */ 0xF8 => { m_lit_16!(y); r_pop_16!(x); r_psh_16!(x.bitor(y)); }
- /* XORr*: */ 0xF9 => { m_lit_16!(y); r_pop_16!(x); r_psh_16!(x.bitxor(y)); }
- /* ANDr*: */ 0xFA => { m_lit_16!(y); r_pop_16!(x); r_psh_16!(x.bitand(y)); }
- /* NOTr*: */ 0xFB => { m_lit_16!(x); r_psh_16!(x.not()); }
- /* SHFr*: */ 0xFC => { m_lit_8!(y); r_pop_16!(x); r_psh_16!(shf!(x,y)); }
- /* SHCr*: */ 0xFD => { m_lit_8!(y); r_pop_16!(x); r_psh_16!(shc!(x,y)); }
- /* TALr*: */ 0xFE => { m_lit_16!(x); r_psh_8!(x.count_ones() as u8); }
- /* REVr*: */ 0xFF => { m_lit_16!(x); r_psh_16!(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}; }
+ /* 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); }
+ /* 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); }
+ /* OVRr*: */ 0xED => { MLIT2!(c,d); RGET2!(a,b); RPSH2!(c,d); RPSH2!(a,b); }
+ /* SWPr*: */ 0xEE => { MLIT2!(c,d); RPOP2!(a,b); RPSH2!(c,d); RPSH2!(a,b); }
+ /* ROTr*: */ 0xEF => { MLIT2!(e,f); RPOP2!(c,d); RPOP2!(a,b); RPSH2!(c,d); RPSH2!(e,f); RPSH2!(a,b); }
+ /* ADDr*: */ 0xF0 => { MLITD!(y); RPOPD!(x); RPSHD!(x.wrapping_add(y)); }
+ /* SUBr*: */ 0xF1 => { MLITD!(y); RPOPD!(x); RPSHD!(x.wrapping_sub(y)); }
+ /* INCr*: */ 0xF2 => { MLITD!(x); RPSHD!(x.wrapping_add(1)); }
+ /* DECr*: */ 0xF3 => { MLITD!(x); RPSHD!(x.wrapping_sub(1)); }
+ /* LTHr*: */ 0xF4 => { MLITD!(y); RPOPD!(x); RPSHB!(x < y); }
+ /* GTHr*: */ 0xF5 => { MLITD!(y); RPOPD!(x); RPSHB!(x > y); }
+ /* EQUr*: */ 0xF6 => { MLITD!(y); RPOPD!(x); RPSHB!(x==y); }
+ /* NQKr*: */ 0xF7 => { MLITD!(y); RGETD!(x); RPSHD!(y); RPSHB!(x!=y); }
+ /* IORr*: */ 0xF8 => { MLIT2!(x,y); math!(RGETV!(2); IOR x); math!(RGETV!(1); IOR y); }
+ /* XORr*: */ 0xF9 => { MLIT2!(x,y); math!(RGETV!(2); XOR x); math!(RGETV!(1); XOR y); }
+ /* ANDr*: */ 0xFA => { MLIT2!(x,y); math!(RGETV!(2); AND x); math!(RGETV!(1); AND y); }
+ /* NOTr*: */ 0xFB => { MLITD!(x); RPSHD!(x.not()); }
+ /* SHFr*: */ 0xFC => { MLIT1!(y); RPOPD!(x); RPSHD!(shf!(x,y)); }
+ /* SHCr*: */ 0xFD => { MLIT1!(y); RPOPD!(x); RPSHD!(shc!(x,y)); }
+ /* TALr*: */ 0xFE => { MLITD!(x); RPSH1!(x.count_ones() as u8); }
+ /* REVr*: */ 0xFF => { MLITD!(x); RPSHD!(x.reverse_bits()); }
}
}
diff --git a/src/memory.rs b/src/program_memory.rs
index 755c4bc..7ffdb17 100644
--- a/src/memory.rs
+++ b/src/program_memory.rs
@@ -1,9 +1,9 @@
-pub struct Memory {
+pub struct ProgramMemory {
pub mem: [u8; 65536],
pub pc: u16,
}
-impl Memory {
+impl ProgramMemory {
pub fn new() -> Self {
Self {
mem: [0; 65536],
@@ -11,8 +11,15 @@ impl Memory {
}
}
+ pub fn reset(&mut self) {
+ self.mem.fill(0);
+ self.pc = 0;
+ }
+
pub fn load_program(&mut self, bytecode: &[u8]) {
- self.mem[..bytecode.len()].copy_from_slice(bytecode)
+ let length = std::cmp::min(bytecode.len(), 65536);
+ self.mem[..length].copy_from_slice(&bytecode[..length]);
+ self.mem[length..65536].fill(0);
}
pub fn read_u8(&self, addr: u16) -> u8 {
@@ -46,17 +53,4 @@ impl Memory {
let byte_low = self.read_u8_next();
u16::from_be_bytes([byte_high, byte_low])
}
-
- pub fn read_pc(&self) -> u16 {
- self.pc
- }
-
- pub fn write_pc(&mut self, val: u16) {
- self.pc = val;
- }
-
- pub fn reset(&mut self) {
- self.mem.fill(0);
- self.pc = 0;
- }
}
diff --git a/src/stack.rs b/src/stack.rs
index 2862b72..ab18cca 100644
--- a/src/stack.rs
+++ b/src/stack.rs
@@ -11,6 +11,10 @@ impl Stack {
}
}
+ pub fn reset(&mut self) {
+ self.sp = 0;
+ }
+
pub fn push_u8(&mut self, val: u8) {
self.mem[self.sp as usize] = val;
self.sp = self.sp.wrapping_add(1);
@@ -22,67 +26,18 @@ impl Stack {
}
pub fn push_u16(&mut self, val: u16) {
- let [byte_high, byte_low] = u16::to_be_bytes(val);
- self.push_u8(byte_high);
- self.push_u8(byte_low);
+ let [high, low] = u16::to_be_bytes(val);
+ self.mem[self.sp as usize] = high;
+ self.sp = self.sp.wrapping_add(1);
+ self.mem[self.sp as usize] = low;
+ self.sp = self.sp.wrapping_add(1);
}
pub fn pop_u16(&mut self) -> u16 {
- self.sp = self.sp.wrapping_sub(1);
- let byte_low = self.mem[self.sp as usize];
- self.sp = self.sp.wrapping_sub(1);
- let byte_high = self.mem[self.sp as usize];
- u16::from_be_bytes([byte_high, byte_low])
- }
-
- pub fn get_u8(&mut self) -> u8 {
- self.mem[self.sp.wrapping_sub(1) as usize]
- }
-
- pub fn get_u16(&mut self) -> u16 {
- let byte_low = self.mem[self.sp.wrapping_sub(1) as usize];
- let byte_high = self.mem[self.sp.wrapping_sub(2) as usize];
- u16::from_be_bytes([byte_high, byte_low])
- }
-
- pub fn reset(&mut self) {
- self.mem.fill(0);
- self.sp = 0;
- }
-}
-
-use std::ops::Not;
-
-impl Stack {
- pub fn inc_u8(&mut self) {
- let sp = self.sp.wrapping_sub(1) as usize;
- self.mem[sp] = self.mem[sp].wrapping_add(1);
- }
-
- pub fn dec_u8(&mut self) {
- let sp = self.sp.wrapping_sub(1) as usize;
- self.mem[sp] = self.mem[sp].wrapping_sub(1);
- }
-
- pub fn not_u8(&mut self) {
- let sp = self.sp.wrapping_sub(1) as usize;
- self.mem[sp] = self.mem[sp].not();
- }
-
- pub fn not_u16(&mut self) {
- let sp = self.sp.wrapping_sub(1) as usize;
- self.mem[sp] = self.mem[sp].not();
- let sp = self.sp.wrapping_sub(2) as usize;
- self.mem[sp] = self.mem[sp].not();
- }
-
- pub fn tal_u8(&mut self) {
- let sp = self.sp.wrapping_sub(1) as usize;
- self.mem[sp] = self.mem[sp].count_ones() as u8;
- }
-
- pub fn rev_u8(&mut self) {
- let sp = self.sp.wrapping_sub(1) as usize;
- self.mem[sp] = self.mem[sp].reverse_bits();
+ self.sp = self.sp.wrapping_sub(1);
+ let low = self.mem[self.sp as usize];
+ self.sp = self.sp.wrapping_sub(1);
+ let high = self.mem[self.sp as usize];
+ u16::from_be_bytes([high, low])
}
}