capstone_git/arch/
ppc.rs

1//! Contains ppc-specific types
2
3use core::convert::From;
4use core::{cmp, fmt, slice};
5
6// XXX todo(tmfink): create rusty versions
7pub use capstone_sys::ppc_insn_group as PpcInsnGroup;
8pub use capstone_sys::ppc_insn as PpcInsn;
9pub use capstone_sys::ppc_reg as PpcReg;
10pub use capstone_sys::ppc_bc as PpcBc;
11pub use capstone_sys::ppc_bh as PpcBh;
12use capstone_sys::{cs_ppc, cs_ppc_op, ppc_op_mem, ppc_op_crx, ppc_op_type};
13
14pub use crate::arch::arch_builder::ppc::*;
15use crate::arch::DetailsArchInsn;
16use crate::instruction::{RegId, RegIdInt};
17
18/// Contains PPC-specific details for an instruction
19pub struct PpcInsnDetail<'a>(pub(crate) &'a cs_ppc);
20
21impl PpcInsnDetail<'_> {
22    /// Branch code for branch instructions
23    pub fn bc(&self) -> PpcBc {
24        self.0.bc
25    }
26
27    /// Branch hint for branch instructions
28    pub fn bh(&self) -> PpcBh {
29        self.0.bh
30    }
31
32    /// Whether this 'dot' insn updates CR0
33    pub fn update_cr0(&self) -> PpcBh {
34        self.0.bh
35    }
36}
37
38impl_PartialEq_repr_fields!(PpcInsnDetail<'a> [ 'a ];
39    bc, bh, update_cr0, operands
40);
41
42/// PPC operand
43#[derive(Clone, Debug, Eq, PartialEq)]
44pub enum PpcOperand {
45    /// Register
46    Reg(RegId),
47
48    /// Immediate
49    Imm(i64),
50
51    /// Memory
52    Mem(PpcOpMem),
53
54    /// Condition Register field
55    Crx(PpcOpCrx),
56
57    /// Invalid
58    Invalid,
59}
60
61impl Default for PpcOperand {
62    fn default() -> Self {
63        PpcOperand::Invalid
64    }
65}
66
67/// PPC memory operand
68#[derive(Debug, Copy, Clone)]
69pub struct PpcOpMem(pub(crate) ppc_op_mem);
70
71impl PpcOpMem {
72    /// Base register
73    pub fn base(&self) -> RegId {
74        RegId(self.0.base as RegIdInt)
75    }
76
77    /// Disp value
78    pub fn disp(&self) -> i32 {
79        self.0.disp
80    }
81}
82
83impl_PartialEq_repr_fields!(PpcOpMem;
84    base, disp
85);
86
87impl cmp::Eq for PpcOpMem {}
88
89/// PPC condition register field
90#[derive(Debug, Copy, Clone)]
91pub struct PpcOpCrx(pub(crate) ppc_op_crx);
92
93impl PpcOpCrx {
94    /// Scale
95    pub fn scale(&self) -> u32 {
96        self.0.scale as u32
97    }
98
99    /// Register value
100    pub fn reg(&self) -> RegId {
101        RegId(self.0.reg as RegIdInt)
102    }
103
104    /// Condition value
105    pub fn cond(&self) -> PpcBc {
106        self.0.cond
107    }
108}
109
110impl cmp::PartialEq for PpcOpCrx {
111    fn eq(&self, other: &Self) -> bool {
112        (self.scale(), self.reg(), self.cond()) == (other.scale(), other.reg(), other.cond())
113    }
114}
115
116impl cmp::Eq for PpcOpCrx {}
117
118impl From<&cs_ppc_op> for PpcOperand {
119    fn from(insn: &cs_ppc_op) -> PpcOperand {
120        match insn.type_ {
121            ppc_op_type::PPC_OP_REG => {
122                PpcOperand::Reg(RegId(unsafe { insn.__bindgen_anon_1.reg } as RegIdInt))
123            }
124            ppc_op_type::PPC_OP_IMM => PpcOperand::Imm(unsafe { insn.__bindgen_anon_1.imm }),
125            ppc_op_type::PPC_OP_MEM => {
126                PpcOperand::Mem(PpcOpMem(unsafe { insn.__bindgen_anon_1.mem }))
127            }
128            ppc_op_type::PPC_OP_CRX => {
129                PpcOperand::Crx(PpcOpCrx(unsafe { insn.__bindgen_anon_1.crx }))
130            }
131            ppc_op_type::PPC_OP_INVALID => PpcOperand::Invalid,
132        }
133    }
134}
135
136def_arch_details_struct!(
137    InsnDetail = PpcInsnDetail;
138    Operand = PpcOperand;
139    OperandIterator = PpcOperandIterator;
140    OperandIteratorLife = PpcOperandIterator<'a>;
141    [ pub struct PpcOperandIterator<'a>(slice::Iter<'a, cs_ppc_op>); ]
142    cs_arch_op = cs_ppc_op;
143    cs_arch = cs_ppc;
144);
145
146#[cfg(test)]
147mod test {
148    use super::*;
149
150    #[test]
151    fn test_ppc_op_type() {
152        use capstone_sys::*;
153        use super::ppc_op_type::*;
154        use super::PpcBc::*;
155        use super::PpcReg::*;
156        use self::PpcOperand::*;
157
158        fn t(
159            op: (ppc_op_type, cs_ppc_op__bindgen_ty_1),
160            expected_op: PpcOperand,
161        ) {
162            let op = PpcOperand::from(&cs_ppc_op {
163                type_: op.0,
164                __bindgen_anon_1: op.1
165            });
166            assert_eq!(expected_op, op);
167        }
168
169        t(
170            (PPC_OP_INVALID, cs_ppc_op__bindgen_ty_1 { reg: 0 }),
171            Invalid,
172        );
173        t(
174            (PPC_OP_REG, cs_ppc_op__bindgen_ty_1 { reg: 0 }),
175            Reg(RegId(0)),
176        );
177        t(
178            (PPC_OP_IMM, cs_ppc_op__bindgen_ty_1 { imm: 42 }),
179            Imm(42),
180        );
181
182        let crx = ppc_op_crx { scale: 0, reg: PPC_REG_R0, cond: PPC_BC_LT };
183        t(
184            (PPC_OP_CRX, cs_ppc_op__bindgen_ty_1 { crx }),
185            Crx(PpcOpCrx(crx)),
186        );
187
188        let op_mem = PpcOperand::from(&cs_ppc_op {
189            type_: PPC_OP_MEM,
190            __bindgen_anon_1: cs_ppc_op__bindgen_ty_1 { mem: ppc_op_mem {
191                base: PPC_REG_VS38,
192                disp: -10 }}
193        });
194        if let Mem(op_mem) = op_mem {
195            assert_eq!(
196                (op_mem.base(), op_mem.disp()),
197                (RegId(PPC_REG_VS38 as RegIdInt), -10)
198            );
199        } else {
200            panic!("Did not get expected Mem");
201        }
202    }
203}