1pub mod decode_error;
2pub mod emulate;
3pub mod instruction;
4pub mod jxx;
5pub mod operand;
6pub mod single_operand;
7pub mod two_operand;
8
9use decode_error::DecodeError;
10use emulate::Emulate;
11use instruction::Instruction;
12use jxx::*;
13use operand::{parse_destination, parse_source, OperandWidth};
14use single_operand::*;
15use two_operand::*;
16
17const RRC_OPCODE: u16 = 0;
18const SWPB_OPCODE: u16 = 1;
19const RRA_OPCODE: u16 = 2;
20const SXT_OPCODE: u16 = 3;
21const PUSH_OPCODE: u16 = 4;
22const CALL_OPCODE: u16 = 5;
23const RETI_OPCODE: u16 = 6;
24
25const MOV_OPCODE: u16 = 4;
26const ADD_OPCODE: u16 = 5;
27const ADDC_OPCODE: u16 = 6;
28const SUBC_OPCODE: u16 = 7;
29const SUB_OPCODE: u16 = 8;
30const CMP_OPCODE: u16 = 9;
31const DADD_OPCODE: u16 = 10;
32const BIT_OPCODE: u16 = 11;
33const BIC_OPCODE: u16 = 12;
34const BIS_OPCODE: u16 = 13;
35const XOR_OPCODE: u16 = 14;
36const AND_OPCODE: u16 = 15;
37
38const SINGLE_OPERAND_REGISTER_MASK: u16 = 0b1111;
39
40const SINGLE_OPERAND_OPCODE_MASK: u16 = 0b0000_0011_1000_0000;
41
42const SINGLE_OPERAND_SOURCE_MASK: u16 = 0b11_0000;
43
44const SINGLE_OPERAND_WIDTH_MASK: u16 = 0b100_0000;
45
46const INST_TYPE_MASK: u16 = 0b1110_0000_0000_0000;
47
48const SINGLE_OPERAND_INSTRUCTION: u16 = 0b0000_0000_0000_0000;
49
50const JMP_INSTRUCTION: u16 = 0b0010_0000_0000_0000;
53
54const JMP_CONDITION_MASK: u16 = 0b0001_1100_0000_0000;
56
57const JMP_OFFSET: u16 = 0b0000001111111111;
61
62const TWO_OPERAND_OPCODE_MASK: u16 = 0b1111_0000_0000_0000;
63const TWO_OPERAND_SOURCE_MASK: u16 = 0b1111_0000_0000;
64const TWO_OPERAND_AD_MASK: u16 = 0b1000_0000;
65const TWO_OPERAND_WIDTH: u16 = 0b100_0000;
66const TWO_OPERAND_AS: u16 = 0b11_0000;
67const TWO_OPERAND_DESTINATION: u16 = 0b1111;
68
69pub type Result<T> = std::result::Result<T, DecodeError>;
71
72pub fn decode(data: &[u8]) -> Result<Instruction> {
79 if data.len() < 2 {
80 return Err(DecodeError::MissingInstruction);
81 }
82
83 let (int_bytes, remaining_data) = data.split_at(std::mem::size_of::<u16>());
84 let first_word = u16::from_le_bytes(int_bytes.try_into().unwrap());
85
86 let inst_type = first_word & INST_TYPE_MASK;
87 match inst_type {
88 SINGLE_OPERAND_INSTRUCTION => {
89 let opcode = (SINGLE_OPERAND_OPCODE_MASK & first_word) >> 7;
90 let register = (SINGLE_OPERAND_REGISTER_MASK & first_word) as u8;
91 let source_addressing = (SINGLE_OPERAND_SOURCE_MASK & first_word) >> 4;
92 let operand_width =
93 OperandWidth::from(((SINGLE_OPERAND_WIDTH_MASK & first_word) >> 6) as u8);
94
95 let (source, _) = operand::parse_source(register, source_addressing, remaining_data)?;
96
97 match opcode {
98 RRC_OPCODE => Ok(Instruction::Rrc(Rrc::new(source, Some(operand_width)))),
99 SWPB_OPCODE => Ok(Instruction::Swpb(Swpb::new(source, None))),
100 RRA_OPCODE => Ok(Instruction::Rra(Rra::new(source, Some(operand_width)))),
101 SXT_OPCODE => Ok(Instruction::Sxt(Sxt::new(source, None))),
102 PUSH_OPCODE => Ok(Instruction::Push(Push::new(source, Some(operand_width)))),
103 CALL_OPCODE => Ok(Instruction::Call(Call::new(source, None))),
104 RETI_OPCODE => Ok(Instruction::Reti(Reti::new())),
105 _ => Err(DecodeError::InvalidOpcode(opcode)),
106 }
107 }
108 JMP_INSTRUCTION => {
109 let condition = (first_word & JMP_CONDITION_MASK) >> 10;
110 let offset = jxx_fix_offset(first_word & JMP_OFFSET);
111
112 match condition {
113 0 => Ok(Instruction::Jnz(Jnz::new(offset))),
114 1 => Ok(Instruction::Jz(Jz::new(offset))),
115 2 => Ok(Instruction::Jlo(Jlo::new(offset))),
116 3 => Ok(Instruction::Jc(Jc::new(offset))),
117 4 => Ok(Instruction::Jn(Jn::new(offset))),
118 5 => Ok(Instruction::Jge(Jge::new(offset))),
119 6 => Ok(Instruction::Jl(Jl::new(offset))),
120 7 => Ok(Instruction::Jmp(Jmp::new(offset))),
121 _ => Err(DecodeError::InvalidJumpCondition(condition)),
122 }
123 }
124 _ => {
125 let opcode = (first_word & TWO_OPERAND_OPCODE_MASK) >> 12;
131 let source_register = ((first_word & TWO_OPERAND_SOURCE_MASK) >> 8) as u8;
132 let ad = (first_word & TWO_OPERAND_AD_MASK) >> 7;
133 let operand_width = OperandWidth::from(((first_word & TWO_OPERAND_WIDTH) >> 6) as u8);
134 let source_addressing = (first_word & TWO_OPERAND_AS) >> 4;
135 let destination_register = (first_word & TWO_OPERAND_DESTINATION) as u8;
136
137 let (source, remaining_data) =
139 parse_source(source_register, source_addressing, remaining_data)?;
140
141 let destination = parse_destination(destination_register, ad, remaining_data)?;
142
143 match opcode {
144 MOV_OPCODE => {
145 let inst = Mov::new(source, operand_width, destination);
146 match inst.emulate() {
147 Some(inst) => Ok(inst),
148 None => Ok(Instruction::Mov(inst)),
149 }
150 }
151 ADD_OPCODE => {
152 let inst = Add::new(source, operand_width, destination);
153 match inst.emulate() {
154 Some(inst) => Ok(inst),
155 None => Ok(Instruction::Add(inst)),
156 }
157 }
158 ADDC_OPCODE => {
159 let inst = Addc::new(source, operand_width, destination);
160 match inst.emulate() {
161 Some(inst) => Ok(inst),
162 None => Ok(Instruction::Addc(inst)),
163 }
164 }
165 SUBC_OPCODE => {
166 let inst = Subc::new(source, operand_width, destination);
167 match inst.emulate() {
168 Some(inst) => Ok(inst),
169 None => Ok(Instruction::Subc(inst)),
170 }
171 }
172 SUB_OPCODE => {
173 let inst = Sub::new(source, operand_width, destination);
174 match inst.emulate() {
175 Some(inst) => Ok(inst),
176 None => Ok(Instruction::Sub(inst)),
177 }
178 }
179 CMP_OPCODE => {
180 let inst = Cmp::new(source, operand_width, destination);
181 match inst.emulate() {
182 Some(inst) => Ok(inst),
183 None => Ok(Instruction::Cmp(inst)),
184 }
185 }
186 DADD_OPCODE => {
187 let inst = Dadd::new(source, operand_width, destination);
188 match inst.emulate() {
189 Some(inst) => Ok(inst),
190 None => Ok(Instruction::Dadd(inst)),
191 }
192 }
193 BIT_OPCODE => Ok(Instruction::Bit(Bit::new(
194 source,
195 operand_width,
196 destination,
197 ))),
198 BIC_OPCODE => {
199 let inst = Bic::new(source, operand_width, destination);
200 match inst.emulate() {
201 Some(inst) => Ok(inst),
202 None => Ok(Instruction::Bic(inst)),
203 }
204 }
205 BIS_OPCODE => {
206 let inst = Bis::new(source, operand_width, destination);
207 match inst.emulate() {
208 Some(inst) => Ok(inst),
209 None => Ok(Instruction::Bis(inst)),
210 }
211 }
212 XOR_OPCODE => {
213 let inst = Xor::new(source, operand_width, destination);
214 match inst.emulate() {
215 Some(inst) => Ok(inst),
216 None => Ok(Instruction::Xor(inst)),
217 }
218 }
219 AND_OPCODE => Ok(Instruction::And(And::new(
220 source,
221 operand_width,
222 destination,
223 ))),
224 _ => Err(DecodeError::InvalidOpcode(opcode)),
225 }
226 }
227 }
228}
229
230#[cfg(test)]
231mod tests {
232 use super::*;
233 use crate::operand::Operand;
234
235 #[test]
236 fn empty_data() {
237 let data = [];
238 assert_eq!(decode(&data), Err(DecodeError::MissingInstruction));
239 }
240
241 #[test]
242 fn jnz() {
243 let data = [0x00, 0x20];
244 let inst = decode(&data);
245 assert_eq!(inst, Ok(Instruction::Jnz(Jnz::new(0))));
246 }
247
248 #[test]
249 fn negative_jnz() {
250 let data = [0xf9, 0x23];
251 let inst = decode(&data);
252 assert_eq!(inst, Ok(Instruction::Jnz(Jnz::new(-7))));
253 }
254
255 #[test]
256 fn jz() {
257 let data = [0x00, 0x24];
258 let inst = decode(&data);
259 assert_eq!(inst, Ok(Instruction::Jz(Jz::new(0))));
260 }
261
262 #[test]
263 fn jlo() {
264 let data = [0x00, 0x28];
265 let inst = decode(&data);
266 assert_eq!(inst, Ok(Instruction::Jlo(Jlo::new(0))));
267 }
268
269 #[test]
270 fn jlc() {
271 let data = [0x00, 0x2c];
272 let inst = decode(&data);
273 assert_eq!(inst, Ok(Instruction::Jc(Jc::new(0))));
274 }
275
276 #[test]
277 fn jn() {
278 let data = [0x00, 0x30];
279 let inst = decode(&data);
280 assert_eq!(inst, Ok(Instruction::Jn(Jn::new(0))));
281 }
282
283 #[test]
284 fn jge() {
285 let data = [0x00, 0x34];
286 let inst = decode(&data);
287 assert_eq!(inst, Ok(Instruction::Jge(Jge::new(0))));
288 }
289
290 #[test]
291 fn jl() {
292 let data = [0x00, 0x38];
293 let inst = decode(&data);
294 assert_eq!(inst, Ok(Instruction::Jl(Jl::new(0))));
295 }
296
297 #[test]
298 fn jmp() {
299 let data = [0x00, 0x3c];
300 let inst = decode(&data);
301 assert_eq!(inst, Ok(Instruction::Jmp(Jmp::new(0))));
302 }
303
304 #[test]
305 fn rrc_w_register_direct() {
306 let data = [0x09, 0x10];
307 let inst = decode(&data);
308 assert_eq!(
309 inst,
310 Ok(Instruction::Rrc(Rrc::new(
311 Operand::RegisterDirect(9),
312 Some(OperandWidth::Word)
313 )))
314 )
315 }
316
317 #[test]
318 fn rrc_b_register_direct() {
319 let data = [0x49, 0x10];
320 let inst = decode(&data);
321 assert_eq!(
322 inst,
323 Ok(Instruction::Rrc(Rrc::new(
324 Operand::RegisterDirect(9),
325 Some(OperandWidth::Byte)
326 )))
327 );
328 }
329
330 #[test]
331 fn rrc_w_indexed_positive() {
332 let data = [0x19, 0x10, 0x4, 0x0];
333 let inst = decode(&data);
334 assert_eq!(
335 inst,
336 Ok(Instruction::Rrc(Rrc::new(
337 Operand::Indexed((9, 4)),
338 Some(OperandWidth::Word)
339 )))
340 );
341 }
342
343 #[test]
344 fn rrc_w_indexed_negative() {
345 let data = [0x19, 0x10, 0xfb, 0xff];
346 let inst = decode(&data);
347 assert_eq!(
348 inst,
349 Ok(Instruction::Rrc(Rrc::new(
350 Operand::Indexed((9, -5)),
351 Some(OperandWidth::Word)
352 )))
353 );
354 }
355
356 #[test]
357 fn rrc_b_indexed_positive() {
358 let data = [0x59, 0x10, 0x04, 0x00];
359 let inst = decode(&data);
360 assert_eq!(
361 inst,
362 Ok(Instruction::Rrc(Rrc::new(
363 Operand::Indexed((9, 4)),
364 Some(OperandWidth::Byte)
365 )))
366 );
367 }
368
369 #[test]
370 fn rrc_b_indexed_negative() {
371 let data = [0x59, 0x10, 0xfb, 0xff];
372 let inst = decode(&data);
373 assert_eq!(
374 inst,
375 Ok(Instruction::Rrc(Rrc::new(
376 Operand::Indexed((9, -5)),
377 Some(OperandWidth::Byte)
378 )))
379 );
380 }
381
382 #[test]
383 fn rrc_w_register_indirect() {
384 let data = [0x29, 0x10];
385 let inst = decode(&data);
386 assert_eq!(
387 inst,
388 Ok(Instruction::Rrc(Rrc::new(
389 Operand::RegisterIndirect(9),
390 Some(OperandWidth::Word)
391 )))
392 );
393 }
394
395 #[test]
396 fn rrc_b_register_indirect() {
397 let data = [0x69, 0x10];
398 let inst = decode(&data);
399 assert_eq!(
400 inst,
401 Ok(Instruction::Rrc(Rrc::new(
402 Operand::RegisterIndirect(9),
403 Some(OperandWidth::Byte)
404 )))
405 );
406 }
407
408 #[test]
409 fn rrc_w_register_indirect_autoincrement() {
410 let data = [0x39, 0x10];
411 let inst = decode(&data);
412 assert_eq!(
413 inst,
414 Ok(Instruction::Rrc(Rrc::new(
415 Operand::RegisterIndirectAutoIncrement(9),
416 Some(OperandWidth::Word)
417 )))
418 );
419 }
420
421 #[test]
422 fn rrc_b_register_indirect_autoincrement() {
423 let data = [0x79, 0x10];
424 let inst = decode(&data);
425 assert_eq!(
426 inst,
427 Ok(Instruction::Rrc(Rrc::new(
428 Operand::RegisterIndirectAutoIncrement(9),
429 Some(OperandWidth::Byte)
430 )))
431 );
432 }
433
434 #[test]
435 fn swpb_register_direct() {
436 let data = [0x89, 0x10];
437 let inst = decode(&data);
438 assert_eq!(
439 inst,
440 Ok(Instruction::Swpb(Swpb::new(
441 Operand::RegisterDirect(9),
442 None
443 )))
444 );
445 }
446
447 #[test]
448 fn swpb_register_indexed_positive() {
449 let data = [0x99, 0x10, 0x04, 0x00];
450 let inst = decode(&data);
451 assert_eq!(
452 inst,
453 Ok(Instruction::Swpb(Swpb::new(Operand::Indexed((9, 4)), None)))
454 );
455 }
456
457 #[test]
458 fn swpb_register_indexed_negative() {
459 let data = [0x99, 0x10, 0xfb, 0xff];
460 let inst = decode(&data);
461 assert_eq!(
462 inst,
463 Ok(Instruction::Swpb(Swpb::new(
464 Operand::Indexed((9, -5)),
465 None
466 )))
467 );
468 }
469
470 #[test]
471 fn swpb_register_indirect() {
472 let data = [0xa9, 0x10];
473 let inst = decode(&data);
474 assert_eq!(
475 inst,
476 Ok(Instruction::Swpb(Swpb::new(
477 Operand::RegisterIndirect(9),
478 None
479 )))
480 );
481 }
482
483 #[test]
484 fn swpb_register_indirect_autoincrement() {
485 let data = [0xb9, 0x10];
486 let inst = decode(&data);
487 assert_eq!(
488 inst,
489 Ok(Instruction::Swpb(Swpb::new(
490 Operand::RegisterIndirectAutoIncrement(9),
491 None
492 )))
493 );
494 }
495
496 #[test]
497 fn rra_w_register_direct() {
498 let data = [0x09, 0x11];
499 let inst = decode(&data);
500 assert_eq!(
501 inst,
502 Ok(Instruction::Rra(Rra::new(
503 Operand::RegisterDirect(9),
504 Some(OperandWidth::Word)
505 )))
506 );
507 }
508
509 #[test]
510 fn rra_b_register_direct() {
511 let data = [0x49, 0x11];
512 let inst = decode(&data);
513 assert_eq!(
514 inst,
515 Ok(Instruction::Rra(Rra::new(
516 Operand::RegisterDirect(9),
517 Some(OperandWidth::Byte)
518 )))
519 );
520 }
521
522 #[test]
523 fn rra_w_indexed_positive() {
524 let data = [0x19, 0x11, 0x4, 0x0];
525 let inst = decode(&data);
526 assert_eq!(
527 inst,
528 Ok(Instruction::Rra(Rra::new(
529 Operand::Indexed((9, 4)),
530 Some(OperandWidth::Word)
531 )))
532 );
533 }
534
535 #[test]
536 fn rra_w_indexed_negative() {
537 let data = [0x19, 0x11, 0xfb, 0xff];
538 let inst = decode(&data);
539 assert_eq!(
540 inst,
541 Ok(Instruction::Rra(Rra::new(
542 Operand::Indexed((9, -5)),
543 Some(OperandWidth::Word)
544 )))
545 );
546 }
547
548 #[test]
549 fn rra_b_indexed_positive() {
550 let data = [0x59, 0x11, 0x04, 0x00];
551 let inst = decode(&data);
552 assert_eq!(
553 inst,
554 Ok(Instruction::Rra(Rra::new(
555 Operand::Indexed((9, 4)),
556 Some(OperandWidth::Byte)
557 )))
558 );
559 }
560
561 #[test]
562 fn rra_b_indexed_negative() {
563 let data = [0x59, 0x11, 0xfb, 0xff];
564 let inst = decode(&data);
565 assert_eq!(
566 inst,
567 Ok(Instruction::Rra(Rra::new(
568 Operand::Indexed((9, -5)),
569 Some(OperandWidth::Byte)
570 )))
571 );
572 }
573
574 #[test]
575 fn rra_w_register_indirect() {
576 let data = [0x29, 0x11];
577 let inst = decode(&data);
578 assert_eq!(
579 inst,
580 Ok(Instruction::Rra(Rra::new(
581 Operand::RegisterIndirect(9),
582 Some(OperandWidth::Word)
583 )))
584 );
585 }
586
587 #[test]
588 fn rra_b_register_indirect() {
589 let data = [0x69, 0x11];
590 let inst = decode(&data);
591 assert_eq!(
592 inst,
593 Ok(Instruction::Rra(Rra::new(
594 Operand::RegisterIndirect(9),
595 Some(OperandWidth::Byte)
596 )))
597 );
598 }
599
600 #[test]
601 fn rra_w_register_indirect_autoincrement() {
602 let data = [0x39, 0x11];
603 let inst = decode(&data);
604 assert_eq!(
605 inst,
606 Ok(Instruction::Rra(Rra::new(
607 Operand::RegisterIndirectAutoIncrement(9),
608 Some(OperandWidth::Word)
609 )))
610 );
611 }
612
613 #[test]
614 fn rra_b_register_indirect_autoincrement() {
615 let data = [0x79, 0x11];
616 let inst = decode(&data);
617 assert_eq!(
618 inst,
619 Ok(Instruction::Rra(Rra::new(
620 Operand::RegisterIndirectAutoIncrement(9),
621 Some(OperandWidth::Byte)
622 )))
623 );
624 }
625
626 #[test]
627 fn sxt_register_direct() {
628 let data = [0x89, 0x11];
629 let inst = decode(&data);
630 assert_eq!(
631 inst,
632 Ok(Instruction::Sxt(Sxt::new(Operand::RegisterDirect(9), None)))
633 );
634 }
635
636 #[test]
637 fn sxt_register_indexed_positive() {
638 let data = [0x99, 0x11, 0x04, 0x00];
639 let inst = decode(&data);
640 assert_eq!(
641 inst,
642 Ok(Instruction::Sxt(Sxt::new(Operand::Indexed((9, 4)), None)))
643 );
644 }
645
646 #[test]
647 fn sxt_register_indexed_negative() {
648 let data = [0x99, 0x11, 0xfb, 0xff];
649 let inst = decode(&data);
650 assert_eq!(
651 inst,
652 Ok(Instruction::Sxt(Sxt::new(Operand::Indexed((9, -5)), None)))
653 );
654 }
655
656 #[test]
657 fn sxt_register_indirect() {
658 let data = [0xa9, 0x11];
659 let inst = decode(&data);
660 assert_eq!(
661 inst,
662 Ok(Instruction::Sxt(Sxt::new(
663 Operand::RegisterIndirect(9),
664 None
665 )))
666 );
667 }
668
669 #[test]
670 fn sxt_register_indirect_autoincrement() {
671 let data = [0xb9, 0x11];
672 let inst = decode(&data);
673 assert_eq!(
674 inst,
675 Ok(Instruction::Sxt(Sxt::new(
676 Operand::RegisterIndirectAutoIncrement(9),
677 None
678 )))
679 );
680 }
681
682 #[test]
683 fn push_w_register_direct() {
684 let data = [0x09, 0x12];
685 let inst = decode(&data);
686 assert_eq!(
687 inst,
688 Ok(Instruction::Push(Push::new(
689 Operand::RegisterDirect(9),
690 Some(OperandWidth::Word)
691 )))
692 );
693 }
694
695 #[test]
696 fn push_b_register_direct() {
697 let data = [0x49, 0x12];
698 let inst = decode(&data);
699 assert_eq!(
700 inst,
701 Ok(Instruction::Push(Push::new(
702 Operand::RegisterDirect(9),
703 Some(OperandWidth::Byte)
704 )))
705 );
706 }
707
708 #[test]
709 fn push_w_indexed_positive() {
710 let data = [0x19, 0x12, 0x4, 0x0];
711 let inst = decode(&data);
712 assert_eq!(
713 inst,
714 Ok(Instruction::Push(Push::new(
715 Operand::Indexed((9, 4)),
716 Some(OperandWidth::Word)
717 )))
718 );
719 }
720
721 #[test]
722 fn push_w_indexed_negative() {
723 let data = [0x19, 0x12, 0xfb, 0xff];
724 let inst = decode(&data);
725 assert_eq!(
726 inst,
727 Ok(Instruction::Push(Push::new(
728 Operand::Indexed((9, -5)),
729 Some(OperandWidth::Word)
730 )))
731 );
732 }
733
734 #[test]
735 fn push_b_indexed_positive() {
736 let data = [0x59, 0x12, 0x04, 0x00];
737 let inst = decode(&data);
738 assert_eq!(
739 inst,
740 Ok(Instruction::Push(Push::new(
741 Operand::Indexed((9, 4)),
742 Some(OperandWidth::Byte)
743 )))
744 );
745 }
746
747 #[test]
748 fn push_b_indexed_negative() {
749 let data = [0x59, 0x12, 0xfb, 0xff];
750 let inst = decode(&data);
751 assert_eq!(
752 inst,
753 Ok(Instruction::Push(Push::new(
754 Operand::Indexed((9, -5)),
755 Some(OperandWidth::Byte)
756 ))),
757 );
758 }
759
760 #[test]
761 fn push_w_register_indirect() {
762 let data = [0x29, 0x12];
763 let inst = decode(&data);
764 assert_eq!(
765 inst,
766 Ok(Instruction::Push(Push::new(
767 Operand::RegisterIndirect(9),
768 Some(OperandWidth::Word)
769 )))
770 );
771 }
772
773 #[test]
774 fn push_b_register_indirect() {
775 let data = [0x69, 0x12];
776 let inst = decode(&data);
777 assert_eq!(
778 inst,
779 Ok(Instruction::Push(Push::new(
780 Operand::RegisterIndirect(9),
781 Some(OperandWidth::Byte)
782 )))
783 );
784 }
785
786 #[test]
787 fn push_w_register_indirect_autoincrement() {
788 let data = [0x39, 0x12];
789 let inst = decode(&data);
790 assert_eq!(
791 inst,
792 Ok(Instruction::Push(Push::new(
793 Operand::RegisterIndirectAutoIncrement(9),
794 Some(OperandWidth::Word)
795 )))
796 );
797 }
798
799 #[test]
800 fn push_b_register_indirect_autoincrement() {
801 let data = [0x79, 0x12];
802 let inst = decode(&data);
803 assert_eq!(
804 inst,
805 Ok(Instruction::Push(Push::new(
806 Operand::RegisterIndirectAutoIncrement(9),
807 Some(OperandWidth::Byte)
808 )))
809 );
810 }
811
812 #[test]
813 fn push_const_sr_one() {
814 let data = [0x12, 0x12, 0x0, 0x44];
815 let inst = decode(&data);
816 assert_eq!(
817 inst,
818 Ok(Instruction::Push(Push::new(
819 Operand::Absolute(0x4400),
820 Some(OperandWidth::Word)
821 )))
822 );
823 }
824
825 #[test]
826 fn push_const_sr_two() {
827 let data = [0x22, 0x12];
828 let inst = decode(&data);
829 assert_eq!(
830 inst,
831 Ok(Instruction::Push(Push::new(
832 Operand::Constant(4),
833 Some(OperandWidth::Word)
834 )))
835 );
836 }
837
838 #[test]
839 fn push_const_sr_three() {
840 let data = [0x32, 0x12];
841 let inst = decode(&data);
842 assert_eq!(
843 inst,
844 Ok(Instruction::Push(Push::new(
845 Operand::Constant(8),
846 Some(OperandWidth::Word)
847 )))
848 );
849 }
850
851 #[test]
852 fn push_const_cg_zero() {
853 let data = [0x03, 0x12];
854 let inst = decode(&data);
855 assert_eq!(
856 inst,
857 Ok(Instruction::Push(Push::new(
858 Operand::Constant(0),
859 Some(OperandWidth::Word)
860 )))
861 );
862 }
863
864 #[test]
865 fn push_const_cg_one() {
866 let data = [0x13, 0x12];
867 let inst = decode(&data);
868 assert_eq!(
869 inst,
870 Ok(Instruction::Push(Push::new(
871 Operand::Constant(1),
872 Some(OperandWidth::Word)
873 )))
874 );
875 }
876
877 #[test]
878 fn push_const_cg_two() {
879 let data = [0x23, 0x12];
880 let inst = decode(&data);
881 assert_eq!(
882 inst,
883 Ok(Instruction::Push(Push::new(
884 Operand::Constant(2),
885 Some(OperandWidth::Word)
886 )))
887 );
888 }
889
890 #[test]
891 fn push_const_cg_three() {
892 let data = [0x33, 0x12];
893 let inst = decode(&data);
894 assert_eq!(
895 inst,
896 Ok(Instruction::Push(Push::new(
897 Operand::Constant(-1),
898 Some(OperandWidth::Word)
899 )))
900 );
901 }
902
903 #[test]
904 fn call_register_direct() {
905 let data = [0x89, 0x12];
906 let inst = decode(&data);
907 assert_eq!(
908 inst,
909 Ok(Instruction::Call(Call::new(
910 Operand::RegisterDirect(9),
911 None
912 )))
913 );
914 }
915
916 #[test]
917 fn call_register_indexed_positive() {
918 let data = [0x99, 0x12, 0x04, 0x00];
919 let inst = decode(&data);
920 assert_eq!(
921 inst,
922 Ok(Instruction::Call(Call::new(Operand::Indexed((9, 4)), None)))
923 );
924 }
925
926 #[test]
927 fn call_register_indexed_negative() {
928 let data = [0x99, 0x12, 0xfb, 0xff];
929 let inst = decode(&data);
930 assert_eq!(
931 inst,
932 Ok(Instruction::Call(Call::new(
933 Operand::Indexed((9, -5)),
934 None
935 )))
936 );
937 }
938
939 #[test]
940 fn call_register_indirect() {
941 let data = [0xa9, 0x12];
942 let inst = decode(&data);
943 assert_eq!(
944 inst,
945 Ok(Instruction::Call(Call::new(
946 Operand::RegisterIndirect(9),
947 None
948 )))
949 );
950 }
951
952 #[test]
953 fn call_register_indirect_autoincrement() {
954 let data = [0xb9, 0x12];
955 let inst = decode(&data);
956 assert_eq!(
957 inst,
958 Ok(Instruction::Call(Call::new(
959 Operand::RegisterIndirectAutoIncrement(9),
960 None
961 )))
962 );
963 }
964
965 #[test]
966 fn call_pc_symbolic() {
967 let data = [0x90, 0x12, 0x2, 0x0];
968 let inst = decode(&data);
969 assert_eq!(
970 inst,
971 Ok(Instruction::Call(Call::new(Operand::Symbolic(2), None)))
972 );
973 }
974
975 #[test]
976 fn call_pc_immediate() {
977 let data = [0xb0, 0x12, 0x2, 0x0];
978 let inst = decode(&data);
979 assert_eq!(
980 inst,
981 Ok(Instruction::Call(Call::new(Operand::Immediate(2), None)))
982 );
983 }
984
985 #[test]
986 fn reti() {
987 let data = [0x00, 0x13];
988 let inst = decode(&data);
989 assert_eq!(inst, Ok(Instruction::Reti(Reti::new())));
990 }
991
992 #[test]
993 fn push_sr() {
994 let data = [0x02, 0x12];
995 let inst = decode(&data);
996 assert_eq!(
997 inst,
998 Ok(Instruction::Push(Push::new(
999 Operand::RegisterDirect(2),
1000 Some(OperandWidth::Word),
1001 )))
1002 );
1003 }
1004}