1use crate::prelude::{*, convert::TryFrom, fmt::UpperHex};
2use crate::chip::access::{*, Byte::*, Register::*, Word::*, Double::*, Internal::*};
3
4#[derive(Debug, Clone, Copy, PartialEq)]
6pub enum Op {
7 NOP(raw::u8),
8 Add{from: Byte, carry: bool},
9 AddTo{value: u8, carry: bool},
10 And{from: Byte},
11 AndWith{value: u8},
12 Call{sub: u16},
13 CallIf(Test, u16),
14 CarryFlag(bool),
15 Compare{from: Byte},
16 CompareWith{value: u8},
17 ComplementAccumulator,
18 DecimalAddAdjust,
19 DecrementByte{register: Byte},
20 DecrementWord{register: Internal},
21 Interrupts(bool),
22 DoubleAdd{register: Internal},
23 ExchangeDoubleWithHilo,
24 ExchangeTopWithHilo,
25 ExclusiveOr{ from: Byte },
26 ExclusiveOrWith{value: u8},
27 Halt,
28 In(raw::u8),
29 IncrementByte{register: Byte},
30 IncrementWord{register: Internal},
31 Jump{to: u16},
32 JumpIf(Test, u16),
33 LoadAccumulator{address: u16},
34 LoadAccumulatorIndirect{register: Double},
35 LoadExtendedWith{to: Internal, value: u16 },
36 LoadHilo{address: u16},
37 Move{to: Byte, from: Byte},
38 MoveData{value: u8, to: Byte},
39 Or{from: Byte},
40 OrWith{value: u8},
41 Out(raw::u8),
42 Pop(Word),
43 ProgramCounterFromHilo,
44 Push(Word),
45 Reset{vector: raw::u8},
46 Return,
47 ReturnIf(Test),
48 RotateLeftCarrying,
49 RotateRightCarrying,
50 RotateAccumulatorLeft,
51 RotateAccumulatorRight,
52 StackPointerFromHilo,
53 StoreAccumulator{address: u16},
54 StoreAccumulatorIndirect{register: Double},
55 StoreHilo{address: u16},
56 Subtract{from: Byte, carry: bool},
57 SubtractBy{value: u8, carry: bool},
58}
59
60impl From<raw::u8> for Internal {
61 fn from(value: raw::u8) -> Self {
62 match value & 0b00_11_0000 {
63 0b00_00_0000 => Wide(BC),
64 0b00_01_0000 => Wide(DE),
65 0b00_10_0000 => Wide(HL),
66 0b00_11_0000 => StackPointer,
67 _ => unreachable!(),
68 }
69 }
70}
71
72impl From<Word> for raw::u8 {
73 fn from(value: Word) -> Self {
74 match value {
75 Word::ProgramStatus | OnBoard(StackPointer) => 3,
76 OnBoard(Wide(pair)) => pair as raw::u8,
77 word => panic!("No bit encoding for location {word:?} in op."),
78 }
79 }
80}
81
82impl From<raw::u8> for Byte {
83 fn from(value: raw::u8) -> Self {
84 match value & 0b00_111_000 {
85 0b00_000_000 => Single(B),
86 0b00_001_000 => Single(C),
87 0b00_010_000 => Single(D),
88 0b00_011_000 => Single(E),
89 0b00_100_000 => Single(H),
90 0b00_101_000 => Single(L),
91 0b00_110_000 => Byte::Indirect,
92 0b00_111_000 => Single(A),
93 _ => unreachable!(),
94 }
95 }
96}
97
98impl From<Byte> for raw::u8 {
99 fn from(value: Byte) -> Self {
100 match value {
101 Byte::Indirect => 6,
102 Single(A) => 7,
103 #[cfg(target_endian="little")]
104 Single(reg) => reg as raw::u8,
105 #[cfg(target_endian="big")]
106 Single(reg) => reg as raw::u8 ^ 0x01,
107 Byte::RAM(_) => panic!("No encoding for direct RAM references"),
108 }
109 }
110}
111
112impl Byte {
113 fn split(value: raw::u8) -> (Self, Self) {
114 (Self::from(value), Self::from(value << 3))
115 }
116}
117
118#[repr(u8)]
119#[derive(Debug, Clone, Copy, PartialEq)]
120pub enum Flag {
121 Zero,
122 Carry,
123 EvenParity,
124 Negative,
125}
126
127#[repr(u8)]
128#[derive(Debug, Clone, Copy, PartialEq)]
129pub enum Test {
130 Not(Flag),
131 Is(Flag),
132}
133
134use Flag::*;
135use Test::*;
136
137impl Test {
138 pub fn approves(self, env: &super::State) -> bool {
139 match self {
140 Not(Zero) => !env.z,
141 Is(Zero) => env.z,
142 Not(Carry) => !env.c,
143 Is(Carry) => env.c,
144 Not(EvenParity) => !env.p,
145 Is(EvenParity) => env.p,
146 Not(Negative) => !env.m,
147 Is(Negative) => env.m,
148 }
149 }
150}
151
152impl From<raw::u8> for Test {
153 fn from(value: raw::u8) -> Self {
154 let test = match (value & 0b00_11_0_000) >> 4 {
155 0b00 => Zero,
156 0b01 => Carry,
157 0b10 => EvenParity,
158 0b11 => Negative,
159 _ => unreachable!()
160 };
161 match (value & 0b00_00_1_000) >> 3 {
162 0b0 => Not(test),
163 0b1 => Is(test),
164 _ => unreachable!()
165 }
166 }
167}
168
169impl From<Test> for raw::u8 {
170 fn from(value: Test) -> Self {
171 match value {
172 Not(Zero) => 0b00_00_0_000,
173 Is(Zero) => 0b00_00_1_000,
174 Not(Carry) => 0b00_01_0_000,
175 Is(Carry) => 0b00_01_1_000,
176 Not(EvenParity) => 0b00_10_0_000,
177 Is(EvenParity) => 0b00_10_1_000,
178 Not(Negative) => 0b00_11_0_000,
179 Is(Negative) => 0b00_11_1_000,
180 }
181 }
182}
183
184#[disclose]
185#[allow(non_upper_case_globals)]
186mod b11111111 {
187 use super::raw::u8;
188
189 const NoOp: u8 = 0b00000000;
190 const RotateLeftCarrying: u8 = 0b00000111;
191 const RotateRightCarrying: u8 = 0b00001111;
192 const RotateAccumulatorLeft: u8 = 0b00010111;
193 const RotateAccumulatorRight: u8 = 0b00011111;
194
195 const StoreAccumulatorDirect: u8 = 0b00110010;
196 const LoadAccumulatorDirect: u8 = 0b00111010;
197
198 const StoreHiloDirect: u8 = 0b00100010;
199 const LoadHiloDirect: u8 = 0b00101010;
200
201 const DecimalAddAdjust: u8 = 0b00100111;
202 const ComplementAccumulator: u8 = 0b00101111;
203
204 const SetCarry: u8 = 0b00110111;
205 const ComplementCarry: u8 = 0b00111111;
206
207 const Halt: u8 = 0b01110110;
208 const Return: u8 = 0b11001001;
209
210 const Output: u8 = 0b11010011;
211 const Input: u8 = 0b11011011;
212
213 const ExchangeTopWithHilo: u8 = 0b11100011;
214 const ProgramCounterFromHilo: u8 = 0b11101001;
215 const ExchangeDoubleWithHilo: u8 = 0b11101011;
216 const StackPointerFromHilo: u8 = 0b11111001;
217
218 const DisableInterrupts: u8 = 0b11110011;
219 const EnableInterrupts: u8 = 0b11111011;
220
221 const AndImmediate: u8 = 0b11100110;
222 const AddImmediate: u8 = 0b11000110;
223 const AddImmediateCarrying: u8 = 0b11001110;
224 const SubtractImmediate: u8 = 0b11010110;
225 const SubtractImmediateBorrowing: u8 = 0b11011110;
226 const ExclusiveOrImmediate: u8 = 0b11101110;
227 const OrImmediate: u8 = 0b11110110;
228 const CompareImmediate: u8 = 0b11111110;
229
230 const StoreHiLoDirect: u8 = 0b00100010;
231 const Jump: u8 = 0b11000011;
232 const Call: u8 = 0b11001101;
233}
234
235#[disclose]
236#[allow(non_upper_case_globals)]
237mod b11_00_1111 {
238 use super::raw::u8;
239
240 const LoadExtendedImmediate: u8 = 0b00_00_0001;
241 const IncrementExtended: u8 = 0b00_00_0011;
242 const DecrementExtended: u8 = 0b00_00_1011;
243 const DoubleAdd: u8 = 0b00_00_1001;
244 const Push: u8 = 0b11_00_0101;
245 const Pop: u8 = 0b11_00_0001;
246}
247
248#[disclose]
249#[allow(non_upper_case_globals)]
250mod b11_000_111 {
251 use super::raw::u8;
252
253 const IncrementRegister: u8 = 0b00_000_100;
254 const DecrementRegister: u8 = 0b00_000_101;
255 const JumpIf: u8 = 0b11_000_010;
256 const Reset: u8 = 0b11_000_111;
257 const ReturnIf: u8 = 0b11_000_000;
258 const CallIf: u8 = 0b11_000_100;
259 const MoveImmediate: u8 = 0b00_000_110;
260}
261
262#[disclose]
263#[allow(non_upper_case_globals)]
264mod b11_111_000 {
265 use super::raw::u8;
266
267 const AddToAccumulator: u8 = 0b10_000_000;
268 const AddCarryingToAccumulator : u8 = 0b10_001_000;
269 const SubtractFromAccumulator: u8 = 0b10_010_000;
270 const SubtractBorrowingFromAccumulator: u8 = 0b10_011_000;
271 const AndWithAccumulator: u8 = 0b10_100_000;
272 const ExclusiveOrWithAccumulator: u8 = 0b10_101_000;
273 const OrWithAccumulator: u8 = 0b10_110_000;
274 const CompareWithAccumulator: u8 = 0b10_111_000;
275}
276
277#[disclose]
278#[allow(non_upper_case_globals)]
279mod b11_000000 {
280 const Move: super::raw::u8 = 0b01_000000;
281}
282
283#[disclose]
284#[allow(non_upper_case_globals)]
285mod b111_0_1111 {
286 use super::raw::u8;
287
288 const LoadAccumulatorIndirect: u8 = 0b000_0_1010;
289 const StoreAccumulatorIndirect: u8 = 0b000_0_0010;
290}
291
292#[derive(Debug)]
293pub struct OutOfRange;
294#[derive(Debug, Clone, Copy, PartialEq)]
295pub enum Error {
296 Unknown(u8),
297 NotUsable(Op),
298 Mismatch(Op, u8),
299 Invalid([u8;1]),
300 InvalidPair([u8;2]),
301 InvalidTriple([u8;3]),
302 NoData,
303}
304
305impl core::fmt::Display for OutOfRange {
306 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
307 write!(f, "value out of bounds")
308 }
309}
310
311impl core::error::Error for OutOfRange {}
312
313impl core::fmt::Display for Error {
314 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
315 write!(f, "{self:?}")
316 }
317}
318
319impl core::error::Error for self::Error {}
320
321impl UpperHex for Error {
322 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
323 match self {
324 Self::Mismatch(op, code) => write!(f, "Mismatch({op:?}, {code:X})"),
325 Self::Invalid([a]) => write!(f, "Invalid([{a:#04X}])"),
326 Self::InvalidPair([a, b]) => write!(f, "InvalidPair([{a:#04X}, {b:#04X}])"),
327 Self::InvalidTriple([a, b, c]) => write!(f, "InvalidTriple([{a:#04X}, {b:#04X}, {c:#04X}])"),
328 _ => write!(f, "{self:?}"),
329 }
330 }
331}
332
333impl TryFrom<[u8;1]> for Op {
334 type Error = [u8;1];
335 fn try_from(value: [u8;1]) -> Result<Self, Self::Error> {
336 {
337 use Op::*;
338 let value = value[0].0;
339 let value = match value & 0b11111111 {
340 b11111111::NoOp => return Ok(NOP(4)),
341 b11111111::ExchangeDoubleWithHilo => return Ok(ExchangeDoubleWithHilo),
342 b11111111::Halt => return Ok(Halt),
343 b11111111::Return => return Ok(Return),
344 b11111111::ExchangeTopWithHilo => return Ok(ExchangeTopWithHilo),
345 b11111111::RotateLeftCarrying => return Ok(RotateLeftCarrying),
346 b11111111::RotateRightCarrying => return Ok(RotateRightCarrying),
347 b11111111::RotateAccumulatorLeft => return Ok(RotateAccumulatorLeft),
348 b11111111::RotateAccumulatorRight => return Ok(RotateAccumulatorRight),
349 b11111111::SetCarry => return Ok(CarryFlag(true)),
350 b11111111::ComplementCarry => return Ok(CarryFlag(false)),
351 b11111111::DecimalAddAdjust => return Ok(DecimalAddAdjust),
352 b11111111::ComplementAccumulator => return Ok(ComplementAccumulator),
353 b11111111::ProgramCounterFromHilo => return Ok(ProgramCounterFromHilo),
354 b11111111::StackPointerFromHilo => return Ok(StackPointerFromHilo),
355 b11111111::DisableInterrupts => return Ok(Interrupts(false)),
356 b11111111::EnableInterrupts => return Ok(Interrupts(true)),
357 _ => value
358 };
359 let _value = match value & 0b11_000_111 {
360 b11_000_111::Reset => return Ok(Reset{vector: value >> 3 & 0x07}),
361 b11_000_111::ReturnIf => return Ok(ReturnIf(Test::from(value))),
362 b11_000_111::IncrementRegister => return Ok(IncrementByte { register: Byte::from(value) }),
363 b11_000_111::DecrementRegister => return Ok(DecrementByte { register: Byte::from(value) }),
364 _ => value,
365 };
366 let _value = match value & 0b11_00_1111 {
367 b11_00_1111::DecrementExtended => return Ok(DecrementWord{register: Internal::from(value)}),
368 b11_00_1111::IncrementExtended => return Ok(IncrementWord { register: Internal::from(value) }),
369 b11_00_1111::DoubleAdd => return Ok(DoubleAdd{register: Internal::from(value)}),
370 b11_00_1111::Push => return Ok(Push(match Internal::from(value) { StackPointer => ProgramStatus, wide => OnBoard(wide)})),
371 b11_00_1111::Pop => return Ok(Pop(match Internal::from(value) { StackPointer => ProgramStatus, wide => OnBoard(wide)})),
372 _ => value,
373 };
374 let _value = match (value & 0b11_111_000, value << 3) {
375 (b11_111_000::AddToAccumulator, value) => return Ok(Add{from: Byte::from(value), carry: false}),
376 (b11_111_000::AddCarryingToAccumulator, value) => return Ok(Add{ from: Byte::from(value), carry: true}),
377 (b11_111_000::SubtractFromAccumulator, value) => return Ok(Subtract{ from: Byte::from(value), carry: false}),
378 (b11_111_000::SubtractBorrowingFromAccumulator, value) => return Ok(Subtract{ from: Byte::from(value), carry: true}),
379 (b11_111_000::AndWithAccumulator, value) => return Ok(And{from: Byte::from(value)}),
380 (b11_111_000::ExclusiveOrWithAccumulator, value) => return Ok(ExclusiveOr { from: Byte::from(value) }),
381 (b11_111_000::OrWithAccumulator, value) => return Ok(Or { from: Byte::from(value) }),
382 (b11_111_000::CompareWithAccumulator, value) => return Ok(Compare{from: Byte::from(value)}),
383 _ => value,
384 };
385 let _value = match value & 0b11_000000 {
386 b11_000000::Move => {
387 let (to, from) = Byte::split(value);
388 return Ok(Move{to, from});
389 }
390 _ => value,
391 };
392 let _value = match value & 0b111_0_1111 {
393 b111_0_1111::LoadAccumulatorIndirect => return Ok(LoadAccumulatorIndirect {
394 register: if value & 0b000_1_0000 != 0 { DE } else { BC }
395 }),
396 b111_0_1111::StoreAccumulatorIndirect => return Ok(StoreAccumulatorIndirect {
397 register: if value & 0b000_1_0000 != 0 { DE } else { BC }
398 }),
399 _ => value,
400 };
401 }
402 Err(value)
403 }
404}
405
406impl TryFrom<[u8;2]> for Op {
407 type Error = [u8;2];
408 fn try_from(code: [u8;2]) -> Result<Self, Self::Error> {
409 use Op::*;
410 let [action, value] = code;
411 let value = value;
412 let action = match action.0 {
413 b11111111::AddImmediate => return Ok(AddTo { value, carry: false }),
414 b11111111::AddImmediateCarrying => return Ok(AddTo{ value, carry: true }),
415 b11111111::SubtractImmediate => return Ok(SubtractBy{ value, carry: false }),
416 b11111111::SubtractImmediateBorrowing => return Ok(SubtractBy { value, carry: true }),
417 b11111111::AndImmediate => return Ok(AndWith { value }),
418 b11111111::ExclusiveOrImmediate => return Ok(ExclusiveOrWith{value}),
419 b11111111::OrImmediate => return Ok(OrWith{value}),
420 b11111111::CompareImmediate => return Ok(CompareWith{ value }),
421 b11111111::Output => return Ok(Out(code[1].0)),
422 b11111111::Input => return Ok(In(code[1].0)),
423 next => next,
424 };
425 let _action = match action & 0b11_000_111 {
426 b11_000_111::MoveImmediate => return Ok(MoveData{ value, to: Byte::from(action) }),
427 _next => action,
428 };
429 Err(code)
430 }
431}
432
433impl TryFrom<[u8;3]> for Op {
434 type Error = [u8;3];
435 fn try_from(value: [u8;3]) -> Result<Self, Self::Error> {
436 use Op::*;
437 let action = value[0].0;
438 let data = Wrapping(raw::u16::from_le_bytes([value[1].0, value[2].0]));
439 match action {
440 b11111111::LoadHiloDirect => return Ok(LoadHilo{address: data}),
441 b11111111::StoreHiloDirect => return Ok(StoreHilo{address: data}),
442 b11111111::LoadAccumulatorDirect => return Ok(LoadAccumulator { address: data }),
443 b11111111::StoreAccumulatorDirect => return Ok(StoreAccumulator { address: data }),
444 b11111111::Jump => return Ok(Jump{to: data}),
445 b11111111::Call => return Ok(Call{sub: data}),
446 _ => action,
447 };
448 match action & 0b11_00_1111 {
449 b11_00_1111::LoadExtendedImmediate => return Ok(LoadExtendedWith { to: Internal::from(action), value: data }),
450 _ => action,
451 };
452 match action & 0b11_000_111 {
453 b11_000_111::JumpIf => return Ok(JumpIf(Test::from(action), data)),
454 b11_000_111::CallIf => return Ok(CallIf(Test::from(action), data)),
455 _ => action,
456 };
457 Err(value)
458 }
459}
460
461impl Op {
462 pub fn len(&self) -> raw::u8 {
463 use Op::*;
464 match self {
465 Call{..} | CallIf(..) | Jump{..} | JumpIf(..) | LoadExtendedWith{..} |
466 ReturnIf(..) | StoreAccumulator{..} | LoadAccumulator {..} | LoadHilo{..} | StoreHilo {..}
467 => 3,
468 AddTo{..} | AndWith{..} | ExclusiveOrWith{..} | OrWith{..} | SubtractBy{..} | CompareWith{..} | MoveData{..} |
469 Out(..) | In(..)
470 => 2,
471 NOP(..) | Push(..) | Reset{..} | ExchangeDoubleWithHilo | Return | Halt | Pop(..) | ExchangeTopWithHilo |
472 Move{..} | RotateLeftCarrying | RotateRightCarrying | RotateAccumulatorLeft | RotateAccumulatorRight |
473 IncrementByte {..} | DecrementByte {..} | Add{..} | Subtract{..} | And{..} | ExclusiveOr{..} | Or{..} |
474 Compare{..} | IncrementWord{..} | DecrementWord {..} | Interrupts(..) |
475 LoadAccumulatorIndirect {..} | StoreAccumulatorIndirect{..} |
476 DoubleAdd{..} | CarryFlag(..) | DecimalAddAdjust | ComplementAccumulator | ProgramCounterFromHilo | StackPointerFromHilo
477 => 1,
478 }
479 }
480
481 pub fn extract(feed: impl IntoIterator<Item = u8>) -> Result<(Op, usize), self::Error> {
482 let mut feed = feed.into_iter();
483 let code = match Op::try_from([feed.next().ok_or(Error::NoData)?]) {
484 Ok(op) => return Ok((op, 1)),
485 Err(code) => code,
486 };
487 match code[0].0 {
488 0xCB | 0xD9 => return Err(Error::Unknown(code[0])),
489 0xDD | 0xED | 0xFD => return Err(Error::Unknown(code[0])),
490 nop if nop & 0b11_000_111 == 0 => return Err(Error::Unknown(code[0])),
491 _ => ()
492 };
493 let code = match Op::try_from([code[0], feed.next().ok_or(Error::Invalid(code))?]) {
494 Ok(op) => return Ok((op, 2)),
495 Err(code) => code,
496 };
497 match Op::try_from([code[0], code[1], feed.next().ok_or(Error::InvalidPair(code))?]) {
498 Ok(op) => Ok((op, 3)),
499 Err(code) => Err(Error::InvalidTriple(code))
500 }
501 }
502}
503
504impl Into<[raw::u8;4]> for Op {
505 fn into(self) -> [raw::u8;4] {
506 use Op::*;
507 use raw::u8;
508 match self {
509 NOP(..) => [ 1, 0, 0, 0 ],
510 Add{ from, .. } | Subtract { from, .. } | And { from } |
511 ExclusiveOr { from } | Or { from } | Compare { from }
512 => {
513 let op = match self {
514 Add{ carry: false, ..} => b11_111_000::AddToAccumulator,
515 Add{ carry: true, ..} => b11_111_000::AddCarryingToAccumulator,
516 Subtract { carry: false, .. } => b11_111_000::SubtractFromAccumulator,
517 Subtract { carry: true, .. } => b11_111_000::SubtractBorrowingFromAccumulator,
518 And { .. } => b11_111_000::AndWithAccumulator,
519 ExclusiveOr { .. } => b11_111_000::ExclusiveOrWithAccumulator,
520 Or { .. } => b11_111_000::OrWithAccumulator,
521 Compare { .. } => b11_111_000::CompareWithAccumulator,
522 _ => unreachable!(),
523 };
524 [ 1, op | raw::u8::from(from), 0, 0 ]
525 }
526 AddTo { value, .. } | SubtractBy { value, .. } | AndWith { value } |
527 ExclusiveOrWith { value } | OrWith { value } | CompareWith { value }
528 => {
529 let op = match self {
530 AddTo { carry: false, .. } => b11111111::AddImmediate,
531 AddTo { carry: true, .. } => b11111111::AddImmediateCarrying,
532 SubtractBy { carry: false, .. } => b11111111::SubtractImmediate,
533 SubtractBy { carry: true, .. } => b11111111::SubtractImmediateBorrowing,
534 AndWith { .. } => b11111111::AndImmediate,
535 ExclusiveOrWith { .. } => b11111111::ExclusiveOrImmediate,
536 OrWith { .. } => b11111111::OrImmediate,
537 CompareWith { .. } => b11111111::CompareImmediate,
538 _ => unreachable!()
539 };
540 [2, op, value.0, 0]
541 }
542 Call { sub } => { let address = sub.0.to_le_bytes(); [ 3, b11111111::Call, address[0], address[1] ]}
543 CallIf(test, sub)
544 => { let address = sub.0.to_le_bytes(); [ 3, b11_000_111::CallIf | (u8::from(test) << 3), address[0], address[1] ]}
545 CarryFlag(set) => [ 1, if set { b11111111::SetCarry } else { b11111111::ComplementCarry }, 0, 0 ],
546 ComplementAccumulator => [ 1, b11111111::ComplementAccumulator, 0, 0 ],
547 DecimalAddAdjust => [ 1, b11111111::DecimalAddAdjust, 0, 0 ],
548 DecrementByte { register } => [ 1, b11_000_111::DecrementRegister | (u8::from(register) << 3), 0, 0 ],
549 DecrementWord { register } => [ 1, b11_00_1111::DecrementExtended | (u8::from(OnBoard(register)) << 4), 0, 0 ],
550 DoubleAdd { register } => [ 1, b11_00_1111::DoubleAdd | (u8::from(OnBoard(register)) << 4), 0, 0 ],
551 ExchangeDoubleWithHilo => [ 1, b11111111::ExchangeDoubleWithHilo, 0, 0 ],
552 ExchangeTopWithHilo => [ 1, b11111111::ExchangeTopWithHilo, 0, 0 ],
553 Halt => [ 1, b11111111::Halt, 0, 0 ],
554 In(port) => [ 2, b11111111::Input, port, 0 ],
555 IncrementByte { register } => [ 1, b11_000_111::IncrementRegister | (u8::from(register)) << 3, 0, 0 ],
556 IncrementWord { register } => [ 1, b11_00_1111::IncrementExtended | (u8::from(OnBoard(register)) << 4), 0, 0 ],
557 Interrupts(accepted) => [ 1, if accepted { b11111111:: EnableInterrupts } else { b11111111::DisableInterrupts }, 0, 0 ],
558 Jump { to } => { let bytes = to.0.to_le_bytes(); [ 3, b11111111::Jump, bytes[0], bytes[1] ] }
559 JumpIf(test, to)
560 => { let bytes = to.0.to_le_bytes(); [ 3, b11_000_111::JumpIf | (u8::from(test) << 4), bytes[0], bytes[1] ]}
561 LoadAccumulator { address } => { let bytes = address.0.to_le_bytes(); [ 3, b11111111::LoadAccumulatorDirect, bytes[0], bytes[1] ] }
562 LoadAccumulatorIndirect { register } => [ 1, b111_0_1111::LoadAccumulatorIndirect | ((u8::from(OnBoard(Wide(register))) & 0x01) << 4), 0, 0 ],
563 LoadExtendedWith { to, value }
564 => { let bytes = value.0.to_le_bytes(); [ 3, b11_00_1111::LoadExtendedImmediate | (u8::from(OnBoard(to)) << 4), bytes[0], bytes[1] ] }
565 LoadHilo { address }
566 => { let bytes = address.0.to_le_bytes(); [3, b11111111::LoadHiloDirect, bytes[0], bytes[1] ] }
567 Move { to, from } => [ 1, b11_000000::Move | (u8::from(to) << 3) | raw::u8::from(from), 0, 0 ],
568 MoveData { value, to } => [ 2, b11_000_111::MoveImmediate | (u8::from(to) << 3), value.0, 0 ],
569 Out(port) => [ 2, b11111111::Output, port, 0 ],
570 Pop(target) => [ 1, b11_00_1111::Pop | (u8::from(target) << 4), 0, 0 ],
571 ProgramCounterFromHilo => [ 1, b11111111::ProgramCounterFromHilo, 0, 0 ],
572 Push(source) => [ 1, b11_00_1111::Push | (u8::from(source) << 4), 0, 0 ],
573 Reset { vector } => [ 1, b11_000_111::Reset | (vector << 3), 0, 0 ],
574 Return => [ 1, b11111111::Return, 0, 0 ],
575 ReturnIf(test) => [ 1, b11_000_111::ReturnIf | (u8::from(test) << 3), 0, 0 ],
576 RotateAccumulatorLeft => [ 1, b11111111::RotateAccumulatorLeft, 0, 0 ],
577 RotateAccumulatorRight => [ 1, b11111111::RotateAccumulatorRight, 0, 0 ],
578 RotateLeftCarrying => [ 1, b11111111::RotateLeftCarrying, 0, 0 ],
579 RotateRightCarrying => [ 1, b11111111::RotateRightCarrying, 0, 0 ],
580 StackPointerFromHilo => [ 1, b11111111::StackPointerFromHilo, 0, 0 ],
581 StoreAccumulator { address }
582 => { let bytes = address.0.to_le_bytes(); [ 3, b11111111::StoreAccumulatorDirect, bytes[0], bytes[1] ] }
583 StoreAccumulatorIndirect { register }
584 => [ 1, b111_0_1111::StoreAccumulatorIndirect | ((u8::from(OnBoard(Wide(register))) & 0b01 ) << 4), 0, 0 ],
585 StoreHilo { address } => { let bytes = address.0.to_le_bytes(); [ 3, b11111111::StoreHiLoDirect, bytes[0], bytes[1] ] }
586 }
587 }
588}
589
590#[cfg(test)]
591mod tests;