1use core::convert::From;
4use core::{cmp, fmt, slice};
5use core::ffi::c_int;
6
7use capstone_sys::{
8 cs_tms320c64x, cs_tms320c64x_op, tms320c64x_funit, tms320c64x_mem_dir, tms320c64x_mem_disp,
9 tms320c64x_mem_mod, tms320c64x_op_mem, tms320c64x_op_type,
10};
11
12pub use capstone_sys::tms320c64x_insn as Tms320c64xInsn;
14pub use capstone_sys::tms320c64x_insn_group as Tms320c64xInsnGroup;
15pub use capstone_sys::tms320c64x_reg as Tms320c64xReg;
16
17pub use crate::arch::arch_builder::tms320c64x::*;
18use crate::instruction::{RegId, RegIdInt};
19
20
21pub struct Tms320c64xInsnDetail<'a>(pub(crate) &'a cs_tms320c64x);
23
24define_cs_enum_wrapper_reverse!(
25 [
26 => Tms320c64xFuntionalUnit = tms320c64x_funit,
28 ]
29 => Invalid = TMS320C64X_FUNIT_INVALID;
31 => D = TMS320C64X_FUNIT_D;
33 => L = TMS320C64X_FUNIT_L;
35 => M = TMS320C64X_FUNIT_M;
37 => S = TMS320C64X_FUNIT_S;
39 => No = TMS320C64X_FUNIT_NO;
41);
42
43impl Tms320c64xInsnDetail<'_> {
44 pub fn is_condition_zero(&self) -> bool {
46 self.0.condition.zero != 0
47 }
48
49 pub fn condition_reg(&self) -> RegId {
51 RegId(self.0.condition.reg as RegIdInt)
52 }
53
54 pub fn functional_unit(&self) -> Tms320c64xFuntionalUnit {
56 Tms320c64xFuntionalUnit::from_u32(self.0.funit.unit)
57 .unwrap_or(Tms320c64xFuntionalUnit::Invalid)
58 }
59
60 pub fn functional_unit_side(&self) -> u8 {
62 self.0.funit.side as u8
63 }
64
65 pub fn functional_unit_cross_path(&self) -> i8 {
67 self.0.funit.crosspath as i8
70 }
71
72 pub fn parallel(&self) -> i8 {
74 self.0.parallel as c_int as i8
75 }
76}
77
78impl_PartialEq_repr_fields!(Tms320c64xInsnDetail<'a> [ 'a ];
79 is_condition_zero, condition_reg, functional_unit, functional_unit_side,
80 functional_unit_cross_path, parallel
81);
82
83#[derive(Clone, Debug, Eq, PartialEq)]
85pub enum Tms320c64xOperand {
86 Reg(RegId),
88
89 Imm(i32),
91
92 Mem(Tms320c64xOpMem),
94
95 RegPair(RegId, RegId),
97
98 Invalid,
100}
101
102impl Default for Tms320c64xOperand {
103 fn default() -> Self {
104 Tms320c64xOperand::Invalid
105 }
106}
107
108define_cs_enum_wrapper_reverse!(
109 [
110 => Tms320c64xMemDisplayType = tms320c64x_mem_disp,
112 ]
113 => Invalid = TMS320C64X_MEM_DISP_INVALID;
115 => Constant = TMS320C64X_MEM_DISP_CONSTANT;
117 => Register = TMS320C64X_MEM_DISP_REGISTER;
119);
120
121#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
123pub enum Tms320c64xMemDisplay {
124 Invalid,
126
127 Constant(u32),
129
130 Register(RegId),
132}
133
134define_cs_enum_wrapper_reverse!(
135 [
136 => Tms320c64xMemDirection = tms320c64x_mem_dir,
138 ]
139 => Invalid = TMS320C64X_MEM_DIR_INVALID;
141 => Forward = TMS320C64X_MEM_DIR_FW;
143 => Backward = TMS320C64X_MEM_DIR_BW;
145);
146
147define_cs_enum_wrapper_reverse!(
148 [
149 => Tms320c64xMemModify = tms320c64x_mem_mod,
151 ]
152 => Invalid = TMS320C64X_MEM_MOD_INVALID;
154 => No = TMS320C64X_MEM_MOD_NO;
156 => Pre = TMS320C64X_MEM_MOD_PRE;
158 => Post = TMS320C64X_MEM_MOD_POST;
160);
161
162#[derive(Debug, Copy, Clone)]
164pub struct Tms320c64xOpMem(pub(crate) tms320c64x_op_mem);
165
166impl Tms320c64xOpMem {
168 pub fn base(&self) -> RegId {
170 RegId(self.0.base as RegIdInt)
171 }
172
173 fn disp(&self) -> u32 {
175 self.0.disp as u32
176 }
177
178 pub fn unit(&self) -> u32 {
180 self.0.unit as u32
181 }
182
183 pub fn scaled(&self) -> u32 {
185 self.0.scaled as u32
186 }
187
188 fn display_type(&self) -> Tms320c64xMemDisplayType {
190 Tms320c64xMemDisplayType::from_u32(self.0.disptype as u32)
191 .unwrap_or(Tms320c64xMemDisplayType::Invalid)
192 }
193
194 pub fn display(&self) -> Tms320c64xMemDisplay {
196 match self.display_type() {
197 Tms320c64xMemDisplayType::Invalid => Tms320c64xMemDisplay::Invalid,
198 Tms320c64xMemDisplayType::Constant => Tms320c64xMemDisplay::Constant(self.disp()),
199 Tms320c64xMemDisplayType::Register => {
200 Tms320c64xMemDisplay::Register(RegId(self.disp() as RegIdInt))
201 }
202 }
203 }
204
205 pub fn direction(&self) -> Tms320c64xMemDirection {
207 Tms320c64xMemDirection::from_u32(self.0.direction as u32)
208 .unwrap_or(Tms320c64xMemDirection::Invalid)
209 }
210
211 pub fn modify(&self) -> Tms320c64xMemModify {
213 Tms320c64xMemModify::from_u32(self.0.modify as u32).unwrap_or(Tms320c64xMemModify::Invalid)
214 }
215}
216
217impl_PartialEq_repr_fields!(Tms320c64xOpMem;
218 base, disp, unit, scaled, display_type, direction, modify
219);
220
221impl cmp::Eq for Tms320c64xOpMem {}
222
223impl From<&cs_tms320c64x_op> for Tms320c64xOperand {
224 fn from(insn: &cs_tms320c64x_op) -> Tms320c64xOperand {
225 match insn.type_ {
226 tms320c64x_op_type::TMS320C64X_OP_REG => {
227 Tms320c64xOperand::Reg(RegId(unsafe { insn.__bindgen_anon_1.reg } as RegIdInt))
228 }
229 tms320c64x_op_type::TMS320C64X_OP_IMM => {
230 Tms320c64xOperand::Imm(unsafe { insn.__bindgen_anon_1.imm } as i32)
231 }
232 tms320c64x_op_type::TMS320C64X_OP_MEM => {
233 Tms320c64xOperand::Mem(Tms320c64xOpMem(unsafe { insn.__bindgen_anon_1.mem }))
234 }
235 tms320c64x_op_type::TMS320C64X_OP_REGPAIR => {
236 let reg = unsafe { insn.__bindgen_anon_1.reg };
237 Tms320c64xOperand::RegPair(RegId((reg as RegIdInt) + 1), RegId(reg as RegIdInt))
239 }
240 tms320c64x_op_type::TMS320C64X_OP_INVALID => Tms320c64xOperand::Invalid,
241 }
242 }
243}
244
245def_arch_details_struct!(
246 InsnDetail = Tms320c64xInsnDetail;
247 Operand = Tms320c64xOperand;
248 OperandIterator = Tms320c64xOperandIterator;
249 OperandIteratorLife = Tms320c64xOperandIterator<'a>;
250 [ pub struct Tms320c64xOperandIterator<'a>(slice::Iter<'a, cs_tms320c64x_op>); ]
251 cs_arch_op = cs_tms320c64x_op;
252 cs_arch = cs_tms320c64x;
253);
254
255#[cfg(test)]
256mod test {
257 use super::*;
258 use capstone_sys::*;
259 use core::ffi::{c_int, c_uint};
260
261 const OP_MEM_ZERO: tms320c64x_op_mem = tms320c64x_op_mem {
262 base: 0,
263 disp: 0,
264 unit: 0,
265 scaled: 0,
266 disptype: 0,
267 direction: 0,
268 modify: 0,
269 };
270
271 #[test]
272 fn tms320c64x_insn_detail() {
273 let op = cs_tms320c64x_op {
274 type_: tms320c64x_op_type::TMS320C64X_OP_IMM,
275 __bindgen_anon_1: cs_tms320c64x_op__bindgen_ty_1 { imm: 0 },
276 };
277 let cs_insn = cs_tms320c64x {
278 op_count: 0,
279 operands: [op; 8],
280 condition: cs_tms320c64x__bindgen_ty_1 {
281 reg: tms320c64x_reg::TMS320C64X_REG_GPLYA as c_uint,
282 zero: 1,
283 },
284 funit: cs_tms320c64x__bindgen_ty_2 {
285 unit: tms320c64x_funit::TMS320C64X_FUNIT_L as c_uint,
286 side: 18,
287 crosspath: -1 as c_int as c_uint,
288 },
289 parallel: 1,
290 };
291 let d = Tms320c64xInsnDetail(&cs_insn);
292
293 assert!(d.is_condition_zero());
294 assert_eq!(
295 d.condition_reg(),
296 RegId(Tms320c64xReg::TMS320C64X_REG_GPLYA as RegIdInt)
297 );
298 assert_eq!(d.functional_unit(), Tms320c64xFuntionalUnit::L);
299 assert_eq!(d.functional_unit_side(), 18);
300 assert_eq!(d.functional_unit_cross_path(), -1);
301 assert_eq!(d.parallel(), 1);
302 }
303
304 #[test]
305 fn tms320c64x_op_from() {
306 let op = cs_tms320c64x_op {
307 type_: tms320c64x_op_type::TMS320C64X_OP_INVALID,
308 __bindgen_anon_1: cs_tms320c64x_op__bindgen_ty_1 { reg: 0 },
309 };
310 assert_eq!(
311 Tms320c64xOperand::from(&op),
312 Tms320c64xOperand::Invalid
313 );
314 }
315
316 #[test]
317 fn op_mem() {
318 assert_eq!(
320 Tms320c64xOpMem(OP_MEM_ZERO).display(),
321 Tms320c64xMemDisplay::Invalid
322 );
323 assert_eq!(
324 Tms320c64xOpMem(tms320c64x_op_mem {
325 disptype: 999,
326 ..OP_MEM_ZERO
327 })
328 .display(),
329 Tms320c64xMemDisplay::Invalid
330 );
331 assert_eq!(
332 Tms320c64xOpMem(tms320c64x_op_mem {
333 disptype: tms320c64x_mem_disp::TMS320C64X_MEM_DISP_CONSTANT as c_uint,
334 disp: 3133789374,
335 ..OP_MEM_ZERO
336 })
337 .display(),
338 Tms320c64xMemDisplay::Constant(3133789374)
339 );
340 assert_eq!(
341 Tms320c64xOpMem(tms320c64x_op_mem {
342 disptype: tms320c64x_mem_disp::TMS320C64X_MEM_DISP_REGISTER as c_uint,
343 disp: tms320c64x_reg::TMS320C64X_REG_A13 as c_uint,
344 ..OP_MEM_ZERO
345 })
346 .display(),
347 Tms320c64xMemDisplay::Register(RegId(Tms320c64xReg::TMS320C64X_REG_A13 as RegIdInt))
348 );
349
350 assert_eq!(
352 Tms320c64xOpMem(tms320c64x_op_mem {
353 base: tms320c64x_reg::TMS320C64X_REG_A13 as c_uint,
354 ..OP_MEM_ZERO
355 })
356 .base(),
357 RegId(Tms320c64xReg::TMS320C64X_REG_A13 as RegIdInt)
358 );
359 assert_eq!(
360 Tms320c64xOpMem(tms320c64x_op_mem {
361 unit: 29393 as c_uint,
362 ..OP_MEM_ZERO
363 })
364 .unit(),
365 29393
366 );
367 assert_eq!(
368 Tms320c64xOpMem(tms320c64x_op_mem {
369 scaled: 29393 as c_uint,
370 ..OP_MEM_ZERO
371 })
372 .scaled(),
373 29393
374 );
375 assert_eq!(
376 Tms320c64xOpMem(tms320c64x_op_mem {
377 direction: tms320c64x_mem_dir::TMS320C64X_MEM_DIR_FW as c_uint,
378 ..OP_MEM_ZERO
379 })
380 .direction(),
381 Tms320c64xMemDirection::Forward,
382 );
383 assert_eq!(
384 Tms320c64xOpMem(tms320c64x_op_mem {
385 modify: tms320c64x_mem_mod::TMS320C64X_MEM_MOD_PRE as c_uint,
386 ..OP_MEM_ZERO
387 })
388 .modify(),
389 Tms320c64xMemModify::Pre,
390 );
391 }
392}