disasm_core/
insn.rs

1use core::ops::{Add, Deref};
2
3use alloc::{boxed::Box, vec::Vec};
4
5use crate::{
6    flags::Flags,
7    operand::{Operand, OperandKind, Reg},
8};
9
10pub const INSN_ALIAS: u32 = 1 << 0;
11
12#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
13pub struct Opcode(pub u32);
14
15impl Opcode {
16    pub const INVALID: Self = Self(0);
17}
18
19impl Add<u32> for Opcode {
20    type Output = Self;
21
22    fn add(self, rhs: u32) -> Self {
23        Self(self.0 + rhs)
24    }
25}
26
27#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
28pub struct Slot(u16);
29
30impl Default for Slot {
31    fn default() -> Self {
32        Self::NONE
33    }
34}
35
36impl Slot {
37    pub const NONE: Self = Self::new(0xffff);
38
39    pub const fn new(id: u16) -> Self {
40        Self(id)
41    }
42
43    pub const fn raw(&self) -> u16 {
44        self.0
45    }
46}
47
48#[derive(Clone, Default)]
49pub struct Insn {
50    opcode: Opcode,
51    flags: Flags,
52    operands: Vec<Operand>,
53    slot: Slot,
54}
55
56impl Insn {
57    pub fn clear(&mut self) {
58        self.opcode = Opcode::INVALID;
59        self.flags = Flags::empty();
60        self.operands.clear();
61        self.slot = Slot::NONE;
62    }
63
64    pub fn flags(&self) -> &Flags {
65        &self.flags
66    }
67
68    pub fn flags_mut(&mut self) -> &mut Flags {
69        &mut self.flags
70    }
71
72    pub fn is_alias(&self) -> bool {
73        self.flags.any(INSN_ALIAS)
74    }
75
76    pub fn set_alias(&mut self) {
77        self.flags.set(INSN_ALIAS);
78    }
79
80    pub fn slot(&self) -> Slot {
81        self.slot
82    }
83
84    pub fn set_slot(&mut self, slot: Slot) {
85        self.slot = slot;
86    }
87
88    pub fn opcode(&self) -> Opcode {
89        self.opcode
90    }
91
92    pub fn set_opcode(&mut self, opcode: Opcode) {
93        self.opcode = opcode;
94    }
95
96    pub fn operands(&self) -> &[Operand] {
97        self.operands.as_slice()
98    }
99
100    pub fn push_operand<T>(&mut self, operand: T)
101    where
102        T: Into<Operand>,
103    {
104        self.operands.push(operand.into());
105    }
106
107    pub fn push_operand_if_some<T>(&mut self, operand: Option<T>)
108    where
109        T: Into<Operand>,
110    {
111        if let Some(operand) = operand {
112            self.operands.push(operand.into());
113        }
114    }
115
116    pub fn push_reg(&mut self, reg: Reg) {
117        self.push_operand(OperandKind::Reg(reg));
118    }
119
120    pub fn push_offset(&mut self, reg: Reg, offset: i64) {
121        self.push_operand(OperandKind::Relative(reg, offset));
122    }
123
124    pub fn push_imm(&mut self, value: i64) {
125        self.push_operand(OperandKind::Imm(value));
126    }
127
128    pub fn push_uimm(&mut self, value: u64) {
129        self.push_operand(OperandKind::Uimm(value));
130    }
131
132    pub fn push_absolute(&mut self, addr: u64) {
133        self.push_operand(OperandKind::Absolute(addr));
134    }
135
136    pub fn push_indirect(&mut self, reg: Reg) {
137        self.push_operand(OperandKind::Indirect(reg));
138    }
139
140    pub fn push_pc_rel(&mut self, base: u64, offset: i64) {
141        self.push_operand(OperandKind::PcRelative(base, offset));
142    }
143
144    pub fn push_arch_spec(&mut self, a: u64, b: u64, c: u64) {
145        self.push_operand(OperandKind::ArchSpec(a, b, c));
146    }
147
148    pub fn push_arch_spec3(&mut self, a: impl Into<u64>, b: impl Into<u64>, c: impl Into<u64>) {
149        self.push_arch_spec(a.into(), b.into(), c.into());
150    }
151
152    pub fn push_arch_spec2(&mut self, a: impl Into<u64>, b: impl Into<u64>) {
153        self.push_arch_spec3(a, b, 0_u64);
154    }
155
156    pub fn push_arch_spec1(&mut self, a: impl Into<u64>) {
157        self.push_arch_spec2(a, 0_u64);
158    }
159}
160
161pub struct Bundle {
162    len: usize,
163    latency: u8,
164    insn: Box<[Insn]>,
165}
166
167impl Bundle {
168    pub fn empty() -> Self {
169        Self {
170            len: 0,
171            latency: 1,
172            insn: Box::new([]),
173        }
174    }
175
176    #[inline]
177    pub fn set_latency(&mut self, latency: u8) {
178        self.latency = latency;
179    }
180
181    #[inline]
182    pub fn latency(&self) -> usize {
183        self.latency as usize
184    }
185
186    pub fn as_slice(&self) -> &[Insn] {
187        &self.insn[..self.len]
188    }
189
190    pub fn clear(&mut self) {
191        self.len = 0;
192        self.latency = 1;
193    }
194
195    /// Take instruction to decode
196    pub fn peek(&mut self) -> &mut Insn {
197        if self.insn.len() <= self.len {
198            let mut vec = core::mem::take(&mut self.insn).into_vec();
199            vec.resize(self.len + 4, Insn::default());
200            self.insn = vec.into_boxed_slice();
201        }
202        let insn = &mut self.insn[self.len];
203        insn.clear();
204        insn
205    }
206
207    /// Previous peek was succesfull, advance to next instruction
208    pub fn next(&mut self) {
209        self.len += 1;
210    }
211
212    pub fn push_with<F>(&mut self, opcode: Opcode, mut f: F)
213    where
214        F: FnMut(&mut Insn),
215    {
216        let insn = self.peek();
217        insn.set_opcode(opcode);
218        f(insn);
219        self.next();
220    }
221
222    pub fn push(&mut self, opcode: Opcode) {
223        self.push_with(opcode, |_| ());
224    }
225}
226
227impl Deref for Bundle {
228    type Target = [Insn];
229
230    fn deref(&self) -> &Self::Target {
231        self.as_slice()
232    }
233}
234
235impl<'a> IntoIterator for &'a Bundle {
236    type Item = &'a Insn;
237    type IntoIter = core::slice::Iter<'a, Insn>;
238
239    fn into_iter(self) -> Self::IntoIter {
240        self.iter()
241    }
242}