Skip to content

Commit e3ca3d4

Browse files
committed
rs: add ARC arch support
1 parent 4df3796 commit e3ca3d4

File tree

6 files changed

+180
-0
lines changed

6 files changed

+180
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
- HPPA arch support
1515
- LoongArch arch support
1616
- Xtensa arch support
17+
- ARC arch support
1718
- Arch-specific features flags to enable/disable arch support
1819
- Expose X86 instruction encoding info via `X86InsnDetail::encoding()`
1920
- Make RegAccessType available for ARM64

capstone-rs/src/arch/arc.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//! Contains arc-specific types
2+
3+
use core::convert::{From, TryInto};
4+
use core::{cmp, fmt, slice};
5+
6+
pub use capstone_sys::arc_insn as ArcInsn;
7+
pub use capstone_sys::arc_reg as ArcReg;
8+
use capstone_sys::{arc_op_type, cs_arc, cs_arc_op, cs_arc_op__bindgen_ty_1};
9+
10+
pub use crate::arch::arch_builder::arc::*;
11+
use crate::arch::DetailsArchInsn;
12+
use crate::instruction::{RegId, RegIdInt};
13+
use crate::RegAccessType;
14+
15+
/// Contains arc-specific details for an instruction
16+
pub struct ArcInsnDetail<'a>(pub(crate) &'a cs_arc);
17+
18+
impl_PartialEq_repr_fields!(ArcInsnDetail<'a> [ 'a ];
19+
operands
20+
);
21+
22+
/// arc operand
23+
#[derive(Clone, Debug, Eq, PartialEq, Default)]
24+
pub struct ArcOperand {
25+
/// Operand type
26+
pub op_type: ArcOperandType,
27+
28+
/// How is this operand accessed?
29+
///
30+
/// NOTE: this field is always `None` if the "full" feataure is not enabled.
31+
pub access: Option<RegAccessType>,
32+
}
33+
34+
impl From<&cs_arc_op> for ArcOperand {
35+
fn from(op: &cs_arc_op) -> ArcOperand {
36+
let op_type = ArcOperandType::new(op.type_, op.__bindgen_anon_1);
37+
ArcOperand {
38+
op_type,
39+
access: op.access.try_into().ok(),
40+
}
41+
}
42+
}
43+
44+
/// Arc operand
45+
#[derive(Clone, Debug, PartialEq)]
46+
pub enum ArcOperandType {
47+
/// Register
48+
Reg(RegId),
49+
50+
/// Immediate
51+
Imm(i64),
52+
53+
/// Invalid
54+
Invalid,
55+
}
56+
57+
impl ArcOperandType {
58+
fn new(op_type: arc_op_type, value: cs_arc_op__bindgen_ty_1) -> ArcOperandType {
59+
match op_type {
60+
arc_op_type::ARC_OP_REG => ArcOperandType::Reg(RegId(unsafe { value.reg } as RegIdInt)),
61+
arc_op_type::ARC_OP_IMM => ArcOperandType::Imm(unsafe { value.imm }),
62+
arc_op_type::ARC_OP_INVALID => ArcOperandType::Invalid,
63+
}
64+
}
65+
}
66+
67+
impl cmp::Eq for ArcOperandType {}
68+
69+
impl Default for ArcOperandType {
70+
fn default() -> Self {
71+
ArcOperandType::Invalid
72+
}
73+
}
74+
75+
def_arch_details_struct!(
76+
InsnDetail = ArcInsnDetail;
77+
Operand = ArcOperand;
78+
OperandIterator = ArcOperandIterator;
79+
OperandIteratorLife = ArcOperandIterator<'a>;
80+
[ pub struct ArcOperandIterator<'a>(slice::Iter<'a, cs_arc_op>); ]
81+
cs_arch_op = cs_arc_op;
82+
cs_arch = cs_arc;
83+
);

