diff options
| -rw-r--r-- | src/bedrock.rs | 20 | ||||
| -rw-r--r-- | src/device_bus.rs | 85 | ||||
| -rw-r--r-- | src/lib.rs | 28 | ||||
| -rw-r--r-- | src/processor.rs | 657 | ||||
| -rw-r--r-- | src/program_memory.rs (renamed from src/memory.rs) | 26 | ||||
| -rw-r--r-- | src/stack.rs | 73 | 
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!(), +        }      }  } @@ -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])      }  } | 
