Skip to content

Commit b2cb063

Browse files
committed
rs: add ARC arch support
1 parent 73148cc commit b2cb063

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
@@ -498,6 +498,7 @@ impl InsnDetail<'_> {
498498
def_arch_detail_match!(
499499
[AARCH64, AArch64Detail, AArch64InsnDetail, aarch64, "arch_aarch64"]
500500
[ALPHA, AlphaDetail, AlphaInsnDetail, alpha, "arch_alpha"]
501+
[ARC, ArcDetail, ArcInsnDetail, arc, "arch_arc"]
501502
[ARM, ArmDetail, ArmInsnDetail, arm, "arch_arm"]
502503
[BPF, BpfDetail, BpfInsnDetail, bpf, "arch_bpf"]
503504
[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
@@ -938,6 +938,82 @@ fn test_capstone_is_diet() {
938938
println!("Capstone is diet: {}", Capstone::is_diet());
939939
}
940940

941+
#[cfg(feature = "arch_arc")]
942+
#[test]
943+
fn test_arch_arc() {
944+
test_arch_mode_endian_insns(
945+
&mut Capstone::new()
946+
.arc()
947+
.mode(arc::ArchMode::Default)
948+
.build()
949+
.unwrap(),
950+
Arch::ARC,
951+
Mode::Default,
952+
None,
953+
&[],
954+
&[("ld", b"\x04\x11\x00\x00"), ("ld.aw", b"\x04\x11\x00\x02")],
955+
);
956+
}
957+
958+
#[cfg(feature = "arch_arc")]
959+
#[test]
960+
fn test_arch_arc_detail() {
961+
use crate::arch::arc::ArcOperand;
962+
use capstone_sys::arc_reg::*;
963+
964+
test_arch_mode_endian_insns_detail(
965+
&mut Capstone::new()
966+
.arc()
967+
.mode(arc::ArchMode::Default)
968+
.build()
969+
.unwrap(),
970+
Arch::ARC,
971+
Mode::Default,
972+
None,
973+
&[],
974+
&[
975+
// ld %r0, [%r1, 4]
976+
DII::new(
977+
"ld",
978+
b"\x04\x11\x00\x00",
979+
&[
980+
ArcOperand {
981+
op_type: arc::ArcOperandType::Reg(RegId(ARC_REG_R0 as RegIdInt)),
982+
access: Some(RegAccessType::WriteOnly),
983+
},
984+
ArcOperand {
985+
op_type: arc::ArcOperandType::Reg(RegId(ARC_REG_R1 as RegIdInt)),
986+
access: Some(RegAccessType::ReadOnly),
987+
},
988+
ArcOperand {
989+
op_type: arc::ArcOperandType::Imm(4),
990+
access: Some(RegAccessType::ReadOnly),
991+
},
992+
],
993+
),
994+
// ld.aw %r0, [%r1, 4]
995+
DII::new(
996+
"ld.aw",
997+
b"\x04\x11\x00\x02",
998+
&[
999+
ArcOperand {
1000+
op_type: arc::ArcOperandType::Reg(RegId(ARC_REG_R0 as RegIdInt)),
1001+
access: Some(RegAccessType::WriteOnly),
1002+
},
1003+
ArcOperand {
1004+
op_type: arc::ArcOperandType::Reg(RegId(ARC_REG_R1 as RegIdInt)),
1005+
access: Some(RegAccessType::ReadOnly),
1006+
},
1007+
ArcOperand {
1008+
op_type: arc::ArcOperandType::Imm(4),
1009+
access: Some(RegAccessType::ReadOnly),
1010+
},
1011+
],
1012+
),
1013+
],
1014+
);
1015+
}
1016+
9411017
#[cfg(feature = "arch_arm")]
9421018
#[test]
9431019
fn test_arch_arm() {

0 commit comments

Comments
 (0)