capstone-rs/src/arch/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,15 @@ macro_rules! arch_info_base {
213213
( syntax: )
214214
( both_endian: true )
215215
]
216+
[
217+
( arc, ARC, "arch_arc" )
218+
( mode:
219+
Default,
220+
)
221+
( extra_modes: )
222+
( syntax: )
223+
( both_endian: true )
224+
]
216225
[
217226
( arm, ARM, "arch_arm" )
218227
( mode:
@@ -581,6 +590,14 @@ macro_rules! detail_arch_base {
581590
/// Returns the Alpha details, if any
582591
=> arch_name = alpha,
583592
]
593+
[
594+
detail = ArcDetail,
595+
insn_detail = ArcInsnDetail<'a>,
596+
op = ArcOperand,
597+
feature = "arch_arc",
598+
/// Returns the ARC details, if any
599+
=> arch_name = arc,
600+
]
584601
[
585602
detail = ArmDetail,
586603
insn_detail = ArmInsnDetail<'a>,

capstone-rs/src/constants.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ define_cs_enum_wrapper!(
198198
]
199199
/// ARM (Advanced RISC Machine)
200200
=> ARM = CS_ARCH_ARM;
201+
/// ARC
202+
=> ARC = CS_ARCH_ARC;
201203
/// ARM 64-bit (also known as AArch64)
202204
=> AARCH64 = CS_ARCH_AARCH64;
203205
/// Alpha

capstone-rs/src/instruction.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ impl InsnDetail<'_> {
494494
def_arch_detail_match!(
495495
[AARCH64, AArch64Detail, AArch64InsnDetail, aarch64, "arch_aarch64"]
496496
[ALPHA, AlphaDetail, AlphaInsnDetail, alpha, "arch_alpha"]
497+
[ARC, ArcDetail, ArcInsnDetail, arc, "arch_arc"]
497498
[ARM, ArmDetail, ArmInsnDetail, arm, "arch_arm"]
498499
[BPF, BpfDetail, BpfInsnDetail, bpf, "arch_bpf"]
499500
[EVM, EvmDetail, EvmInsnDetail, evm, "arch_evm"]

capstone-rs/src/test.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,82 @@ fn test_capstone_is_diet() {
845845
println!("Capstone is diet: {}", Capstone::is_diet());
846846
}
847847

848+
#[cfg(feature = "arch_arc")]
849+
#[test]
850+
fn test_arch_arc() {
851+
test_arch_mode_endian_insns(
852+
&mut Capstone::new()
853+
.arc()
854+
.mode(arc::ArchMode::Default)
855+
.build()
856+
.unwrap(),
857+
Arch::ARC,
858+
Mode::Default,
859+
None,
860+
&[],
861+
&[("ld", b"\x04\x11\x00\x00"), ("ld.aw", b"\x04\x11\x00\x02")],
862+
);
863+
}
864+
865+
#[cfg(feature = "arch_arc")]
866+
#[test]
867+
fn test_arch_arc_detail() {
868+
use crate::arch::arc::ArcOperand;
869+
use capstone_sys::arc_reg::*;
870+
871+
test_arch_mode_endian_insns_detail(
872+
&mut Capstone::new()
873+
.arc()
874+
.mode(arc::ArchMode::Default)
875+
.build()
876+
.unwrap(),
877+
Arch::ARC,
878+
Mode::Default,
879+
None,
880+
&[],
881+
&[
882+
// ld %r0, [%r1, 4]
883+
DII::new(
884+
"ld",
885+
b"\x04\x11\x00\x00",
886+
&[
887+
ArcOperand {
888+
op_type: arc::ArcOperandType::Reg(RegId(ARC_REG_R0 as RegIdInt)),
889+
access: Some(RegAccessType::WriteOnly),
890+
},
891+
ArcOperand {
892+
op_type: arc::ArcOperandType::Reg(RegId(ARC_REG_R1 as RegIdInt)),
893+
access: Some(RegAccessType::ReadOnly),
894+
},
895+
ArcOperand {
896+
op_type: arc::ArcOperandType::Imm(4),
897+
access: Some(RegAccessType::ReadOnly),
898+
},
899+
],
900+
),
901+
// ld.aw %r0, [%r1, 4]
902+
DII::new(
903+
"ld.aw",
904+
b"\x04\x11\x00\x02",
905+
&[
906+
ArcOperand {
907+
op_type: arc::ArcOperandType::Reg(RegId(ARC_REG_R0 as RegIdInt)),
908+
access: Some(RegAccessType::WriteOnly),
909+
},
910+
ArcOperand {
911+
op_type: arc::ArcOperandType::Reg(RegId(ARC_REG_R1 as RegIdInt)),
912+
access: Some(RegAccessType::ReadOnly),
913+
},
914+
ArcOperand {
915+
op_type: arc::ArcOperandType::Imm(4),
916+
access: Some(RegAccessType::ReadOnly),
917+
},
918+
],
919+
),
920+
],
921+
);
922+
}
923+
848924
#[cfg(feature = "arch_arm")]
849925
#[test]
850926
fn test_arch_arm() {

0 commit comments

Comments
 (0)