use core::convert::From;
use core::{cmp, fmt, slice};
pub use capstone_sys::ppc_insn_group as PpcInsnGroup;
pub use capstone_sys::ppc_insn as PpcInsn;
pub use capstone_sys::ppc_reg as PpcReg;
pub use capstone_sys::ppc_bc as PpcBc;
pub use capstone_sys::ppc_bh as PpcBh;
use capstone_sys::{cs_ppc, cs_ppc_op, ppc_op_mem, ppc_op_crx, ppc_op_type};
pub use crate::arch::arch_builder::ppc::*;
use crate::arch::DetailsArchInsn;
use crate::instruction::{RegId, RegIdInt};
pub struct PpcInsnDetail<'a>(pub(crate) &'a cs_ppc);
impl<'a> PpcInsnDetail<'a> {
pub fn bc(&self) -> PpcBc {
self.0.bc
}
pub fn bh(&self) -> PpcBh {
self.0.bh
}
pub fn update_cr0(&self) -> PpcBh {
self.0.bh
}
}
impl_PartialEq_repr_fields!(PpcInsnDetail<'a> [ 'a ];
bc, bh, update_cr0, operands
);
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum PpcOperand {
Reg(RegId),
Imm(i64),
Mem(PpcOpMem),
Crx(PpcOpCrx),
Invalid,
}
impl Default for PpcOperand {
fn default() -> Self {
PpcOperand::Invalid
}
}
#[derive(Debug, Copy, Clone)]
pub struct PpcOpMem(pub(crate) ppc_op_mem);
impl PpcOpMem {
pub fn base(&self) -> RegId {
RegId(self.0.base as RegIdInt)
}
pub fn disp(&self) -> i32 {
self.0.disp
}
}
impl_PartialEq_repr_fields!(PpcOpMem;
base, disp
);
impl cmp::Eq for PpcOpMem {}
#[derive(Debug, Copy, Clone)]
pub struct PpcOpCrx(pub(crate) ppc_op_crx);
impl PpcOpCrx {
pub fn scale(&self) -> u32 {
self.0.scale as u32
}
pub fn reg(&self) -> RegId {
RegId(self.0.reg as RegIdInt)
}
pub fn cond(&self) -> PpcBc {
self.0.cond
}
}
impl cmp::PartialEq for PpcOpCrx {
fn eq(&self, other: &Self) -> bool {
(self.scale(), self.reg(), self.cond()) == (other.scale(), other.reg(), other.cond())
}
}
impl cmp::Eq for PpcOpCrx {}
impl<'a> From<&'a cs_ppc_op> for PpcOperand {
fn from(insn: &cs_ppc_op) -> PpcOperand {
match insn.type_ {
ppc_op_type::PPC_OP_REG => {
PpcOperand::Reg(RegId(unsafe { insn.__bindgen_anon_1.reg } as RegIdInt))
}
ppc_op_type::PPC_OP_IMM => PpcOperand::Imm(unsafe { insn.__bindgen_anon_1.imm }),
ppc_op_type::PPC_OP_MEM => {
PpcOperand::Mem(PpcOpMem(unsafe { insn.__bindgen_anon_1.mem }))
}
ppc_op_type::PPC_OP_CRX => {
PpcOperand::Crx(PpcOpCrx(unsafe { insn.__bindgen_anon_1.crx }))
}
ppc_op_type::PPC_OP_INVALID => PpcOperand::Invalid,
}
}
}
def_arch_details_struct!(
InsnDetail = PpcInsnDetail;
Operand = PpcOperand;
OperandIterator = PpcOperandIterator;
OperandIteratorLife = PpcOperandIterator<'a>;
[ pub struct PpcOperandIterator<'a>(slice::Iter<'a, cs_ppc_op>); ]
cs_arch_op = cs_ppc_op;
cs_arch = cs_ppc;
);
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_ppc_op_type() {
use capstone_sys::*;
use super::ppc_op_type::*;
use super::PpcBc::*;
use super::PpcReg::*;
use self::PpcOperand::*;
fn t(
op: (ppc_op_type, cs_ppc_op__bindgen_ty_1),
expected_op: PpcOperand,
) {
let op = PpcOperand::from(&cs_ppc_op {
type_: op.0,
__bindgen_anon_1: op.1
});
assert_eq!(expected_op, op);
}
t(
(PPC_OP_INVALID, cs_ppc_op__bindgen_ty_1 { reg: 0 }),
Invalid,
);
t(
(PPC_OP_REG, cs_ppc_op__bindgen_ty_1 { reg: 0 }),
Reg(RegId(0)),
);
t(
(PPC_OP_IMM, cs_ppc_op__bindgen_ty_1 { imm: 42 }),
Imm(42),
);
let crx = ppc_op_crx { scale: 0, reg: PPC_REG_R0, cond: PPC_BC_LT };
t(
(PPC_OP_CRX, cs_ppc_op__bindgen_ty_1 { crx }),
Crx(PpcOpCrx(crx)),
);
let op_mem = PpcOperand::from(&cs_ppc_op {
type_: PPC_OP_MEM,
__bindgen_anon_1: cs_ppc_op__bindgen_ty_1 { mem: ppc_op_mem {
base: PPC_REG_VS38,
disp: -10 }}
});
if let Mem(op_mem) = op_mem {
assert_eq!(
(op_mem.base(), op_mem.disp()),
(RegId(PPC_REG_VS38 as RegIdInt), -10)
);
} else {
panic!("Did not get expected Mem");
}
}
}