msp430_asm/
lib.rs

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
50/// JMP_MASK masks off the high three bits to check whether the pattern 001
51/// is present. This describes a JMP instruction
52const JMP_INSTRUCTION: u16 = 0b0010_0000_0000_0000;
53
54/// JMP_CONDITION_MASK masks off the three bits used to denote the Jxx condition
55const JMP_CONDITION_MASK: u16 = 0b0001_1100_0000_0000;
56
57/// JMP_OFFSET masks off the lower 10 bits used to represent the offset.
58/// This can be a negative offset and it represented as such in one's
59/// compliment
60const 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
69/// Stores the return type for a decode
70pub type Result<T> = std::result::Result<T, DecodeError>;
71
72/// Decodes the next instruction represented in the slice passed to it. This
73/// will only decode a single instruction. To use this correctly to decode a
74/// series of instructions, you keep track of the number of the size of the
75/// last decoded instruction to remove those bytes from the input to correctly
76/// decode the next due to the fact that instructions are not fixed width and
77/// maybe 2, 4 or 6 bytes
78pub 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            // The opcode is the first four bits for this type of
126            // instruction so there isn't a simple mask we can check.
127            // If it doesn't match a single operand or jmp instuction
128            // we'll fall through to here and attempt to match a two
129            // operand. If it doesn't match any we'll return None
130            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            // if source has an additional word it is encoded before the destination
138            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}