summaryrefslogtreecommitdiff
path: root/src/processor.rs
blob: bc16f01d832405caa8b8cfe9648f512fba209d21 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
use crate::*;
use std::ops::*;


#[derive(Copy, Clone, Debug)]
pub enum Signal {
    Sleep,
    Fork,
    Halt,
    Debug1,
    Debug2,
    Debug3,
    Debug4,
    Debug5,
    Debug6,
}


impl <
    D0:Device, D1:Device, D2:Device, D3:Device, D4:Device, D5:Device, D6:Device, D7:Device,
    D8:Device, D9:Device, DA:Device, DB:Device, DC:Device, DD:Device, DE:Device, DF:Device,
> Bedrock<D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,DA,DB,DC,DD,DE,DF> {
    pub fn evaluate(&mut self, cycles: usize) -> Option<Signal> {
        macro_rules! WPSH1  { ($x:expr)           => { self.wst.push_u8($x) }; }
        macro_rules! RPSH1  { ($x:expr)           => { self.rst.push_u8($x) }; }
        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}) }; }

        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(); }; }

        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) }
            };
        }

        let end = self.cyc + cycles;
        while self.cyc < end {
            self.cyc += 1;

            match self.mem.read_u8_next() {
    /* HLT    */ 0x00 => { return Some(Signal::Halt); }
    /* JMP    */ 0x01 => { WPOPD!(a); self.mem.pc=a; }
    /* JCN    */ 0x02 => { WPOPD!(a); WPOP1!(t); if t!=0 {self.mem.pc=a}; }
    /* JCK    */ 0x03 => { WPOPD!(a); WGET1!(t); if t!=0 {self.mem.pc=a}; }
    /* 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 => { 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::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::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::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::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::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::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()); }
            }
        }

        return None;
    }
}