Skip to main content

c6000_disassembler/instruction/
moving.rs

1use crate::instruction::{
2    C6000Instruction, ConditionalOperation, InstructionData, Unit,
3    parser::{ParsedVariable, ParsingInstruction, parse},
4    register::{ControlRegister, Register, RegisterFile},
5};
6
7pub struct MoveConstantInstruction {
8    pub high: bool,
9    pub constant: u32,
10    pub destination: Register,
11    pub unit: Unit,
12    instruction_data: InstructionData,
13}
14
15impl C6000Instruction for MoveConstantInstruction {
16    fn new(input: &super::InstructionInput) -> std::io::Result<Self> {
17        let format_combinations = [
18            (
19                Unit::S,
20                vec![
21                    ParsingInstruction::Bit {
22                        name: String::from("p"),
23                    },
24                    ParsingInstruction::Bit {
25                        name: String::from("s"),
26                    },
27                    ParsingInstruction::Match {
28                        size: 4,
29                        value: 0b01010,
30                    },
31                    ParsingInstruction::Bit {
32                        name: String::from("h"),
33                    },
34                    ParsingInstruction::Unsigned {
35                        size: 16,
36                        name: String::from("cst"),
37                    },
38                    ParsingInstruction::Register {
39                        size: 5,
40                        name: String::from("dst"),
41                    },
42                    ParsingInstruction::ConditionalOperation {
43                        name: String::from("cond"),
44                    },
45                ],
46            ),
47            (
48                Unit::L,
49                vec![
50                    ParsingInstruction::Bit {
51                        name: String::from("p"),
52                    },
53                    ParsingInstruction::Bit {
54                        name: String::from("s"),
55                    },
56                    ParsingInstruction::Match {
57                        size: 10,
58                        value: 0b0011010110,
59                    },
60                    ParsingInstruction::Bit {
61                        name: String::from("x"),
62                    },
63                    ParsingInstruction::Match {
64                        size: 5,
65                        value: 0b00101,
66                    },
67                    ParsingInstruction::Unsigned {
68                        size: 5,
69                        name: String::from("cst"),
70                    },
71                    ParsingInstruction::Register {
72                        size: 5,
73                        name: String::from("dst"),
74                    },
75                    ParsingInstruction::ConditionalOperation {
76                        name: String::from("cond"),
77                    },
78                ],
79            ),
80            (
81                Unit::D,
82                vec![
83                    ParsingInstruction::Bit {
84                        name: String::from("p"),
85                    },
86                    ParsingInstruction::Bit {
87                        name: String::from("s"),
88                    },
89                    ParsingInstruction::Match {
90                        size: 11,
91                        value: 0b00000010000,
92                    },
93                    ParsingInstruction::Unsigned {
94                        size: 5,
95                        name: String::from("cst"),
96                    },
97                    ParsingInstruction::Match { size: 5, value: 0 },
98                    ParsingInstruction::Register {
99                        size: 5,
100                        name: String::from("dst"),
101                    },
102                    ParsingInstruction::ConditionalOperation {
103                        name: String::from("cond"),
104                    },
105                ],
106            ),
107        ];
108        for (unit, format) in format_combinations {
109            let Ok(parsed_variables) = parse(input.opcode, format.as_slice()) else {
110                continue;
111            };
112            let p_bit = ParsedVariable::try_get(&parsed_variables, "p")?.get_bool()?;
113            let constant = ParsedVariable::try_get(&parsed_variables, "cst")?.get_u32()?;
114            let destination = ParsedVariable::try_get(&parsed_variables, "dst")?.get_register()?;
115            let high = {
116                if unit == Unit::S {
117                    ParsedVariable::try_get(&parsed_variables, "h")?.get_bool()?
118                } else {
119                    false
120                }
121            };
122            let conditional_operation =
123                ParsedVariable::try_get(&parsed_variables, "cond")?.get_conditional_operation()?;
124            return Ok(Self {
125                high,
126                constant,
127                destination,
128                unit,
129                instruction_data: InstructionData {
130                    opcode: input.opcode,
131                    conditional_operation,
132                    p_bit,
133                    ..Default::default()
134                },
135            });
136        }
137        Err(std::io::Error::new(
138            std::io::ErrorKind::InvalidInput,
139            format!("Not a Move Constant instruction: No matches found."),
140        ))
141    }
142
143    fn new_compact(input: &super::InstructionInput) -> std::io::Result<Self> {
144        let format_combinations = [
145            (
146                Unit::S,
147                vec![
148                    ParsingInstruction::Bit {
149                        name: String::from("s"),
150                    },
151                    ParsingInstruction::Match {
152                        size: 4,
153                        value: 0b1001,
154                    },
155                    ParsingInstruction::Unsigned {
156                        size: 2,
157                        name: String::from("cst65"),
158                    },
159                    ParsingInstruction::Register {
160                        size: 3,
161                        name: String::from("dst"),
162                    },
163                    ParsingInstruction::Unsigned {
164                        size: 1,
165                        name: String::from("cst7"),
166                    },
167                    ParsingInstruction::Unsigned {
168                        size: 2,
169                        name: String::from("cst43"),
170                    },
171                    ParsingInstruction::Unsigned {
172                        size: 3,
173                        name: String::from("cst20"),
174                    },
175                ],
176            ),
177            (
178                Unit::L,
179                vec![
180                    ParsingInstruction::Bit {
181                        name: String::from("s"),
182                    },
183                    ParsingInstruction::Match {
184                        size: 6,
185                        value: 0b010011,
186                    },
187                    ParsingInstruction::Register {
188                        size: 3,
189                        name: String::from("dst"),
190                    },
191                    ParsingInstruction::Match { size: 1, value: 1 },
192                    ParsingInstruction::Unsigned {
193                        size: 2,
194                        name: String::from("cst43"),
195                    },
196                    ParsingInstruction::Unsigned {
197                        size: 3,
198                        name: String::from("cst20"),
199                    },
200                ],
201            ),
202        ];
203        for (unit, format) in format_combinations {
204            let Ok(parsed_variables) = parse(input.opcode, format.as_slice()) else {
205                continue;
206            };
207            let mut constant = ParsedVariable::try_get(&parsed_variables, "cst20")?.get_u8()?;
208            constant += ParsedVariable::try_get(&parsed_variables, "cst43")?.get_u8()? << 3;
209            if unit == Unit::S {
210                constant += ParsedVariable::try_get(&parsed_variables, "cst65")?.get_u8()? << 5;
211                constant += ParsedVariable::try_get(&parsed_variables, "cst7")?.get_u8()? << 7;
212            }
213            let destination = ParsedVariable::try_get(&parsed_variables, "dst")?.get_register()?;
214            return Ok(Self {
215                high: false,
216                constant: constant as u32,
217                destination,
218                unit,
219                instruction_data: InstructionData {
220                    opcode: input.opcode,
221                    compact: true,
222                    ..Default::default()
223                },
224            });
225        }
226
227        let multiunit_formats = [
228            vec![
229                ParsingInstruction::Bit {
230                    name: String::from("s"),
231                },
232                ParsingInstruction::Match {
233                    size: 2,
234                    value: 0b11,
235                },
236                ParsingInstruction::LSDUnit {
237                    name: String::from("unit"),
238                },
239                ParsingInstruction::Match {
240                    size: 2,
241                    value: 0b11,
242                },
243                ParsingInstruction::Register {
244                    size: 3,
245                    name: String::from("dst"),
246                },
247                ParsingInstruction::Match {
248                    size: 3,
249                    value: 0b010,
250                },
251                ParsingInstruction::Unsigned {
252                    size: 1,
253                    name: String::from("cst"),
254                },
255                ParsingInstruction::Unsigned {
256                    size: 2,
257                    name: String::from("cc"),
258                },
259            ],
260            vec![
261                ParsingInstruction::Bit {
262                    name: String::from("s"),
263                },
264                ParsingInstruction::Match {
265                    size: 2,
266                    value: 0b11,
267                },
268                ParsingInstruction::LSDUnit {
269                    name: String::from("unit"),
270                },
271                ParsingInstruction::Match {
272                    size: 2,
273                    value: 0b11,
274                },
275                ParsingInstruction::Register {
276                    size: 3,
277                    name: String::from("dst"),
278                },
279                ParsingInstruction::Match {
280                    size: 3,
281                    value: 0b110,
282                },
283                ParsingInstruction::Unsigned {
284                    size: 1,
285                    name: String::from("cst"),
286                },
287                ParsingInstruction::Match {
288                    size: 2,
289                    value: 0b00,
290                },
291            ],
292        ];
293
294        for format in multiunit_formats {
295            let Ok(parsed_variables) = parse(input.opcode as u32, format.as_slice()) else {
296                continue;
297            };
298            let constant = ParsedVariable::try_get(&parsed_variables, "cst")?.get_u32()?;
299            let destination = ParsedVariable::try_get(&parsed_variables, "dst")?.get_register()?;
300            let unit = ParsedVariable::try_get(&parsed_variables, "unit")?.get_unit()?;
301            let conditional_operation = {
302                if let Ok(variable) = ParsedVariable::try_get(&parsed_variables, "cc") {
303                    match variable.get_u8()? {
304                        0 => Some(ConditionalOperation::NonZero(Register::A(0))),
305                        1 => Some(ConditionalOperation::Zero(Register::A(0))),
306                        2 => Some(ConditionalOperation::NonZero(Register::B(0))),
307                        3 => Some(ConditionalOperation::Zero(Register::B(0))),
308                        _ => None,
309                    }
310                } else {
311                    None
312                }
313            };
314            return Ok(Self {
315                high: false,
316                constant,
317                destination,
318                unit,
319                instruction_data: InstructionData {
320                    opcode: input.opcode,
321                    conditional_operation,
322                    compact: true,
323                    ..Default::default()
324                },
325            });
326        }
327
328        Err(std::io::Error::new(
329            std::io::ErrorKind::InvalidInput,
330            format!("Not a Move Constant instruction: No matches found."),
331        ))
332    }
333
334    fn instruction_clean(&self) -> String {
335        if self.high {
336            String::from("MVKH")
337        } else {
338            String::from("MVK")
339        }
340    }
341
342    fn instruction(&self) -> String {
343        let mut value = self.instruction_clean();
344        value += ".";
345        let side = self.destination.side();
346        value += self.unit.to_sided_string(side).as_str();
347        value
348    }
349
350    fn operands(&self) -> String {
351        format!("0x{:04X}, {}", self.constant, self.destination.to_string())
352    }
353
354    fn instruction_data(&self) -> &InstructionData {
355        &self.instruction_data
356    }
357
358    fn instruction_data_mut(&mut self) -> &mut InstructionData {
359        &mut self.instruction_data
360    }
361}
362
363pub struct MoveRegisterInstruction {
364    pub source: RegisterFile,
365    pub destination: RegisterFile,
366    side: bool,
367    pub delayed: bool,
368    pub unit: Unit,
369    instruction_data: InstructionData,
370}
371
372impl MoveRegisterInstruction {
373    fn new_mv(opcode: u32) -> std::io::Result<Self> {
374        let format_combinations = [
375            (
376                Unit::S,
377                vec![
378                    ParsingInstruction::Bit {
379                        name: String::from("p"),
380                    },
381                    ParsingInstruction::Bit {
382                        name: String::from("s"),
383                    },
384                    ParsingInstruction::Match {
385                        size: 10,
386                        value: 0b0001101000,
387                    },
388                    ParsingInstruction::Bit {
389                        name: String::from("x"),
390                    },
391                    ParsingInstruction::Match { size: 5, value: 0 },
392                    ParsingInstruction::RegisterCrosspath {
393                        size: 5,
394                        name: String::from("src"),
395                    },
396                    ParsingInstruction::Register {
397                        size: 5,
398                        name: String::from("dst"),
399                    },
400                    ParsingInstruction::ConditionalOperation {
401                        name: String::from("cond"),
402                    },
403                ],
404            ),
405            (
406                Unit::L,
407                vec![
408                    ParsingInstruction::Bit {
409                        name: String::from("p"),
410                    },
411                    ParsingInstruction::Bit {
412                        name: String::from("s"),
413                    },
414                    ParsingInstruction::Match {
415                        size: 16,
416                        value: 0x106,
417                    },
418                    ParsingInstruction::RegisterPair {
419                        size: 5,
420                        name: String::from("src"),
421                    },
422                    ParsingInstruction::RegisterPair {
423                        size: 5,
424                        name: String::from("dst"),
425                    },
426                    ParsingInstruction::ConditionalOperation {
427                        name: String::from("cond"),
428                    },
429                ],
430            ),
431            (
432                Unit::L,
433                vec![
434                    ParsingInstruction::Bit {
435                        name: String::from("p"),
436                    },
437                    ParsingInstruction::Bit {
438                        name: String::from("s"),
439                    },
440                    ParsingInstruction::Match {
441                        size: 3,
442                        value: 0b110,
443                    },
444                    ParsingInstruction::MatchMultiple {
445                        size: 7,
446                        values: vec![0x2, 0x7E],
447                    },
448                    ParsingInstruction::Bit {
449                        name: String::from("x"),
450                    },
451                    ParsingInstruction::Match { size: 5, value: 0 },
452                    ParsingInstruction::Register {
453                        size: 5,
454                        name: String::from("src"),
455                    },
456                    ParsingInstruction::Register {
457                        size: 5,
458                        name: String::from("dst"),
459                    },
460                    ParsingInstruction::ConditionalOperation {
461                        name: String::from("cond"),
462                    },
463                ],
464            ),
465            (
466                Unit::D,
467                vec![
468                    ParsingInstruction::Bit {
469                        name: String::from("p"),
470                    },
471                    ParsingInstruction::Bit {
472                        name: String::from("s"),
473                    },
474                    ParsingInstruction::Match {
475                        size: 16,
476                        value: 0x250,
477                    },
478                    ParsingInstruction::Register {
479                        size: 5,
480                        name: String::from("src"),
481                    },
482                    ParsingInstruction::Register {
483                        size: 5,
484                        name: String::from("dst"),
485                    },
486                    ParsingInstruction::ConditionalOperation {
487                        name: String::from("cond"),
488                    },
489                ],
490            ),
491            (
492                Unit::D,
493                vec![
494                    ParsingInstruction::Bit {
495                        name: String::from("p"),
496                    },
497                    ParsingInstruction::Bit {
498                        name: String::from("s"),
499                    },
500                    ParsingInstruction::Match {
501                        size: 10,
502                        value: 0x23C,
503                    },
504                    ParsingInstruction::Bit {
505                        name: String::from("x"),
506                    },
507                    ParsingInstruction::Match { size: 5, value: 0 },
508                    ParsingInstruction::RegisterCrosspath {
509                        size: 5,
510                        name: String::from("src"),
511                    },
512                    ParsingInstruction::Register {
513                        size: 5,
514                        name: String::from("dst"),
515                    },
516                    ParsingInstruction::ConditionalOperation {
517                        name: String::from("cond"),
518                    },
519                ],
520            ),
521            (
522                Unit::M,
523                vec![
524                    ParsingInstruction::Bit {
525                        name: String::from("p"),
526                    },
527                    ParsingInstruction::Bit {
528                        name: String::from("s"),
529                    },
530                    ParsingInstruction::Match {
531                        size: 10,
532                        value: 0x3C,
533                    },
534                    ParsingInstruction::Bit {
535                        name: String::from("x"),
536                    },
537                    ParsingInstruction::Match {
538                        size: 5,
539                        value: 0x1A,
540                    },
541                    ParsingInstruction::Register {
542                        size: 5,
543                        name: String::from("src"),
544                    },
545                    ParsingInstruction::Register {
546                        size: 5,
547                        name: String::from("dst"),
548                    },
549                    ParsingInstruction::ConditionalOperation {
550                        name: String::from("cond"),
551                    },
552                ],
553            ),
554        ];
555        for (unit, format) in format_combinations {
556            let Ok(parsed_variables) = parse(opcode, format.as_slice()) else {
557                continue;
558            };
559            let p_bit = ParsedVariable::try_get(&parsed_variables, "p")?.get_bool()?;
560            let side = ParsedVariable::try_get(&parsed_variables, "s")?.get_bool()?;
561            let source_register =
562                ParsedVariable::try_get(&parsed_variables, "src")?.get_register()?;
563            let destination_register =
564                ParsedVariable::try_get(&parsed_variables, "dst")?.get_register()?;
565            let source = RegisterFile::GeneralPurpose(source_register);
566            let destination = RegisterFile::GeneralPurpose(destination_register);
567            let conditional_operation =
568                ParsedVariable::try_get(&parsed_variables, "cond")?.get_conditional_operation()?;
569            let delayed = if unit == Unit::M { true } else { false };
570            return Ok(Self {
571                source,
572                destination,
573                unit,
574                side,
575                delayed,
576                instruction_data: InstructionData {
577                    opcode,
578                    conditional_operation,
579                    p_bit,
580                    ..Default::default()
581                },
582            });
583        }
584        Err(std::io::Error::other("Not MV/MVD"))
585    }
586
587    fn new_mvc(opcode: u32) -> std::io::Result<Self> {
588        let format_combinations = [
589            vec![
590                ParsingInstruction::Bit {
591                    name: String::from("p"),
592                },
593                ParsingInstruction::BitMatch {
594                    name: String::from("s"),
595                    value: true,
596                },
597                ParsingInstruction::Match {
598                    size: 10,
599                    value: 0b0011111000,
600                },
601                ParsingInstruction::Bit {
602                    name: String::from("x"),
603                },
604                ParsingInstruction::Match { size: 5, value: 0 },
605                ParsingInstruction::ControlRegister {
606                    size: 5,
607                    name: String::from("crlo"),
608                },
609                ParsingInstruction::Register {
610                    size: 5,
611                    name: String::from("dst"),
612                },
613                ParsingInstruction::ConditionalOperation {
614                    name: String::from("cond"),
615                },
616            ],
617            vec![
618                ParsingInstruction::Bit {
619                    name: String::from("p"),
620                },
621                ParsingInstruction::BitMatch {
622                    name: String::from("s"),
623                    value: true,
624                },
625                ParsingInstruction::Match {
626                    size: 10,
627                    value: 0b0011101000,
628                },
629                ParsingInstruction::Bit {
630                    name: String::from("x"),
631                },
632                ParsingInstruction::Match { size: 5, value: 0 },
633                ParsingInstruction::Register {
634                    size: 5,
635                    name: String::from("src"),
636                },
637                ParsingInstruction::ControlRegister {
638                    size: 5,
639                    name: String::from("crlo"),
640                },
641                ParsingInstruction::ConditionalOperation {
642                    name: String::from("cond"),
643                },
644            ],
645            vec![
646                ParsingInstruction::Bit {
647                    name: String::from("p"),
648                },
649                ParsingInstruction::BitMatch {
650                    name: String::from("s"),
651                    value: true,
652                },
653                ParsingInstruction::Match {
654                    size: 10,
655                    value: 0b0011111000,
656                },
657                ParsingInstruction::Bit {
658                    name: String::from("x"),
659                },
660                ParsingInstruction::Unsigned {
661                    size: 5,
662                    name: String::from("crhi"),
663                },
664                ParsingInstruction::ControlRegister {
665                    size: 5,
666                    name: String::from("crlo"),
667                },
668                ParsingInstruction::Register {
669                    size: 5,
670                    name: String::from("dst"),
671                },
672                ParsingInstruction::ConditionalOperation {
673                    name: String::from("cond"),
674                },
675            ],
676            vec![
677                ParsingInstruction::Bit {
678                    name: String::from("p"),
679                },
680                ParsingInstruction::BitMatch {
681                    name: String::from("s"),
682                    value: true,
683                },
684                ParsingInstruction::Match {
685                    size: 10,
686                    value: 0b0011101000,
687                },
688                ParsingInstruction::Bit {
689                    name: String::from("x"),
690                },
691                ParsingInstruction::Unsigned {
692                    size: 5,
693                    name: String::from("crhi"),
694                },
695                ParsingInstruction::Register {
696                    size: 5,
697                    name: String::from("src"),
698                },
699                ParsingInstruction::ControlRegister {
700                    size: 5,
701                    name: String::from("crlo"),
702                },
703                ParsingInstruction::ConditionalOperation {
704                    name: String::from("cond"),
705                },
706            ],
707        ];
708        for format in format_combinations {
709            let Ok(parsed_variables) = parse(opcode, format.as_slice()) else {
710                continue;
711            };
712            let p_bit = ParsedVariable::try_get(&parsed_variables, "p")?.get_bool()?;
713            let control_register =
714                ParsedVariable::try_get(&parsed_variables, "crlo")?.get_control_register()?;
715            let (source, destination) = {
716                if let Ok(variable) = ParsedVariable::try_get(&parsed_variables, "dst") {
717                    let destination_register = variable.get_register()?;
718                    (
719                        RegisterFile::Control(control_register),
720                        RegisterFile::GeneralPurpose(destination_register),
721                    )
722                } else if let Ok(variable) = ParsedVariable::try_get(&parsed_variables, "src") {
723                    let source_register = variable.get_register()?;
724                    (
725                        RegisterFile::GeneralPurpose(source_register),
726                        RegisterFile::Control(control_register),
727                    )
728                } else {
729                    continue;
730                }
731            };
732            let conditional_operation =
733                ParsedVariable::try_get(&parsed_variables, "cond")?.get_conditional_operation()?;
734            return Ok(Self {
735                source,
736                destination,
737                unit: Unit::S,
738                side: true,
739                delayed: false,
740                instruction_data: InstructionData {
741                    opcode,
742                    conditional_operation,
743                    p_bit,
744                    ..Default::default()
745                },
746            });
747        }
748        Err(std::io::Error::other("Not MVC"))
749    }
750}
751
752impl C6000Instruction for MoveRegisterInstruction {
753    fn new(input: &super::InstructionInput) -> std::io::Result<Self> {
754        if let Ok(ret_val) = Self::new_mv(input.opcode) {
755            return Ok(ret_val);
756        } else if let Ok(ret_val) = Self::new_mvc(input.opcode) {
757            return Ok(ret_val);
758        }
759
760        Err(std::io::Error::new(
761            std::io::ErrorKind::InvalidInput,
762            format!("Not a Move Register instruction: No matches found."),
763        ))
764    }
765
766    fn new_compact(input: &super::InstructionInput) -> std::io::Result<Self> {
767        let mv_format = [
768            ParsingInstruction::Bit {
769                name: String::from("s"),
770            },
771            ParsingInstruction::Match {
772                size: 2,
773                value: 0b11,
774            },
775            ParsingInstruction::LSDUnit {
776                name: String::from("unit"),
777            },
778            ParsingInstruction::Match { size: 1, value: 0 },
779            ParsingInstruction::Bit {
780                name: String::from("ms_bit"),
781            },
782            ParsingInstruction::Register {
783                size: 3,
784                name: String::from("src"),
785            },
786            ParsingInstruction::Unsigned {
787                size: 2,
788                name: String::from("ms"),
789            },
790            ParsingInstruction::Bit {
791                name: String::from("x"),
792            },
793            ParsingInstruction::Register {
794                size: 3,
795                name: String::from("dst"),
796            },
797        ];
798
799        let mvc_format = [
800            ParsingInstruction::Bit {
801                name: String::from("s"),
802            },
803            ParsingInstruction::Match {
804                size: 6,
805                value: 0b110111,
806            },
807            ParsingInstruction::Register {
808                size: 3,
809                name: String::from("src"),
810            },
811            ParsingInstruction::Match {
812                size: 6,
813                value: 0b110110,
814            },
815        ];
816
817        if let Ok(parsed_variables) = parse(input.opcode, &mv_format) {
818            let unit = ParsedVariable::try_get(&parsed_variables, "unit")?.get_unit()?;
819            let side = ParsedVariable::try_get(&parsed_variables, "s")?.get_bool()?;
820            let crosspath = ParsedVariable::try_get(&parsed_variables, "x")?.get_bool()?;
821            let ms_bit = ParsedVariable::try_get(&parsed_variables, "ms_bit")?.get_bool()?;
822            let ms = ParsedVariable::try_get(&parsed_variables, "ms")?.get_u8()?;
823            let mut source_register =
824                ParsedVariable::try_get(&parsed_variables, "src")?.get_register()?;
825            let mut destination_register =
826                ParsedVariable::try_get(&parsed_variables, "dst")?.get_register()?;
827            if ms_bit {
828                destination_register += (ms) << 3;
829            } else {
830                source_register += (ms) << 3;
831            }
832            if crosspath {
833                source_register = !source_register;
834            }
835            let source = RegisterFile::GeneralPurpose(source_register);
836            let destination = RegisterFile::GeneralPurpose(destination_register);
837            return Ok(Self {
838                source,
839                destination,
840                side,
841                delayed: false,
842                unit,
843                instruction_data: InstructionData {
844                    opcode: input.opcode,
845                    compact: true,
846                    ..Default::default()
847                },
848            });
849        } else if let Ok(parsed_variables) = parse(input.opcode, &mvc_format) {
850            let side = ParsedVariable::try_get(&parsed_variables, "s")?.get_bool()?;
851            let source_register =
852                ParsedVariable::try_get(&parsed_variables, "src")?.get_register()?;
853            let source = RegisterFile::GeneralPurpose(source_register);
854            let destination = RegisterFile::Control(ControlRegister::ILC);
855            return Ok(Self {
856                source,
857                destination,
858                side,
859                delayed: false,
860                unit: Unit::S,
861                instruction_data: InstructionData {
862                    opcode: input.opcode,
863                    compact: true,
864                    ..Default::default()
865                },
866            });
867        }
868
869        Err(std::io::Error::new(
870            std::io::ErrorKind::InvalidInput,
871            format!("Not a Move Register instruction: No matches found."),
872        ))
873    }
874
875    fn instruction_clean(&self) -> String {
876        if self.destination.side() == None || self.source.side() == None {
877            String::from("MVC")
878        } else if self.delayed {
879            String::from("MVD")
880        } else {
881            String::from("MV")
882        }
883    }
884
885    fn instruction(&self) -> String {
886        let mut value = format!(
887            "{}.{}",
888            self.instruction_clean(),
889            self.unit.to_sided_string(self.side)
890        );
891
892        if self.destination.side() == Some(!self.side) || self.source.side() == Some(!self.side) {
893            value += "X";
894        }
895        value
896    }
897
898    fn operands(&self) -> String {
899        format!(
900            "{}, {}",
901            self.source.to_string(),
902            self.destination.to_string()
903        )
904    }
905
906    fn instruction_data(&self) -> &InstructionData {
907        &self.instruction_data
908    }
909
910    fn instruction_data_mut(&mut self) -> &mut InstructionData {
911        &mut self.instruction_data
912    }
913}