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}