Skip to main content

c6000_disassembler/
instruction.rs

1use crate::instruction::fphead::CompactInstructionHeader;
2use crate::instruction::register::Register;
3use std::any::Any;
4use std::fmt::Display;
5use std::io::{Error, ErrorKind, Result};
6
7pub mod branching;
8pub mod fphead;
9pub mod invalid;
10pub mod memory;
11pub mod moving;
12pub mod nop;
13pub mod parser;
14pub mod register;
15
16pub trait AsAny {
17    fn as_any(&self) -> &dyn Any;
18    fn as_any_mut(&mut self) -> &mut dyn Any;
19}
20
21impl<T: Any> AsAny for T {
22    fn as_any(&self) -> &dyn Any {
23        self
24    }
25
26    fn as_any_mut(&mut self) -> &mut dyn Any {
27        self
28    }
29}
30
31pub trait C6000Instruction: AsAny {
32    fn new(_input: &InstructionInput) -> Result<Self>
33    where
34        Self: Sized,
35    {
36        Err(Error::new(ErrorKind::Unsupported, "Instruction not 32-bit"))
37    }
38    fn new_compact(_input: &InstructionInput) -> Result<Self>
39    where
40        Self: Sized,
41    {
42        Err(Error::new(
43            ErrorKind::Unsupported,
44            "Instruction not compact (16-bit)",
45        ))
46    }
47    fn instruction(&self) -> String;
48    fn instruction_clean(&self) -> String {
49        self.instruction()
50    }
51    fn operands(&self) -> String {
52        String::from("")
53    }
54    fn instruction_data(&self) -> &InstructionData;
55    fn instruction_data_mut(&mut self) -> &mut InstructionData;
56    fn opcode(&self) -> u32 {
57        self.instruction_data().opcode
58    }
59    fn is_compact(&self) -> bool {
60        self.instruction_data().compact
61    }
62    fn is_parallel(&self) -> bool {
63        self.instruction_data().parallel
64    }
65    fn get_p_bit(&self) -> bool {
66        self.instruction_data().p_bit
67    }
68    fn set_parallel(&mut self, parallel: bool) {
69        self.instruction_data_mut().parallel = parallel;
70    }
71    fn conditional_operation(&self) -> Option<ConditionalOperation> {
72        self.instruction_data().conditional_operation
73    }
74}
75
76pub struct InstructionInput {
77    pub opcode: u32,
78    pub fphead: Option<CompactInstructionHeader>,
79    pub pce1_address: u32,
80}
81
82#[derive(Clone)]
83pub struct InstructionData {
84    pub opcode: u32,
85    pub compact: bool,
86    pub parallel: bool,
87    /// Determines if the next instruction will be executed in parallel
88    pub p_bit: bool,
89    pub conditional_operation: Option<ConditionalOperation>,
90}
91
92impl Default for InstructionData {
93    fn default() -> Self {
94        Self {
95            opcode: 0,
96            compact: false,
97            parallel: false,
98            p_bit: false,
99            conditional_operation: None,
100        }
101    }
102}
103
104#[derive(PartialEq, Eq, Clone, Copy)]
105pub enum DataSize {
106    Byte,
107    ByteUnsigned,
108    HalfWord,
109    HalfWordUnsigned,
110    Word,
111    NonAlignedWord,
112    DoubleWord,
113    NonAlignedDoubleWord,
114}
115
116impl DataSize {
117    fn to_short_string(&self) -> String {
118        match self {
119            Self::Byte => String::from("B"),
120            Self::ByteUnsigned => String::from("BU"),
121            Self::HalfWord => String::from("H"),
122            Self::HalfWordUnsigned => String::from("HU"),
123            Self::Word => String::from("W"),
124            Self::NonAlignedWord => String::from("NW"),
125            Self::DoubleWord => String::from("DW"),
126            Self::NonAlignedDoubleWord => String::from("NDW"),
127        }
128    }
129}
130
131impl Display for DataSize {
132    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133        match self {
134            Self::Byte => write!(f, "Byte"),
135            Self::ByteUnsigned => write!(f, "ByteUnsigned"),
136            Self::HalfWord => write!(f, "HalfWord"),
137            Self::HalfWordUnsigned => write!(f, "HalfWordUnsigned"),
138            Self::Word => write!(f, "Word"),
139            Self::NonAlignedWord => write!(f, "NonAlignedWord"),
140            Self::DoubleWord => write!(f, "DoubleWord"),
141            Self::NonAlignedDoubleWord => write!(f, "NonAlignedDoubleWord"),
142        }
143    }
144}
145
146#[derive(PartialEq, Eq, Clone, Copy)]
147pub enum Unit {
148    L,
149    S,
150    M,
151    D,
152}
153
154impl Unit {
155    pub fn to_sided_string(&self, side: bool) -> String {
156        let mut value = self.to_string();
157        if side == false {
158            value += "1";
159        } else {
160            value += "2";
161        }
162        value
163    }
164}
165
166impl Display for Unit {
167    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168        match self {
169            Self::L => write!(f, "L"),
170            Self::S => write!(f, "S"),
171            Self::M => write!(f, "M"),
172            Self::D => write!(f, "D"),
173        }
174    }
175}
176
177#[derive(PartialEq, Eq, Clone, Copy)]
178pub enum ConditionalOperation {
179    ReservedLow,
180    ReservedHigh,
181    Zero(Register),
182    NonZero(Register),
183}
184
185impl ConditionalOperation {
186    pub fn from(creg: u8, z: bool) -> Option<Self> {
187        if creg == 0 && z == true {
188            return Some(ConditionalOperation::ReservedLow);
189        } else if creg == 0b111 {
190            return Some(ConditionalOperation::ReservedHigh);
191        }
192        let register_option = {
193            if creg & 0b100 == 0b100 {
194                match creg & 0b11 {
195                    0b00 => Some(Register::A(1)),
196                    0b01 => Some(Register::A(2)),
197                    0b10 => Some(Register::A(0)),
198                    _ => None,
199                }
200            } else {
201                match creg & 0b11 {
202                    0b01 => Some(Register::B(0)),
203                    0b10 => Some(Register::B(1)),
204                    0b11 => Some(Register::B(2)),
205                    _ => None,
206                }
207            }
208        };
209
210        if let Some(register) = register_option {
211            if z {
212                Some(ConditionalOperation::Zero(register))
213            } else {
214                Some(ConditionalOperation::NonZero(register))
215            }
216        } else {
217            None
218        }
219    }
220}
221
222impl Display for ConditionalOperation {
223    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
224        match self {
225            ConditionalOperation::NonZero(register) => write!(f, "{register}"),
226            ConditionalOperation::Zero(register) => write!(f, "!{register}"),
227            ConditionalOperation::ReservedLow | ConditionalOperation::ReservedHigh => write!(f, ""),
228        }
229    }
230}