c6000_disassembler/instruction/
fphead.rs1use std::io::{Error, ErrorKind, Result};
2
3use crate::instruction::{
4 C6000Instruction, DataSize, InstructionData,
5 parser::{ParsedVariable, ParsingInstruction, parse},
6};
7
8#[derive(Clone)]
9pub struct CompactInstructionHeader {
10 instruction_data: InstructionData,
11 pub layout: [bool; 7],
15 pub loads_protected: bool,
18 pub register_set: bool,
22 pub primary_data_size: DataSize,
23 pub secondary_data_size: DataSize,
24 pub decode_compact_branches: bool,
28 pub saturate: bool,
35 pub compact_p_bits: [bool; 14],
36}
37
38impl C6000Instruction for CompactInstructionHeader {
39 fn new(input: &super::InstructionInput) -> Result<Self> {
40 let format = [
41 ParsingInstruction::BitArray {
42 size: 14,
43 name: String::from("p"),
44 },
45 ParsingInstruction::Bit {
46 name: String::from("SAT"),
47 },
48 ParsingInstruction::Bit {
49 name: String::from("BR"),
50 },
51 ParsingInstruction::Unsigned {
52 size: 2,
53 name: String::from("DSZ_1"),
54 },
55 ParsingInstruction::Bit {
56 name: String::from("DSZ_2"),
57 },
58 ParsingInstruction::Bit {
59 name: String::from("RS"),
60 },
61 ParsingInstruction::Bit {
62 name: String::from("PROT"),
63 },
64 ParsingInstruction::BitArray {
65 size: 7,
66 name: String::from("layout"),
67 },
68 ParsingInstruction::Match {
69 size: 4,
70 value: 0b1110,
71 },
72 ];
73 let parsed_variables = parse(input.opcode, &format).map_err(|e| {
74 Error::new(
75 ErrorKind::InvalidInput,
76 format!("Not a compact instruction header: {e}"),
77 )
78 })?;
79
80 let layout = {
81 let layout_vec =
82 ParsedVariable::try_get(&parsed_variables, "layout")?.get_bool_vec()?;
83 let Some(layout_ref) = layout_vec.first_chunk::<7>() else {
84 return Err(Error::other("Layout doesn't have 7 elements"));
85 };
86 *layout_ref
87 };
88 let compact_p_bits = {
89 let layout_vec = ParsedVariable::try_get(&parsed_variables, "p")?.get_bool_vec()?;
90 let Some(layout_ref) = layout_vec.first_chunk::<14>() else {
91 return Err(Error::other("P-bits don't have 14 elements"));
92 };
93 *layout_ref
94 };
95 let loads_protected = ParsedVariable::try_get(&parsed_variables, "PROT")?.get_bool()?;
96 let register_set = ParsedVariable::try_get(&parsed_variables, "RS")?.get_bool()?;
97 let data_sizes_1 = ParsedVariable::try_get(&parsed_variables, "DSZ_1")?.get_u8()?;
98 let data_sizes_2 = ParsedVariable::try_get(&parsed_variables, "DSZ_2")?.get_bool()?;
99 let primary_data_size = {
100 if data_sizes_2 == true {
101 DataSize::DoubleWord
102 } else {
103 DataSize::Word
104 }
105 };
106 let secondary_data_size = {
107 if primary_data_size == DataSize::DoubleWord {
108 match data_sizes_1 {
109 0 => DataSize::Word,
110 1 => DataSize::Byte,
111 2 => DataSize::NonAlignedWord,
112 3 => DataSize::HalfWord,
113 _ => DataSize::Word,
114 }
115 } else {
116 match data_sizes_1 {
117 0 => DataSize::ByteUnsigned,
118 1 => DataSize::Byte,
119 2 => DataSize::HalfWordUnsigned,
120 3 => DataSize::HalfWord,
121 _ => DataSize::ByteUnsigned,
122 }
123 }
124 };
125 let decode_compact_branches =
126 ParsedVariable::try_get(&parsed_variables, "BR")?.get_bool()?;
127 let saturate = ParsedVariable::try_get(&parsed_variables, "SAT")?.get_bool()?;
128 Ok(Self {
129 instruction_data: InstructionData {
130 opcode: input.opcode,
131 ..Default::default()
132 },
133 layout,
134 compact_p_bits,
135 loads_protected,
136 register_set,
137 primary_data_size,
138 secondary_data_size,
139 decode_compact_branches,
140 saturate,
141 })
142 }
143
144 fn instruction(&self) -> String {
145 String::from(".fphead")
146 }
147 fn operands(&self) -> String {
148 let mut return_str = String::new();
149 if self.loads_protected {
150 return_str += "p";
151 } else {
152 return_str += "n";
153 }
154 return_str += ", ";
155 if self.register_set {
156 return_str += "h";
157 } else {
158 return_str += "l";
159 }
160 return_str += ", ";
161 return_str += (self.primary_data_size.to_short_string() + ", ").as_str();
162 return_str += (self.secondary_data_size.to_short_string() + ", ").as_str();
163 if self.decode_compact_branches {
164 return_str += "br";
165 } else {
166 return_str += "nobr";
167 }
168 return_str += ", ";
169 if self.saturate {
170 return_str += "sat";
171 } else {
172 return_str += "nosat";
173 }
174 return_str += ", ";
175 for i in (0..7).rev() {
176 if self.layout[i] {
177 return_str += "1";
178 } else {
179 return_str += "0";
180 }
181 }
182 return_str
183 }
184 fn instruction_data(&self) -> &InstructionData {
185 &self.instruction_data
186 }
187 fn instruction_data_mut(&mut self) -> &mut InstructionData {
188 &mut self.instruction_data
189 }
190}