1use std::fmt;
2
3use crate::address::Address;
4use crate::disassembly::VarnodeData;
5use crate::register::RegisterNames;
6use crate::space::AddressSpaceId;
7use crate::space_manager::SpaceManager;
8use crate::translator::Translator;
9
10use fugue_bv::BitVec;
11use ustr::Ustr;
12
13use super::Register;
14
15#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
16#[derive(serde::Deserialize, serde::Serialize)]
17pub enum Operand {
18 Address {
20 value: Address,
21 size: usize,
22 },
23 Constant {
24 value: u64,
25 size: usize,
26 },
27 Register {
28 name: Ustr,
29 offset: u64,
30 size: usize,
31 },
32 Variable {
33 offset: u64,
34 size: usize,
35 space: AddressSpaceId,
36 },
37}
38
39impl<'z> Operand {
40 pub fn from_varnode(translator: &Translator, varnode: VarnodeData) -> Operand {
41 Self::from_varnodedata(translator.manager(), translator.registers(), varnode)
42 }
43
44 #[inline(always)]
45 pub(crate) fn from_varnodedata(
46 manager: &SpaceManager,
47 registers: &RegisterNames,
48 vnd: VarnodeData,
49 ) -> Operand {
50 let offset = vnd.offset;
51 let size = vnd.size;
52 let space_id = vnd.space;
53
54 if cfg!(feature = "extra-logging") {
55 log::trace!("building operand from {vnd:?}");
56 }
57
58 if space_id.is_default() {
59 Operand::Address {
61 value: Address::new(manager.default_space_ref(), offset),
62 size,
63 }
64 } else if space_id.is_constant() {
65 Operand::Constant {
67 value: offset,
68 size,
69 }
70 } else if space_id.is_register() {
71 let name = unsafe { registers.unchecked_get(offset, size) }.clone();
73
74 Operand::Register {
75 name,
76 offset,
77 size,
78 }
79 } else {
80 Operand::Variable {
82 offset,
83 size,
84 space: space_id,
85 }
86 }
87 }
88
89 pub fn address(&self) -> Option<Address> {
90 if let Self::Address { value, .. } = self {
91 Some(*value)
92 } else {
93 None
94 }
95 }
96
97 pub fn as_bitvec(&self) -> Option<BitVec> {
98 if let Self::Constant { value, size, .. } = self {
99 Some(BitVec::from_u64(*value, size * 8))
100 } else {
101 None
102 }
103 }
104
105 pub fn register(&self) -> Option<Register> {
106 if let Self::Register {
107 name,
108 offset,
109 size,
110 } = self
111 {
112 Some(Register {
113 name: name.clone(),
114 offset: *offset,
115 size: *size,
116 })
117 } else {
118 None
119 }
120 }
121
122 pub fn offset(&self) -> u64 {
123 match self {
124 Operand::Address { value, .. } => value.offset(),
125 Operand::Constant { value, .. } => *value,
126 Operand::Register { offset, .. } | Operand::Variable { offset, .. } => *offset,
127 }
128 }
129
130 pub fn size(&self) -> usize {
131 match self {
132 Operand::Address { size, .. }
133 | Operand::Constant { size, .. }
134 | Operand::Register { size, .. }
135 | Operand::Variable { size, .. } => *size,
136 }
137 }
138
139 pub fn display(&self) -> OperandFormatter {
140 OperandFormatter::new(self)
141 }
142}
143
144impl<'z> fmt::Display for Operand {
145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146 write!(f, "{}", self.display())
147 }
148}
149
150impl<'z> AsRef<Operand> for Operand {
151 fn as_ref(&self) -> &Operand {
152 self
153 }
154}
155
156#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
157pub enum OperandCase {
158 Default,
159 Lower,
160 Upper,
161}
162
163#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
164pub enum OperandSize {
165 Default,
166 AsBits,
167 AsBytes,
168}
169
170impl Default for OperandSize {
171 fn default() -> Self {
172 Self::Default
173 }
174}
175
176pub struct OperandFormatter<'operand> {
177 operand: &'operand Operand,
178 signed: bool,
179 sizes: OperandSize,
180 case: OperandCase,
181}
182
183impl Default for OperandCase {
184 fn default() -> Self {
185 Self::Default
186 }
187}
188
189impl<'operand> OperandFormatter<'operand> {
190 pub fn new(operand: &'operand Operand) -> Self {
191 Self {
192 operand,
193 signed: false,
194 sizes: OperandSize::default(),
195 case: OperandCase::default(),
196 }
197 }
198
199 pub fn signed(self, signed: bool) -> Self {
200 Self { signed, ..self }
201 }
202
203 pub fn case(self, case: OperandCase) -> Self {
204 Self { case, ..self }
205 }
206
207 pub fn sizes(self, sizes: OperandSize) -> Self {
208 Self { sizes, ..self }
209 }
210}
211
212impl<'operand> fmt::Debug for OperandFormatter<'operand> {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 write!(f, "{:?}", self.operand)
215 }
216}
217
218impl<'operand> fmt::Display for OperandFormatter<'operand> {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 match self.operand {
221 Operand::Address { value, .. } => write!(f, "{}", value)?,
222 Operand::Constant { value, size, .. } => {
223 if !self.signed {
224 match size {
225 1 => write!(f, "{:#x}", *value as u8)?,
226 2 => write!(f, "{:#x}", *value as u16)?,
227 4 => write!(f, "{:#x}", *value as u32)?,
228 _ => write!(f, "{:#x}", value)?,
229 }
230 } else {
231 match size {
232 1 => {
233 let i = *value as u8 as i8;
234 write!(f, "{}{:#x}", if i < 0 { "-" } else { "" }, i.abs())?
235 }
236 2 => {
237 let i = *value as u16 as i16;
238 write!(f, "{}{:#x}", if i < 0 { "-" } else { "" }, i.abs())?
239 }
240 4 => {
241 let i = *value as u32 as i32;
242 write!(f, "{}{:#x}", if i < 0 { "-" } else { "" }, i.abs())?
243 }
244 _ => {
245 let i = *value as u64 as i64;
246 write!(f, "{}{:#x}", if i < 0 { "-" } else { "" }, i.abs())?
247 }
248 }
249 }
250 }
251 Operand::Register { name, .. } => match self.case {
252 OperandCase::Default => write!(f, "{}", name)?,
253 OperandCase::Lower => write!(f, "{}", name.to_lowercase())?,
254 OperandCase::Upper => write!(f, "{}", name.to_uppercase())?,
255 },
256 Operand::Variable { offset, .. } => write!(
257 f,
258 "{}{:04x}",
259 if matches!(self.case, OperandCase::Upper) {
260 "VAR"
261 } else {
262 "var"
263 },
264 offset
265 )?,
266 }
267 match self.sizes {
268 OperandSize::Default => (),
269 OperandSize::AsBits => write!(f, ":{}", self.operand.size() * 8)?,
270 OperandSize::AsBytes => write!(f, ":{}", self.operand.size())?,
271 }
272 Ok(())
273 }
274}